2200 lines
104 KiB
Python
Executable File
2200 lines
104 KiB
Python
Executable File
#!/usr/bin/env python3
|
||
"""Dump TLV320DAC3100 registers and decode their current values.
|
||
|
||
This script uses register names and bitfield descriptions hard-coded from the
|
||
TLV320DAC3100 datasheet (Rev. C). It does not parse the PDF at runtime.
|
||
|
||
Behavior:
|
||
- reads implemented TLV320DAC3100 pages over I2C
|
||
- skips fully reserved registers
|
||
- decodes non-reserved bitfields where possible
|
||
- groups coefficient pairs and other multi-register values
|
||
"""
|
||
|
||
from __future__ import annotations
|
||
|
||
import argparse
|
||
import re
|
||
import shlex
|
||
import shutil
|
||
import subprocess
|
||
import sys
|
||
from typing import Iterable
|
||
|
||
DEFINED_PAGES = [0, 1, 3, 8, 9, 12, 13]
|
||
|
||
|
||
class CommandError(RuntimeError):
|
||
pass
|
||
|
||
|
||
SpecEntry = tuple[int, str] | tuple[int, int, str]
|
||
|
||
|
||
def parse_int(text: str) -> int:
|
||
return int(text, 0)
|
||
|
||
|
||
def parse_pages(spec: str) -> list[int]:
|
||
if spec.strip().lower() == "all":
|
||
return list(DEFINED_PAGES)
|
||
|
||
pages: list[int] = []
|
||
for part in spec.split(","):
|
||
part = part.strip()
|
||
if not part:
|
||
continue
|
||
page = parse_int(part)
|
||
if page not in DEFINED_PAGES:
|
||
valid = ", ".join(str(p) for p in DEFINED_PAGES)
|
||
raise argparse.ArgumentTypeError(
|
||
f"unsupported page {page}; valid pages: {valid}, or 'all'"
|
||
)
|
||
if page not in pages:
|
||
pages.append(page)
|
||
return pages
|
||
|
||
|
||
def add_range(target: dict[int, str], start: int, end: int, description: str) -> None:
|
||
for reg in range(start, end + 1):
|
||
target[reg] = description
|
||
|
||
|
||
def build_page_from_spec(spec: Iterable[SpecEntry], *, default: str = "Reserved") -> dict[int, str]:
|
||
page: dict[int, str] = {}
|
||
for entry in spec:
|
||
if len(entry) == 2:
|
||
reg, description = entry
|
||
page[reg] = description
|
||
else:
|
||
start, end, description = entry
|
||
add_range(page, start, end, description)
|
||
|
||
for reg in range(128):
|
||
page.setdefault(reg, default)
|
||
return page
|
||
|
||
|
||
def build_biquad_page(*, register_1_description: str) -> dict[int, str]:
|
||
page = {
|
||
0: "Page Control Register",
|
||
1: register_1_description,
|
||
64: "8 MSBs of 3D PGA gain for PRB_P23, PRB_P24 and PRB_P25",
|
||
65: "8 LSBs of 3D PGA gain for PRB_P23, PRB_P24 and PRB_P25",
|
||
}
|
||
|
||
biquad_regs = [
|
||
("N0", "15:8"),
|
||
("N0", "7:0"),
|
||
("N1", "15:8"),
|
||
("N1", "7:0"),
|
||
("N2", "15:8"),
|
||
("N2", "7:0"),
|
||
("D1", "15:8"),
|
||
("D1", "7:0"),
|
||
("D2", "15:8"),
|
||
("D2", "7:0"),
|
||
]
|
||
|
||
reg = 2
|
||
for biquad in "ABCDEF":
|
||
for coeff, bits in biquad_regs:
|
||
page[reg] = f"Coefficient {coeff}({bits}) for left DAC-programmable biquad {biquad}"
|
||
reg += 1
|
||
|
||
add_range(page, 62, 63, "Reserved")
|
||
|
||
reg = 66
|
||
for biquad in "ABCDEF":
|
||
for coeff, bits in biquad_regs:
|
||
page[reg] = f"Coefficient {coeff}({bits}) for right DAC-programmable biquad {biquad}"
|
||
reg += 1
|
||
|
||
add_range(page, 126, 127, "Reserved")
|
||
|
||
for reg in range(128):
|
||
page.setdefault(reg, "Reserved")
|
||
return page
|
||
|
||
|
||
def build_first_order_page() -> dict[int, str]:
|
||
page = {0: "Page Control Register", 1: "Reserved"}
|
||
|
||
six_regs = [
|
||
("N0", "15:8"),
|
||
("N0", "7:0"),
|
||
("N1", "15:8"),
|
||
("N1", "7:0"),
|
||
("D1", "15:8"),
|
||
("D1", "7:0"),
|
||
]
|
||
|
||
reg = 2
|
||
for coeff, bits in six_regs:
|
||
page[reg] = f"Coefficient {coeff}({bits}) for left DAC-programmable first-order IIR"
|
||
reg += 1
|
||
|
||
for coeff, bits in six_regs:
|
||
page[reg] = f"Coefficient {coeff}({bits}) for right DAC-programmable first-order IIR"
|
||
reg += 1
|
||
|
||
for coeff, bits in six_regs:
|
||
page[reg] = f"Coefficient {coeff}({bits}) for DRC first-order high-pass filter"
|
||
reg += 1
|
||
|
||
for coeff, bits in six_regs:
|
||
page[reg] = f"Coefficient {coeff}({bits}) for DRC first-order low-pass filter"
|
||
reg += 1
|
||
|
||
add_range(page, 26, 127, "Reserved")
|
||
return page
|
||
|
||
|
||
PAGE0_SPEC: list[SpecEntry] = [
|
||
(0, "Page Control Register"),
|
||
(1, "Software Reset"),
|
||
(2, "Reserved"),
|
||
(3, "OT FLAG"),
|
||
(4, "Clock-Gen Muxing (1)"),
|
||
(5, "PLL P and R Values"),
|
||
(6, "PLL J-Value"),
|
||
(7, "PLL D-Value MSB (1)"),
|
||
(8, "PLL D-Value LSB (1)"),
|
||
(9, 10, "Reserved"),
|
||
(11, "DAC NDAC_VAL"),
|
||
(12, "DAC MDAC_VAL"),
|
||
(13, "DAC DOSR_VAL MSB"),
|
||
(14, "DAC DOSR_VAL LSB (1) (2)"),
|
||
(15, 24, "Reserved"),
|
||
(25, "CLKOUT MUX"),
|
||
(26, "CLKOUT M_VAL"),
|
||
(27, "Codec Interface Control 1"),
|
||
(28, "Data-Slot Offset Programmability"),
|
||
(29, "Codec Interface Control 2"),
|
||
(30, "BCLK N_VAL"),
|
||
(31, "Codec Secondary Interface Control 1"),
|
||
(32, "Codec Secondary Interface Control 2"),
|
||
(33, "Codec Secondary Interface Control 3"),
|
||
(34, "I2C Bus Condition"),
|
||
(35, 36, "Reserved"),
|
||
(37, "DAC Flag Register"),
|
||
(38, "DAC Flag Register"),
|
||
(39, "Overflow Flags"),
|
||
(40, 43, "Reserved"),
|
||
(44, "DAC Interrupt Flags (Sticky Bits)"),
|
||
(45, "Reserved"),
|
||
(46, "Interrupt Flags—DAC"),
|
||
(47, "Reserved"),
|
||
(48, "INT1 Control Register"),
|
||
(49, "INT2 Control Register"),
|
||
(50, "Reserved"),
|
||
(51, "GPIO1 In/Out Pin Control"),
|
||
(52, "Reserved"),
|
||
(53, "Reserved"),
|
||
(54, "DIN (IN Pin) Control"),
|
||
(55, 59, "Reserved"),
|
||
(60, "DAC Processing Block Selection"),
|
||
(61, 62, "Reserved"),
|
||
(63, "DAC Data-Path Setup"),
|
||
(64, "DAC Volume Control"),
|
||
(65, "DAC Left Volume Control"),
|
||
(66, "DAC Right Volume Control"),
|
||
(67, "Headset Detection"),
|
||
(68, "DRC Control 1"),
|
||
(69, "DRC Control 2"),
|
||
(70, "DRC Control 3"),
|
||
(71, "Left Beep Generator (1)"),
|
||
(72, "Right Beep Generator"),
|
||
(73, "Beep Length MSB"),
|
||
(74, "Beep-Length Middle Bits"),
|
||
(75, "Beep Length LSB"),
|
||
(76, "Beep Sin(x) MSB"),
|
||
(77, "Beep Sin(x) LSB"),
|
||
(78, "Beep Cos(x) MSB"),
|
||
(79, "Beep Cos(x) LSB"),
|
||
(80, 115, "Reserved"),
|
||
(116, "VOL/MICDET-Pin SAR ADC — Volume Control"),
|
||
(117, "VOL/MICDET-Pin Gain"),
|
||
(118, 127, "Reserved"),
|
||
]
|
||
|
||
PAGE1_SPEC: list[SpecEntry] = [
|
||
(0, "Page Control Register"),
|
||
(1, 29, "Reserved"),
|
||
(30, "Headphone and Speaker Amplifier Error Control"),
|
||
(31, "Headphone Drivers"),
|
||
(32, "Class-D Speaker Amplifier"),
|
||
(33, "HP Output Drivers POP Removal Settings"),
|
||
(34, "Output Driver PGA Ramp-Down Period Control"),
|
||
(35, "DAC_L and DAC_R Output Mixer Routing"),
|
||
(36, "Left Analog Volume to HPL"),
|
||
(37, "Right Analog Volume to HPR"),
|
||
(38, "Left Analog Volume to SPK"),
|
||
(39, "Reserved"),
|
||
(40, "HPL Driver"),
|
||
(41, "HPR Driver"),
|
||
(42, "Class-D Speaker (SPK) Driver"),
|
||
(43, "Reserved"),
|
||
(44, "HP Driver Control"),
|
||
(45, "Reserved"),
|
||
(46, "MICBIAS"),
|
||
(47, 49, "Reserved / undocumented in Rev. C datasheet"),
|
||
(50, "Input CM Settings"),
|
||
(51, 127, "Reserved"),
|
||
]
|
||
|
||
PAGE3_SPEC: list[SpecEntry] = [
|
||
(0, "Page Control Register"),
|
||
(1, 15, "Reserved"),
|
||
(16, "Timer Clock MCLK Divider"),
|
||
(17, 127, "Reserved"),
|
||
]
|
||
|
||
REGISTER_MAP: dict[int, dict[int, str]] = {
|
||
0: build_page_from_spec(PAGE0_SPEC),
|
||
1: build_page_from_spec(PAGE1_SPEC),
|
||
3: build_page_from_spec(PAGE3_SPEC),
|
||
8: build_biquad_page(register_1_description="DAC Coefficient RAM Control"),
|
||
9: build_first_order_page(),
|
||
12: build_biquad_page(register_1_description="Reserved"),
|
||
13: build_first_order_page(),
|
||
}
|
||
|
||
REGISTER_FIELDS = {(0, 0): {'fields': [{'bits': 'D7–D0',
|
||
'lines': ['0000 0000: Page 0 selected',
|
||
'0000 0001: Page 1 selected',
|
||
'...',
|
||
'1111 1110: Page 254 selected',
|
||
'1111 1111: Page 255 selected'],
|
||
'reset': '0000 0000',
|
||
'rw': 'R/W'}]},
|
||
(0, 1): {'fields': [{'bits': 'D7–D1',
|
||
'lines': ['Reserved. Write only zeros to these bits.'],
|
||
'reset': '0000 000',
|
||
'rw': 'R/W'},
|
||
{'bits': 'D0',
|
||
'lines': ["0: Don't care", '1: Self-clearing software reset for control register'],
|
||
'reset': '0',
|
||
'rw': 'R/W'}]},
|
||
(0, 3): {'fields': [{'bits': 'D7–D2',
|
||
'lines': ['Reserved. Do not write to these bits.'],
|
||
'reset': 'XXXX XX',
|
||
'rw': 'R'},
|
||
{'bits': 'D1',
|
||
'lines': ['0: Overtemperature protection flag (active-low). Valid only if speaker amplifier is '
|
||
'powered up',
|
||
'1: Normal operation'],
|
||
'reset': '1',
|
||
'rw': 'R'},
|
||
{'bits': 'D0', 'lines': ['Reserved. Do not write to these bits.'], 'reset': 'X', 'rw': 'R/W'}]},
|
||
(0, 4): {'fields': [{'bits': 'D7–D4',
|
||
'lines': ['Reserved. Write only zeros to these bits.'],
|
||
'reset': '0000',
|
||
'rw': 'R/W'},
|
||
{'bits': 'D3–D2',
|
||
'lines': ['00: PLL_CLKIN = MCLK (device pin)',
|
||
'01: PLL_CLKIN = BCLK (device pin)',
|
||
'10: PLL_CLKIN = GPIO1 (device pin)',
|
||
'11: PLL_CLKIN = DIN (can be used for the system where DAC is not used)'],
|
||
'reset': '00',
|
||
'rw': 'R/W'},
|
||
{'bits': 'D1–D0',
|
||
'lines': ['00: CODEC_CLKIN = MCLK (device pin)',
|
||
'01: CODEC_CLKIN = BCLK (device pin)',
|
||
'10: CODEC_CLKIN = GPIO1 (device pin)',
|
||
'11: CODEC_CLKIN = PLL_CLK (generated on-chip)',
|
||
'(1) See Section 6.3.11 for more details on clock generation mutiplexing and '
|
||
'dividers.'],
|
||
'reset': '00',
|
||
'rw': 'R/W'}]},
|
||
(0, 5): {'fields': [{'bits': 'D7',
|
||
'lines': ['0: PLL is powered down.', '1: PLL is powered up.'],
|
||
'reset': '0',
|
||
'rw': 'R/W'},
|
||
{'bits': 'D6–D4',
|
||
'lines': ['000: PLL divider P = 8',
|
||
'001: PLL divider P = 1',
|
||
'010: PLL divider P = 2',
|
||
'...',
|
||
'110: PLL divider P = 6',
|
||
'111: PLL divider P = 7'],
|
||
'reset': '001',
|
||
'rw': 'R/W'},
|
||
{'bits': 'D3–D0',
|
||
'lines': ['0000: PLL multiplier R = 16',
|
||
'0001: PLL multiplier R = 1',
|
||
'0010: PLL multiplier R = 2',
|
||
'...',
|
||
'1110: PLL multiplier R = 14',
|
||
'1111: PLL multiplier R = 15'],
|
||
'reset': '0001',
|
||
'rw': 'R/W'}]},
|
||
(0, 6): {'fields': [{'bits': 'D7–D6',
|
||
'lines': ['Reserved. Write only zeros to these bits.'],
|
||
'reset': '00',
|
||
'rw': 'R/W'},
|
||
{'bits': 'D5–D0',
|
||
'lines': ['00 0000: Do not use (reserved)',
|
||
'00 0001: PLL multiplier J = 1',
|
||
'00 0010: PLL multiplier J = 2',
|
||
'...',
|
||
'11 1110: PLL multiplier J = 62',
|
||
'11 1111: PLL multiplier J = 63'],
|
||
'reset': '00 0100',
|
||
'rw': 'R/W'}]},
|
||
(0, 7): {'fields': [{'bits': 'D7–D6',
|
||
'lines': ['Reserved. Write only zeros to these bits.'],
|
||
'reset': '00',
|
||
'rw': 'R/W'},
|
||
{'bits': 'D5–D0',
|
||
'lines': ['PLL fractional multiplier D-value MSB bits D[13:8]',
|
||
'(1) Note that this register is updated only when Page 0 / Register 8 is written '
|
||
'immediately after Page 0 / Register 7.'],
|
||
'reset': '00 0000',
|
||
'rw': 'R/W'}]},
|
||
(0, 8): {'fields': [{'bits': 'D7–D0',
|
||
'lines': ['PLL fractional multiplier D-value LSB bits D[7:0]',
|
||
'(1) Note that Page 0 / Register 8 must be written immediately after Page 0 / Register '
|
||
'7.'],
|
||
'reset': '0000 0000',
|
||
'rw': 'R/W'}]},
|
||
(0, 11): {'fields': [{'bits': 'D7',
|
||
'lines': ['0: DAC NDAC divider is powered down.', '1: DAC NDAC divider is powered up.'],
|
||
'reset': '0',
|
||
'rw': 'R/W'},
|
||
{'bits': 'D6–D0',
|
||
'lines': ['000 0000: DAC NDAC divider = 128',
|
||
'000 0001: DAC NDAC divider = 1',
|
||
'000 0010: DAC NDAC divider = 2',
|
||
'...',
|
||
'111 1110: DAC NDAC divider = 126',
|
||
'111 1111: DAC NDAC divider = 127'],
|
||
'reset': '000 0001',
|
||
'rw': 'R/W'}]},
|
||
(0, 12): {'fields': [{'bits': 'D7',
|
||
'lines': ['0: DAC MDAC divider is powered down.', '1: DAC MDAC divider is powered up.'],
|
||
'reset': '0',
|
||
'rw': 'R/W'},
|
||
{'bits': 'D6–D0',
|
||
'lines': ['000 0000: DAC MDAC divider = 128',
|
||
'000 0001: DAC MDAC divider = 1',
|
||
'000 0010: DAC MDAC divider = 2',
|
||
'...',
|
||
'111 1110: DAC MDAC divider = 126',
|
||
'111 1111: DAC MDAC divider = 127'],
|
||
'reset': '000 0001',
|
||
'rw': 'R/W'}]},
|
||
(0, 13): {'fields': [{'bits': 'D7–D2', 'lines': ['Reserved'], 'reset': '0000 00', 'rw': 'R/W'},
|
||
{'bits': 'D1–D0', 'lines': ['DAC OSR value DOSR(9:8)'], 'reset': '00', 'rw': 'R/W'}]},
|
||
(0, 14): {'fields': [{'bits': 'D7–D0',
|
||
'lines': ['DAC OSR Value DOSR (7:0)',
|
||
'0000 0000: DAC OSR (7:0) = 1024 (MSB page 0 / register 13, bits D1–D0 = 00)',
|
||
'0000 0001: Reserved',
|
||
'0000 0010: DAC OSR (7:0) = 2 (MSB page 0 / register 13, bits D1–D0 = 00)',
|
||
'...',
|
||
'1111 1110: DAC OSR (7:0) = 1022 (MSB page 0 / register 13, bits D1–D0 = 11)',
|
||
'1111 1111: DAC OSR (7:0) = Reserved. Do not Use',
|
||
'(1) DAC OSR must be an integral multiple of the interpolation in the DAC miniDSP '
|
||
'engine (specified in register 16). When using PRB',
|
||
'modes, interpolation ratio is 8 while using Filter-A, 4 while using Filter-B and 2 '
|
||
'while using Filter-C.',
|
||
'(2) Note that Page 0 / Register 14 must be written to immediately after writing to '
|
||
'Page 0 / Register 13.'],
|
||
'reset': '1000 0000',
|
||
'rw': 'R/W'}]},
|
||
(0, 25): {'fields': [{'bits': 'D7–D3', 'lines': ['Reserved'], 'reset': '0000 0', 'rw': 'R/W'},
|
||
{'bits': 'D2–D0',
|
||
'lines': ['000: CDIV_CLKIN = MCLK (device pin)',
|
||
'001: CDIV_CLKIN = BCLK (device pin)',
|
||
'010: CDIV_CLKIN = DIN (can be used for the systems where DAC is not required)',
|
||
'011: CDIV_CLKIN = PLL_CLK (generated on-chip)',
|
||
'100: CDIV_CLKIN = DAC_CLK (DAC DSP clock - generated on-chip)',
|
||
'101: CDIV_CLKIN = DAC_MOD_CLK (generated on-chip)',
|
||
'110: Reserved',
|
||
'111: Reserved'],
|
||
'reset': '000',
|
||
'rw': 'R/W'}]},
|
||
(0, 26): {'fields': [{'bits': 'D7',
|
||
'lines': ['0: CLKOUT M divider is powered down.', '1: CLKOUT M divider is powered up.'],
|
||
'reset': '0',
|
||
'rw': 'R/W'},
|
||
{'bits': 'D6–D0',
|
||
'lines': ['000 0000: CLKOUT divider M = 128',
|
||
'000 0001: CLKOUT divider M = 1',
|
||
'000 0010: CLKOUT divider M = 2',
|
||
'...',
|
||
'111 1110: CLKOUT divider M = 126',
|
||
'111 1111: CLKOUT divider M = 127'],
|
||
'reset': '000 0001',
|
||
'rw': 'R/W'}]},
|
||
(0, 27): {'fields': [{'bits': 'D7–D6',
|
||
'lines': ['00: Codec interface = I S',
|
||
'01: Codec Interface = DSP',
|
||
'10: Codec interface = RJF',
|
||
'11: Codec interface = LJF'],
|
||
'reset': '00',
|
||
'rw': 'R/W'},
|
||
{'bits': 'D5–D4',
|
||
'lines': ['00: Codec interface word length = 16 bits',
|
||
'01: Codec interface word length = 20 bits',
|
||
'10: Codec interface word length = 24 bits',
|
||
'11: Codec interface word length = 32 bits'],
|
||
'reset': '00',
|
||
'rw': 'R/W'},
|
||
{'bits': 'D3', 'lines': ['0: BCLK is input', '1: BCLK is output'], 'reset': '0', 'rw': 'R/W'},
|
||
{'bits': 'D2', 'lines': ['0: WCLK is input', '1: WCLK is output'], 'reset': '0', 'rw': 'R/W'},
|
||
{'bits': 'D1–D0', 'lines': ['Reserved'], 'reset': '0', 'rw': 'R/W'}]},
|
||
(0, 28): {'fields': [{'bits': 'D7–D0',
|
||
'lines': ['Offset (Measured With Respect to WCLK Rising Edge in DSP Mode)',
|
||
'0000 0000: Offset = 0 BCLKs',
|
||
'0000 0001: Offset = 1 BCLK',
|
||
'0000 0010: Offset = 2 BCLKs',
|
||
'...',
|
||
'1111 1110: Offset = 254 BCLKs',
|
||
'1111 1111: Offset = 255 BCLKs'],
|
||
'reset': '0000 0000',
|
||
'rw': 'R/W'}]},
|
||
(0, 29): {'fields': [{'bits': 'D7–D4', 'lines': ['Reserved'], 'reset': '0000', 'rw': 'R/W'},
|
||
{'bits': 'D3',
|
||
'lines': ['0: BCLK is not inverted (valid for both primary and secondary BCLK)',
|
||
'1: BCLK is inverted (valid for both primary and secondary BCLK)'],
|
||
'reset': '0',
|
||
'rw': 'R/W'},
|
||
{'bits': 'D2',
|
||
'lines': ['BCLK and WCLK Active Even With Codec Powered Down (Valid for Both Primary and '
|
||
'Secondary BCLK)',
|
||
'0: Disabled',
|
||
'1: Enabled'],
|
||
'reset': '0',
|
||
'rw': 'R/W'},
|
||
{'bits': 'D1–D0',
|
||
'lines': ['00: BDIV_CLKIN = DAC_CLK (generated on-chip)',
|
||
'01: BDIV_CLKIN = DAC_MOD_CLK (generated on-chip)',
|
||
'10: Reserved',
|
||
'11: Reserved'],
|
||
'reset': '00',
|
||
'rw': 'R/W'}]},
|
||
(0, 30): {'fields': [{'bits': 'D7',
|
||
'lines': ['0: BCLK N-divider is powered down.', '1: BCLK N-divider is powered up.'],
|
||
'reset': '0',
|
||
'rw': 'R/W'},
|
||
{'bits': 'D6–D0',
|
||
'lines': ['000 0000: BCLK divider N = 128',
|
||
'000 0001: BCLK divider N = 1',
|
||
'000 0010: BCLK divider N = 2',
|
||
'...',
|
||
'111 1110: BCLK divider N = 126',
|
||
'111 1111: BCLK divider N = 127'],
|
||
'reset': '000 0001',
|
||
'rw': 'R/W'}]},
|
||
(0, 31): {'fields': [{'bits': 'D7–D5',
|
||
'lines': ['000: Secondary BCLK is obtained from GPIO1 pin.',
|
||
'001: Secondary BCLK is not obtained from the GPIO1 pin.',
|
||
'010: Reserved.',
|
||
'011: Reserved.',
|
||
'100: Reserved',
|
||
'101: Reserved.',
|
||
'110: Reserved.',
|
||
'111: Reserved'],
|
||
'reset': '000',
|
||
'rw': 'R/W'},
|
||
{'bits': 'D4–D2',
|
||
'lines': ['000: Secondary WCLK is obtained from GPIO1 pin.',
|
||
'001: Secondary WCLK is not obtained from the GPIO1 pin.',
|
||
'010: Reserved.',
|
||
'011: Reserved.',
|
||
'100: Reserved',
|
||
'101: Reserved.',
|
||
'110: Reserved.',
|
||
'111: Reserved'],
|
||
'reset': '000',
|
||
'rw': 'R/W'},
|
||
{'bits': 'D1–D0',
|
||
'lines': ['00: Secondary DIN is obtained from the GPIO1 pin.',
|
||
'01: Secondary DIN is not obtained from the GPIO1 pin.',
|
||
'10: Reserved.',
|
||
'11: Reserved'],
|
||
'reset': '00',
|
||
'rw': 'R/W'}]},
|
||
(0, 32): {'fields': [{'bits': 'D7–D4', 'lines': ['Reserved'], 'reset': '0000', 'rw': 'R/W'},
|
||
{'bits': 'D3',
|
||
'lines': ['0: Primary BCLK is fed to codec serial-interface and ClockGen blocks.',
|
||
'1: Secondary BCLK is fed to codec serial-interface and ClockGen blocks.'],
|
||
'reset': '0',
|
||
'rw': 'R/W'},
|
||
{'bits': 'D2',
|
||
'lines': ['0: Primary WCLK is fed to codec serial-interface block.',
|
||
'1: Secondary WCLK is fed to codec serial-interface block.'],
|
||
'reset': '0',
|
||
'rw': 'R/W'},
|
||
{'bits': 'D1', 'lines': ['Reserved.'], 'reset': '0', 'rw': 'R/W'},
|
||
{'bits': 'D0',
|
||
'lines': ['0: Primary DIN is fed to codec serial-interface block.',
|
||
'1: Secondary DIN is fed to codec serial-interface block.'],
|
||
'reset': '0',
|
||
'rw': 'R/W'}]},
|
||
(0, 33): {'fields': [{'bits': 'D7',
|
||
'lines': ['0: Primary BCLK output = internally generated BCLK clock',
|
||
'1: Primary BCLK output = secondary BCLK'],
|
||
'reset': '0',
|
||
'rw': 'R/W'},
|
||
{'bits': 'D6',
|
||
'lines': ['0: Secondary BCLK output = primary BCLK',
|
||
'1: Secondary BCLK output = internally generated BCLK clock'],
|
||
'reset': '0',
|
||
'rw': 'R/W'},
|
||
{'bits': 'D5–D4',
|
||
'lines': ['00: Primary WCLK output = internally generated DAC_fS',
|
||
'01: Reserved',
|
||
'10: Primary WCLK output = secondary WCLK',
|
||
'11: Reserved'],
|
||
'reset': '00',
|
||
'rw': 'R/W'},
|
||
{'bits': 'D3–D2',
|
||
'lines': ['00: Secondary WCLK output = primary WCLK',
|
||
'01: Secondary WCLK output = internally generated DAC_fS clock',
|
||
'10: Reserved',
|
||
'11: Reserved'],
|
||
'reset': '00',
|
||
'rw': 'R/W'},
|
||
{'bits': 'D1–D0', 'lines': ['Reserved'], 'reset': '0', 'rw': 'R/W'}]},
|
||
(0, 34): {'fields': [{'bits': 'D7–D6',
|
||
'lines': ['Reserved. Write only the reset value to these bits.'],
|
||
'reset': '00',
|
||
'rw': 'R/W'},
|
||
{'bits': 'D5',
|
||
'lines': ['0: I2C general-call address is ignored.',
|
||
'1: Device accepts I2C general-call address.'],
|
||
'reset': '0',
|
||
'rw': 'R/W'},
|
||
{'bits': 'D4–D0',
|
||
'lines': ['Reserved. Write only zeros to these bits.'],
|
||
'reset': '0 0000',
|
||
'rw': 'R/W'}]},
|
||
(0, 37): {'fields': [{'bits': 'D7',
|
||
'lines': ['0: Left-channel DAC powered down', '1: Left-channel DAC powered up'],
|
||
'reset': '0',
|
||
'rw': 'R'},
|
||
{'bits': 'D6', 'lines': ['Reserved.'], 'reset': 'X', 'rw': 'R'},
|
||
{'bits': 'D5',
|
||
'lines': ['0: HPL driver powered down', '1: HPL driver powered up'],
|
||
'reset': '0',
|
||
'rw': 'R'},
|
||
{'bits': 'D4',
|
||
'lines': ['0: Left-channel class-D driver powered down',
|
||
'1: Left-channel class-D driver powered up'],
|
||
'reset': '0',
|
||
'rw': 'R'},
|
||
{'bits': 'D3',
|
||
'lines': ['0: Right-channel DAC powered down', '1: Right-channel DAC powered up'],
|
||
'reset': '0',
|
||
'rw': 'R'},
|
||
{'bits': 'D2', 'lines': ['Reserved.'], 'reset': 'X', 'rw': 'R'},
|
||
{'bits': 'D1',
|
||
'lines': ['0: HPR driver powered down', '1: HPR driver powered up'],
|
||
'reset': '0',
|
||
'rw': 'R'},
|
||
{'bits': 'D0',
|
||
'lines': ['0: Right-channel class-D driver powered down',
|
||
'1: Right-channel class-D driver powered up'],
|
||
'reset': '0',
|
||
'rw': 'R'}]},
|
||
(0, 38): {'fields': [{'bits': 'D7–D5', 'lines': ['Reserved.'], 'reset': 'XXX', 'rw': 'R'},
|
||
{'bits': 'D4',
|
||
'lines': ['0: Left-channel DAC PGA applied gain ≠ programmed gain',
|
||
'1: Left-channel DAC PGA applied gain = programmed gain'],
|
||
'reset': '0',
|
||
'rw': 'R'},
|
||
{'bits': 'D3–D1', 'lines': ['Reserved.'], 'reset': 'XXX', 'rw': 'R'},
|
||
{'bits': 'D0',
|
||
'lines': ['0: Right-channel DAC PGA applied gain ≠ programmed gain',
|
||
'1: Right-channel DAC PGA applied gain = programmed gain'],
|
||
'reset': '0',
|
||
'rw': 'R'}]},
|
||
(0, 39): {'fields': [{'bits': 'D7 (1)',
|
||
'lines': ['Left-Channel DAC Overflow Flag',
|
||
'0: Overflow has not occurred.',
|
||
'1: Overflow has occurred.'],
|
||
'reset': '0',
|
||
'rw': 'R'},
|
||
{'bits': 'D6 (1)',
|
||
'lines': ['Right-Channel DAC Overflow Flag',
|
||
'0: Overflow has not occurred.',
|
||
'1: Overflow has occurred.'],
|
||
'reset': '0',
|
||
'rw': 'R'},
|
||
{'bits': 'D5 (1)',
|
||
'lines': ['DAC Barrel Shifter Output Overflow Flag',
|
||
'0: Overflow has not occurred.',
|
||
'1: Overflow has occurred.'],
|
||
'reset': '0',
|
||
'rw': 'R'},
|
||
{'bits': 'D4–D0',
|
||
'lines': ['Reserved.',
|
||
'(1) Sticky flag bIt. These is a read-only bit. This bit is automatically cleared '
|
||
'once it is read and is set only if the source trigger occurs again.'],
|
||
'reset': '0',
|
||
'rw': 'R'}]},
|
||
(0, 44): {'fields': [{'bits': 'D7 (1)',
|
||
'lines': ['0: No short circuit is detected at HPL / left class-D driver.',
|
||
'1: Short circuit is detected at HPL / left class-D driver.'],
|
||
'reset': '0',
|
||
'rw': 'R'},
|
||
{'bits': 'D6 (1)',
|
||
'lines': ['0: No short circuit is detected at HPR / right class-D driver.',
|
||
'1: Short circuit is detected at HPR / right class-D driver.'],
|
||
'reset': '0',
|
||
'rw': 'R'},
|
||
{'bits': 'D5 (1)',
|
||
'lines': ['0: No headset button pressed.', '1: Headset button pressed.'],
|
||
'reset': 'X',
|
||
'rw': 'R'},
|
||
{'bits': 'D4 (1)',
|
||
'lines': ['0: No headset insertion or removal is detected.',
|
||
'1: Headset insertion or removal is detected.'],
|
||
'reset': 'X',
|
||
'rw': 'R'},
|
||
{'bits': 'D3 (1)',
|
||
'lines': ['0: Left DAC signal power is less than or equal to the signal threshold of DRC.',
|
||
'1: Left DAC signal power is above the signal threshold of DRC.'],
|
||
'reset': '0',
|
||
'rw': 'R'},
|
||
{'bits': 'D2 (1)',
|
||
'lines': ['0: Right DAC signal power is less than or equal to the signal threshold of DRC.',
|
||
'1: Right DAC signal power is above the signal threshold of DRC.'],
|
||
'reset': '0',
|
||
'rw': 'R'},
|
||
{'bits': 'D1–D0',
|
||
'lines': ['Reserved.',
|
||
'(1) Sticky flag bIt. These is a read-only bit. This bit is automatically cleared '
|
||
'once it is read and is set only if the source trigger occurs again.'],
|
||
'reset': '0',
|
||
'rw': 'R'}]},
|
||
(0, 46): {'fields': [{'bits': 'D7',
|
||
'lines': ['0: No short circuit detected at HPL / left class-D driver.',
|
||
'1: Short circuit detected at HPL / left class-D driver.'],
|
||
'reset': '0',
|
||
'rw': 'R'},
|
||
{'bits': 'D6',
|
||
'lines': ['0: No short circuit detected at HPR / right class-D driver',
|
||
'1: Short circuit detected at HPR / right class-D driver'],
|
||
'reset': '0',
|
||
'rw': 'R'},
|
||
{'bits': 'D5',
|
||
'lines': ['0: No headset button pressed.', '1: Headset button pressed.'],
|
||
'reset': 'X',
|
||
'rw': 'R'},
|
||
{'bits': 'D4',
|
||
'lines': ['0: Headset removal detected.', '1: Headset insertion detected.'],
|
||
'reset': 'X',
|
||
'rw': 'R'},
|
||
{'bits': 'D3',
|
||
'lines': ['0: Left DAC signal power is less than or equal to signal threshold of DRC.',
|
||
'1: Left DAC signal power is greater than signal threshold of DRC.'],
|
||
'reset': '0',
|
||
'rw': 'R'},
|
||
{'bits': 'D2',
|
||
'lines': ['0: Right DAC signal power is less than or equal to signal threshold of DRC.',
|
||
'1: Right DAC signal power is greater than signal threshold of DRC.'],
|
||
'reset': '0',
|
||
'rw': 'R'},
|
||
{'bits': 'D1–D0', 'lines': ['Reserved.'], 'reset': '00', 'rw': 'R'}]},
|
||
(0, 48): {'fields': [{'bits': 'D7',
|
||
'lines': ['0: Headset-insertion detect interrupt is not used in the generation of INT1 '
|
||
'interrupt.',
|
||
'1: Headset-insertion detect interrupt is used in the generation of INT1 interrupt.'],
|
||
'reset': '0',
|
||
'rw': 'R/W'},
|
||
{'bits': 'D6',
|
||
'lines': ['0: Button-press detect interrupt is not used in the generation of INT1 interrupt.',
|
||
'1: Button-press detect interrupt is used in the generation of INT1 interrupt.'],
|
||
'reset': '0',
|
||
'rw': 'R/W'},
|
||
{'bits': 'D5',
|
||
'lines': ['0: DAC DRC signal-power interrupt is not used in the generation of INT1 interrupt.',
|
||
'1: DAC DRC signal-power interrupt is used in the generation of INT1 interrupt.'],
|
||
'reset': '0',
|
||
'rw': 'R/W'},
|
||
{'bits': 'D4', 'lines': ['Reserved'], 'reset': '0', 'rw': 'R/W'},
|
||
{'bits': 'D3',
|
||
'lines': ['0: Short-circuit interrupt is not used in the generation of INT1 interrupt.',
|
||
'1: Short-circuit interrupt is used in the generation of INT1 interrupt.'],
|
||
'reset': '0',
|
||
'rw': 'R/W'},
|
||
{'bits': 'D2',
|
||
'lines': ['0: DAC data overflow does not result in an INT1 interrupt.',
|
||
'1: DAC data overflow results in an INT1 interrupt.'],
|
||
'reset': '0',
|
||
'rw': 'R/W'},
|
||
{'bits': 'D1', 'lines': ['Reserved'], 'reset': '0', 'rw': 'R/W'},
|
||
{'bits': 'D0',
|
||
'lines': ['0: INT1 is only one pulse (active-high) of typical 2-ms duration.',
|
||
'1: INT1 is multiple pulses (active-high) of typical 2-ms duration and 4-ms period, '
|
||
'until flag register 44 is',
|
||
'read by the user.'],
|
||
'reset': '0',
|
||
'rw': 'R/W'}]},
|
||
(0, 49): {'fields': [{'bits': 'D7',
|
||
'lines': ['0: Headset-insertion detect interrupt is not used in the generation of INT2 '
|
||
'interrupt.',
|
||
'1: Headset-insertion detect interrupt is used in the generation of INT2 interrupt.'],
|
||
'reset': '0',
|
||
'rw': 'R/W'},
|
||
{'bits': 'D6',
|
||
'lines': ['0: Button-press detect interrupt is not used in the generation of INT2 interrupt.',
|
||
'1: Button-press detect interrupt is used in the generation of INT2 interrupt.'],
|
||
'reset': '0',
|
||
'rw': 'R/W'},
|
||
{'bits': 'D5',
|
||
'lines': ['0: DAC DRC signal-power interrupt is not used in the generation of INT2 interrupt.',
|
||
'1: DAC DRC signal-power interrupt is used in the generation of INT2 interrupt.'],
|
||
'reset': '0',
|
||
'rw': 'R/W'},
|
||
{'bits': 'D4', 'lines': ['Reserved'], 'reset': '0', 'rw': 'R/W'},
|
||
{'bits': 'D3',
|
||
'lines': ['0: Short-circuit interrupt is not used in the generation of INT2 interrupt.',
|
||
'1: Short-circuit interrupt is used in the generation of INT2 interrupt.'],
|
||
'reset': '0',
|
||
'rw': 'R/W'},
|
||
{'bits': 'D2',
|
||
'lines': ['0: DAC data overflow does not result in an INT2 interrupt.',
|
||
'1: DAC data overflow results in an INT2 interrupt.'],
|
||
'reset': '0',
|
||
'rw': 'R/W'},
|
||
{'bits': 'D1', 'lines': ['Reserved'], 'reset': '0', 'rw': 'R/W'},
|
||
{'bits': 'D0',
|
||
'lines': ['0: INT2 is only one pulse (active-high) of typical 2-ms duration.',
|
||
'1: INT2 is multiple pulses (active-high) of typical 2-ms duration and 4-ms period, '
|
||
'until flag register 44is',
|
||
'read by the user.'],
|
||
'reset': '0',
|
||
'rw': 'R/W'}]},
|
||
(0, 51): {'fields': [{'bits': 'D7–D6',
|
||
'lines': ['Reserved. Do not write any value other than reset value.'],
|
||
'reset': 'XX',
|
||
'rw': 'R/W'},
|
||
{'bits': 'D5–D2',
|
||
'lines': ['0000: GPIO1 disabled (input and output buffers powered down)',
|
||
'0001: GPIO1 is in input mode (can be used as secondary BCLK input, secondary WCLK '
|
||
'input,',
|
||
'secondary DIN input, or in ClockGen block).',
|
||
'0010: GPIO1 is used as general-purpose input (GPI).',
|
||
'0011: GPIO1 output = general-purpose output',
|
||
'0100: GPIO1 output = CLKOUT output',
|
||
'0101: GPIO1 output = INT1 output',
|
||
'0110: GPIO1 output = INT2 output',
|
||
'0111: Reserved',
|
||
'1000: GPIO1 output = secondary BCLK output for codec interface',
|
||
'1001: GPIO1 output = secondary WCLK output for codec interface',
|
||
'1010: Reserved',
|
||
'1011: Reserved',
|
||
'1100: Reserved',
|
||
'1101: Reserved',
|
||
'1110: Reserved',
|
||
'1111: Reserved'],
|
||
'reset': '0000',
|
||
'rw': 'R/W'},
|
||
{'bits': 'D1', 'lines': ['GPIO1 input buffer value'], 'reset': 'X', 'rw': 'R'},
|
||
{'bits': 'D0',
|
||
'lines': ['0: GPIO1 general-purpose output value = 0',
|
||
'1: GPIO1 general-purpose output value = 1'],
|
||
'reset': '0',
|
||
'rw': 'R/W'}]},
|
||
(0, 54): {'fields': [{'bits': 'D7–D3', 'lines': ['Reserved'], 'reset': '0000 0', 'rw': 'R/W'},
|
||
{'bits': 'D2–D1',
|
||
'lines': ['00: DIN disabled (input buffer powered down)',
|
||
'01: DIN enabled (can be used as DIN for codec interface or into ClockGen block)',
|
||
'10: DIN is used as general-purpose input (GPI)',
|
||
'11: Reserved'],
|
||
'reset': '01',
|
||
'rw': 'R/W'},
|
||
{'bits': 'D0', 'lines': ['DIN input-buffer value'], 'reset': 'X', 'rw': 'R'}]},
|
||
(0, 60): {'fields': [{'bits': 'D7–D5', 'lines': ['Reserved. Write only default value.'], 'reset': '000', 'rw': 'R/W'},
|
||
{'bits': 'D4–D0',
|
||
'lines': ['0 0000: Reserved. Do not use.',
|
||
'0 0001: DAC signal-processing block PRB_P1',
|
||
'0 0010: DAC signal-processing block PRB_P2',
|
||
'0 0011: DAC signal-processing block PRB_P3',
|
||
'0 0100: DAC signal-processing block PRB_P4',
|
||
'...',
|
||
'1 1000: DAC signal-processing block PRB_P24',
|
||
'1 1001: DAC signal-processing block PRB_P25',
|
||
'1 1010–1 1111: Reserved. Do not use.'],
|
||
'reset': '00 0001',
|
||
'rw': 'R/W'}]},
|
||
(0, 63): {'fields': [{'bits': 'D7',
|
||
'lines': ['0: Left-channel DAC is powered down.', '1: Left-channel DAC is powered up.'],
|
||
'reset': '0',
|
||
'rw': 'R/W'},
|
||
{'bits': 'D6',
|
||
'lines': ['0: Right-channel DAC is powered down.', '1: Right-channel DAC is powered up.'],
|
||
'reset': '0',
|
||
'rw': 'R/W'},
|
||
{'bits': 'D5–D4',
|
||
'lines': ['00: Left-channel DAC data path = off',
|
||
'01: Left-channel DAC data path = left data',
|
||
'10: Left-channel DAC data path = right data',
|
||
'11: Left-channel DAC data path = left-channel and right-channel data [(L + R) / 2]'],
|
||
'reset': '01',
|
||
'rw': 'R/W'},
|
||
{'bits': 'D3–D2',
|
||
'lines': ['00: Right-channel DAC data path = off',
|
||
'01: Right-channel DAC data path = right data',
|
||
'10: Right-channel DAC data path = left data',
|
||
'11: Right-channel DAC data path = left-channel and right-channel data [(L + R) / 2]'],
|
||
'reset': '01',
|
||
'rw': 'R/W'},
|
||
{'bits': 'D1–D0',
|
||
'lines': ['00: DAC-channel volume-control soft-stepping is enabled for one step per sample '
|
||
'period.',
|
||
'01: DAC-channel volume-control soft-stepping is enabled for one step per two sample '
|
||
'periods.',
|
||
'10: DAC-channel volume-control soft-stepping is disabled.',
|
||
'11: Reserved. Do not write this sequence to these bits.'],
|
||
'reset': '00',
|
||
'rw': 'R/W'}]},
|
||
(0, 64): {'fields': [{'bits': 'D7–D4',
|
||
'lines': ['Reserved. Write only zeros to these bits.'],
|
||
'reset': '0000',
|
||
'rw': 'R/W'},
|
||
{'bits': 'D3',
|
||
'lines': ['0: Left-channel DAC not muted', '1: Left-channel DAC muted'],
|
||
'reset': '1',
|
||
'rw': 'R/W'},
|
||
{'bits': 'D2',
|
||
'lines': ['0: Right-channel DAC not muted', '1: Right-channel DAC muted'],
|
||
'reset': '1',
|
||
'rw': 'R/W'},
|
||
{'bits': 'D1–D0',
|
||
'lines': ['00: Left and right channels have independent volume control. (1)',
|
||
'01: Left-channel volume control Is the programmed value of right-channel volume '
|
||
'control.',
|
||
'10: Right-channel volume control is the programmed value of left-channel volume '
|
||
'control.',
|
||
'11: Same as 00',
|
||
'(1) When DRC is enabled, left and right channel volume controls are always '
|
||
'independent. Program bits D1–D0 to 00.'],
|
||
'reset': '00',
|
||
'rw': 'R/W'}]},
|
||
(0, 65): {'fields': [{'bits': 'D7–D0',
|
||
'lines': ['Left DAC Channel Digital Volume Control Setting',
|
||
'0111 1111–0011 0001: Reserved. Do not use',
|
||
'0011 0000: Digital volume control = 24 dB',
|
||
'0010 1111: Digital volume control = 23.5 dB',
|
||
'0010 1110: Digital volume control = 23 dB',
|
||
'...',
|
||
'0000 0001: Digital volume control = 0.5 dB',
|
||
'0000 0000: Digital volume control = 0 dB',
|
||
'1111 1111: Digital volume control = –0.5 dB',
|
||
'...',
|
||
'1000 0010: Digital volume control = –63 dB',
|
||
'1000 0001: Digital volume control = –63.5 dB',
|
||
'1000 0000: Reserved.'],
|
||
'reset': '0000 0000',
|
||
'rw': 'R/W'}]},
|
||
(0, 66): {'fields': [{'bits': 'D7–D0',
|
||
'lines': ['Right DAC Channel Digital Volume Control Setting',
|
||
'0111 1111–0011 0001: Reserved. Do not use',
|
||
'0011 0000: Digital volume control = 24 dB',
|
||
'0010 1111: Digital volume control = 23.5 dB',
|
||
'0010 1110: Digital volume control = 23 dB',
|
||
'...',
|
||
'0000 0001: Digital volume control = 0.5 dB',
|
||
'0000 0000: Digital volume control = 0 dB',
|
||
'1111 1111: Digital volume control = –0.5 dB',
|
||
'...',
|
||
'1000 0010: Digital volume control = –63 dB',
|
||
'1000 0001: Digital volume control = –63.5 dB',
|
||
'1000 0000: Reserved.'],
|
||
'reset': '0000 0000',
|
||
'rw': 'R/W'}]},
|
||
(0, 67): {'fields': [{'bits': 'D7',
|
||
'lines': ['0: Headset detection disabled', '1: Headset detection enabled'],
|
||
'reset': '0',
|
||
'rw': 'R/W'},
|
||
{'bits': 'D6–D5',
|
||
'lines': ['00: No headset detected',
|
||
'01: Headset without microphone is detected',
|
||
'10: Reserved',
|
||
'11: Headset with microphone is detected'],
|
||
'reset': 'XX',
|
||
'rw': 'R'},
|
||
{'bits': 'D4–D2',
|
||
'lines': ['Debounce Programming for Glitch Rejection During Headset Detection (1)',
|
||
'000: 16 ms (sampled with 2-ms clock)',
|
||
'001: 32 ms (sampled with 4-ms clock)',
|
||
'010: 64 ms (sampled with 8-ms clock)',
|
||
'011: 128 ms (sampled with 16-ms clock)',
|
||
'100: 256 ms (sampled with 32-ms clock)',
|
||
'101: 512 ms (sampled with 64-ms clock)',
|
||
'110: Reserved',
|
||
'111: Reserved'],
|
||
'reset': '000',
|
||
'rw': 'R/W'},
|
||
{'bits': 'D1–D0',
|
||
'lines': ['Debounce programming for glitch rejection during headset button-press detection',
|
||
'00: 0 ms',
|
||
'01: 8 ms (sampled with 1-ms clock)',
|
||
'10: 16 ms (sampled with 2-ms clock)',
|
||
'11: 32 ms (sampled with 4-ms clock)',
|
||
'(1) Note that these times are generated using the 1 MHz reference clock which is '
|
||
'defined in Page 3 / Register 16.'],
|
||
'reset': '00',
|
||
'rw': 'R/W'}]},
|
||
(0, 68): {'fields': [{'bits': 'D7',
|
||
'lines': ['Reserved. Write only the reset value to these bits.'],
|
||
'reset': '0',
|
||
'rw': 'R/W'},
|
||
{'bits': 'D6',
|
||
'lines': ['0: DRC disabled for left channel', '1: DRC enabled for left channel'],
|
||
'reset': '0',
|
||
'rw': 'R/W'},
|
||
{'bits': 'D5',
|
||
'lines': ['0: DRC disabled for right channel', '1: DRC enabled for right channel'],
|
||
'reset': '0',
|
||
'rw': 'R/W'},
|
||
{'bits': 'D4–D2',
|
||
'lines': ['000: DRC threshold = –3 dB',
|
||
'001: DRC threshold = –6 dB',
|
||
'010: DRC threshold = –9 dB',
|
||
'011: DRC threshold = –12 dB',
|
||
'100: DRC threshold = –15 dB',
|
||
'101: DRC threshold = –18 dB',
|
||
'110: DRC threshold = –21 dB',
|
||
'111: DRC threshold = –24 dB'],
|
||
'reset': '011',
|
||
'rw': 'R/W'},
|
||
{'bits': 'D1–D0',
|
||
'lines': ['00: DRC hysteresis = 0 dB',
|
||
'01: DRC hysteresis = 1 dB',
|
||
'10: DRC hysteresis = 2 dB',
|
||
'11: DRC hysteresis = 3 dB'],
|
||
'reset': '11',
|
||
'rw': 'R/W'}]},
|
||
(0, 69): {'fields': [{'bits': 'D7',
|
||
'lines': ['Reserved. Write only the reset value to these bits.'],
|
||
'reset': '0',
|
||
'rw': 'R/W'},
|
||
{'bits': 'D6–D3',
|
||
'lines': ['DRC Hold Time',
|
||
'0000: DRC Hold Disabled',
|
||
'0001: DRC Hold Time = 32 DAC Word Clocks',
|
||
'0010: DRC Hold Time = 64 DAC Word Clocks',
|
||
'0011: DRC Hold Time = 128 DAC Word Clocks',
|
||
'0100: DRC Hold Time = 256 DAC Word Clocks',
|
||
'0101: DRC Hold Time = 512 DAC Word Clocks',
|
||
'0110: DRC Hold Time = 1024 DAC Word Clocks',
|
||
'0111: DRC Hold Time = 2048 DAC Word Clocks',
|
||
'1000: DRC Hold Time = 4096 DAC Word Clocks',
|
||
'1001: DRC Hold Time = 8192 DAC Word Clocks',
|
||
'1010: DRC Hold Time = 16 384 DAC Word Clocks',
|
||
'1011: DRC Hold Time = 32 768 DAC Word Clocks',
|
||
'1100: DRC Hold Time = 65 536 DAC Word Clocks',
|
||
'1101: DRC Hold Time = 98 304 DAC Word Clocks',
|
||
'1110: DRC Hold Time = 131 072 DAC Word Clocks',
|
||
'1111: DRC Hold Time = 163 840 DAC Word Clocks'],
|
||
'reset': '0111',
|
||
'rw': 'R/W'},
|
||
{'bits': 'D2–D0',
|
||
'lines': ['Reserved. Write only the reset value to these bits.'],
|
||
'reset': '000',
|
||
'rw': 'R'}]},
|
||
(0, 70): {'fields': [{'bits': 'D7–D4',
|
||
'lines': ['0000: DRC attack rate = 4 dB per DAC Word Clock',
|
||
'0001: DRC attack rate = 2 dB per DAC word clock',
|
||
'0010: DRC attack rate = 1 dB per DAC word clock',
|
||
'...',
|
||
'1110: DRC attack rate = 2.4414e–5 dB per DAC word clock',
|
||
'1111: DRC attack rate = 1.2207e–5 dB per DAC word clock'],
|
||
'reset': '0000',
|
||
'rw': 'R/W'},
|
||
{'bits': 'D3–D0',
|
||
'lines': ['Decay Rate is defined as DR / 2[bits D3-D0 value] dB per DAC Word Clock, where DR = '
|
||
'0.015625 dB',
|
||
'0000: DRC decay rate (DR) = 0.015625 dB per DAC Word Clock',
|
||
'0001: DRC decay rate = DR / 2 dB per DAC Word Clock',
|
||
'0010: DRC decay rate = DR / 22 dB per DAC Word Clock',
|
||
'0011: DRC decay rate = DR / 23 dB per DAC Word Clock',
|
||
'0100: DRC decay rate = DR / 24 dB per DAC Word Clock',
|
||
'0101: DRC decay rate = DR / 25 dB per DAC Word Clock',
|
||
'0110: DRC decay rate = DR / 26 dB per DAC Word Clock',
|
||
'0111: DRC decay rate = DR / 27 dB per DAC Word Clock',
|
||
'1000: DRC decay rate = DR / 28 dB per DAC Word Clock',
|
||
'1001: DRC decay rate = DR / 29 dB per DAC Word Clock',
|
||
'1010: DRC decay rate = DR / 210 dB per DAC Word Clock',
|
||
'1011: DRC decay rate = DR / 211 dB per DAC Word Clock',
|
||
'1100: DRC decay rate = DR / 212 dB per DAC Word Clock',
|
||
'1101: DRC decay rate = DR / 213 dB per DAC Word Clock',
|
||
'1110: DRC decay rate = DR / 214 dB per DAC Word Clock',
|
||
'1111: DRC decay rate = DR / 215 dB per DAC Word Clock'],
|
||
'reset': '0000',
|
||
'rw': 'R/W'}]},
|
||
(0, 71): {'fields': [{'bits': 'D7',
|
||
'lines': ['0: Beep generator is disabled.',
|
||
'1: Beep generator is enabled (self-clearing based on beep duration).'],
|
||
'reset': '0',
|
||
'rw': 'R/W'},
|
||
{'bits': 'D6', 'lines': ['Reserved. Write only reset value.'], 'reset': '0', 'rw': 'R/W'},
|
||
{'bits': 'D5–D0',
|
||
'lines': ['00 0000: Left-channel beep volume control = 2 dB',
|
||
'00 0001: Left-channel beep volume control = 1 dB',
|
||
'00 0010: Left-channel beep volume control = 0 dB',
|
||
'00 0011: Left-channel beep volume control = –1 dB',
|
||
'...',
|
||
'11 1110: Left-channel beep volume control = –60 dB',
|
||
'11 1111: Left-channel beep volume control = –61 dB',
|
||
'(1) The beep generator is only available in PRB_P25 DAC processing mode.'],
|
||
'reset': '00 0000',
|
||
'rw': 'R/W'}]},
|
||
(0, 72): {'fields': [{'bits': 'D7–D6',
|
||
'lines': ['00: Left and right channels have independent beep volume control.',
|
||
'01: Left-channel beep volume control is the programmed value of right-channel beep '
|
||
'volume control.',
|
||
'10: Right-channel beep volume control is the programmed value of left-channel beep '
|
||
'volume control.',
|
||
'11: Same as 00'],
|
||
'reset': '00',
|
||
'rw': 'R/W'},
|
||
{'bits': 'D5–D0',
|
||
'lines': ['00 0000: Right-channel beep volume control = 2 dB',
|
||
'00 0001: Right-channel beep volume control = 1 dB',
|
||
'00 0010: Right-channel beep volume control = 0 dB',
|
||
'00 0011: Right-channel beep volume control = –1 dB',
|
||
'...',
|
||
'11 1110: Right-channel beep volume control = –60 dB',
|
||
'11 1111: Right-channel beep volume control = –61 dB'],
|
||
'reset': '00 0000',
|
||
'rw': 'R/W'}]},
|
||
(0, 73): {'fields': [{'bits': 'D7–D0',
|
||
'lines': ['8 MSBs out of 24 bits for the number of samples for which the beep must be '
|
||
'generated.'],
|
||
'reset': '0000 0000',
|
||
'rw': 'R/W'}]},
|
||
(0, 74): {'fields': [{'bits': 'D7–D0',
|
||
'lines': ['8 middle bits out of 24 bits for the number of samples for which the beep must be '
|
||
'generated.'],
|
||
'reset': '0000 0000',
|
||
'rw': 'R/W'}]},
|
||
(0, 75): {'fields': [{'bits': 'D7–D0',
|
||
'lines': ['8 LSBs out of 24 bits for the number of samples for which beep must be generated.'],
|
||
'reset': '1110 1110',
|
||
'rw': 'R/W'}]},
|
||
(0, 76): {'fields': [{'bits': 'D7–D0',
|
||
'lines': ['8 MSBs out of 16 bits for sin(2π × fin / fS), where fin is the beep frequency and fS '
|
||
'is the DAC sample rate.'],
|
||
'reset': '0001 0000',
|
||
'rw': 'R/W'}]},
|
||
(0, 77): {'fields': [{'bits': 'D7–D0',
|
||
'lines': ['8 LSBs out of 16 bits for sin(2π × fin / fS), where fin is the beep frequency and fS '
|
||
'is the DAC sample rate.'],
|
||
'reset': '1101 1000',
|
||
'rw': 'R/W'}]},
|
||
(0, 78): {'fields': [{'bits': 'D7–D0',
|
||
'lines': ['8 MSBs out of 16 bits for cos(2π × fin / fS), where fin is the beep frequency and fS '
|
||
'is the DAC sample',
|
||
'rate.'],
|
||
'reset': '0111 1110',
|
||
'rw': 'R/W'}]},
|
||
(0, 79): {'fields': [{'bits': 'D7–D0',
|
||
'lines': ['8 LSBs out of 16 bits for cos(2π × fin / fS), where fin is the beep frequency and fS '
|
||
'is the DAC sample rate.'],
|
||
'reset': '1110 0011',
|
||
'rw': 'R/W'}]},
|
||
(0, 116): {'fields': [{'bits': 'D7',
|
||
'lines': ['0: DAC volume control is controlled by control register. (7-bit Vol ADC is powered '
|
||
'down)',
|
||
'1: DAC volume control is controlled by pin.'],
|
||
'reset': '0',
|
||
'rw': 'R/W'},
|
||
{'bits': 'D6',
|
||
'lines': ['0: Internal on-chip RC oscillator is used for the 7-bit Vol ADC for pin volume '
|
||
'control.',
|
||
'1: MCLK is used for the 7-bit Vol ADC for pin volume control.'],
|
||
'reset': '0',
|
||
'rw': 'R/W'},
|
||
{'bits': 'D5–D4',
|
||
'lines': ['00: No hysteresis for volume control ADC output',
|
||
'01: Hysteresis of ±1 bit',
|
||
'10: Hysteresis of ±2 bits',
|
||
'11: Reserved. Do not write this sequence to these bits.'],
|
||
'reset': '00',
|
||
'rw': 'R/W'},
|
||
{'bits': 'D3', 'lines': ['Reserved. Write only reset value.'], 'reset': '0', 'rw': 'R/W'},
|
||
{'bits': 'D2–D0',
|
||
'lines': ['Throughput of the 7-bit Vol ADC for pin volume control, frequency based on MCLK or '
|
||
'internal oscillator.',
|
||
'MCLK = 12 MHz Internal Oscillator Source',
|
||
'000: Throughput = 15.625 Hz 10.68 Hz',
|
||
'001: Throughput = 31.25 Hz 21.35 Hz',
|
||
'010: Throughput = 62.5 Hz 42.71 Hz',
|
||
'011: Throughput = 125 Hz 8.2 Hz',
|
||
'100: Throughput = 250 Hz 170 Hz',
|
||
'101: Throughput = 500 Hz 340 Hz',
|
||
'110: Throughput = 1 kHz 680 Hz',
|
||
'111: Throughput = 2 kHz 1.37 kHz',
|
||
'Note: These values are based on a nominal oscillator',
|
||
'frequency of 8.2 MHz. The values scale to the actual',
|
||
'oscillator frequency.'],
|
||
'reset': '000',
|
||
'rw': 'R/W'}]},
|
||
(0, 117): {'fields': [{'bits': 'D7', 'lines': ['Reserved. Write only zero to this bit.'], 'reset': '0', 'rw': 'R/W'},
|
||
{'bits': 'D6–D0',
|
||
'lines': ['000 0000: Gain applied by pin volume control = 18 dB',
|
||
'000 0001: Gain applied by pin volume control = 17.5 dB',
|
||
'000 0010: Gain applied by pin volume control = 17 dB',
|
||
'...',
|
||
'010 0011: Gain applied by pin volume control = 0.5 dB',
|
||
'010 0100: Gain applied by pin volume control = 0 dB',
|
||
'010 0101: Gain applied by pin volume control = –0.5 dB',
|
||
'...',
|
||
'101 1001: Gain applied by pin volume control = –26.5 dB',
|
||
'101 1010: Gain applied by pin volume control = –27 dB',
|
||
'101 1011: Gain applied by pin volume control = –28 dB',
|
||
'...',
|
||
'111 1101: Gain applied by pin volume control = –62 dB',
|
||
'111 1110: Gain applied by pin volume control = –63 dB',
|
||
'111 1111: Reserved.'],
|
||
'reset': 'XXX XXXX',
|
||
'rw': 'R'}]},
|
||
(1, 0): {'fields': [{'bits': 'D7–D0',
|
||
'lines': ['0000 0000: Page 0 selected',
|
||
'0000 0001: Page 1 selected',
|
||
'...',
|
||
'1111 1110: Page 254 selected',
|
||
'1111 1111: Page 255 selected'],
|
||
'reset': '0000 0000',
|
||
'rw': 'R/W'}]},
|
||
(1, 30): {'fields': [{'bits': 'D7–D2', 'lines': ['Reserved'], 'reset': '0000 00', 'rw': 'R/W'},
|
||
{'bits': 'D1',
|
||
'lines': ['0: Reset SPK power-up control bits on short-circuit detection.',
|
||
'1: SPK power-up control bits remain unchanged on short-circuit detection.'],
|
||
'reset': '0',
|
||
'rw': 'R/W'},
|
||
{'bits': 'D0',
|
||
'lines': ['0: Reset HPL and HPR power-up control bits on short-circuit detection if page 1 / '
|
||
'register 31, D1 = 1.',
|
||
'1: HPL and HPR power-up control bits remain unchanged on short-circuit detection.'],
|
||
'reset': '0',
|
||
'rw': 'R/W'}]},
|
||
(1, 31): {'fields': [{'bits': 'D7',
|
||
'lines': ['0: HPL output driver is powered down.', '1: HPL output driver is powered up.'],
|
||
'reset': '0',
|
||
'rw': 'R/W'},
|
||
{'bits': 'D6',
|
||
'lines': ['0: HPR output driver is powered down.', '1: HPR output driver is powered up.'],
|
||
'reset': '0',
|
||
'rw': 'R/W'},
|
||
{'bits': 'D5', 'lines': ['Reserved. Write only zero to this bit.'], 'reset': '0', 'rw': 'R/W'},
|
||
{'bits': 'D4–D3',
|
||
'lines': ['00: Output common-mode voltage = 1.35 V',
|
||
'01: Output common-mode voltage = 1.5 V',
|
||
'10: Output common-mode voltage = 1.65 V',
|
||
'11: Output common-mode voltage = 1.8 V'],
|
||
'reset': '0',
|
||
'rw': 'R/W'},
|
||
{'bits': 'D2', 'lines': ['Reserved. Write only 1 to this bit.'], 'reset': '1', 'rw': 'R/W'},
|
||
{'bits': 'D1',
|
||
'lines': ['0: If short-circuit protection is enabled for headphone driver and short circuit '
|
||
'detected, device limits the',
|
||
'maximum current to the load.',
|
||
'1: If short-circuit protection is enabled for headphone driver and short circuit '
|
||
'detected, device powers',
|
||
'down the output driver.'],
|
||
'reset': '0',
|
||
'rw': 'R/W'},
|
||
{'bits': 'D0',
|
||
'lines': ['0: Short circuit is not detected on the headphone driver.',
|
||
'1: Short circuit is detected on the headphone driver.'],
|
||
'reset': '0',
|
||
'rw': 'R'}]},
|
||
(1, 32): {'fields': [{'bits': 'D7',
|
||
'lines': ['0: Class-D output driver is powered down.',
|
||
'1: Class-D output driver is powered up.'],
|
||
'reset': '0',
|
||
'rw': 'R/W'},
|
||
{'bits': 'D6–D1',
|
||
'lines': ['Reserved. Write only the reset value to this bit.'],
|
||
'reset': '000 011',
|
||
'rw': 'R/W'},
|
||
{'bits': 'D0',
|
||
'lines': ['0: Short circuit is not detected on the class-D driver. Valid only if class-D '
|
||
'amplifier is powered up. For',
|
||
'short-circuit flag sticky bit, see page 0 / register 44.',
|
||
'1: Short circuit is detected on the class-D driver. Valid only if class-D amp is '
|
||
'powered-up. For short-',
|
||
'circuit flag sticky bit, see page 0 / register 44.'],
|
||
'reset': '0',
|
||
'rw': 'R'}]},
|
||
(1, 33): {'fields': [{'bits': 'D7',
|
||
'lines': ['0: If the power down sequence is activated by device software, power down using page '
|
||
'1 / register 46,',
|
||
'bit D7, then power down the DAC simultaneously with the HP and SP amplifiers.',
|
||
'1: If the power down sequence is activated by device software, power down using page '
|
||
'1 / register 46,',
|
||
'bit D7, then power down DAC only after HP and SP amplifiers are completely powered '
|
||
'down. This is to',
|
||
'optimize power-down POP.'],
|
||
'reset': '0',
|
||
'rw': 'R/W'},
|
||
{'bits': 'D6–D3',
|
||
'lines': ['0000: Driver power-on time = 0 μs',
|
||
'0001: Driver power-on time = 15.3 μs',
|
||
'0010: Driver power-on time = 153 μs',
|
||
'0011: Driver power-on time = 1.53 ms',
|
||
'0100: Driver power-on time = 15.3 ms',
|
||
'0101: Driver power-on time = 76.2 ms',
|
||
'0110: Driver power-on time = 153 ms',
|
||
'0111: Driver power-on time = 304 ms',
|
||
'1000: Driver power-on time = 610 ms',
|
||
'1001: Driver power-on time = 1.22 s',
|
||
'1010: Driver power-on time = 3.04 s',
|
||
'1011: Driver power-on time = 6.1 s',
|
||
'1100–1111: Reserved. Do not write these sequences to these bits.',
|
||
'Note: These values are based on typical oscillator frequency of 8.2 MHz. Scale '
|
||
'according to the actual',
|
||
'oscillator frequency.'],
|
||
'reset': '0111',
|
||
'rw': 'R/W'},
|
||
{'bits': 'D2–D1',
|
||
'lines': ['00: Driver ramp-up step time = 0 ms',
|
||
'01: Driver ramp-up step time = 0.98 ms',
|
||
'10: Driver ramp-up step time = 1.95 ms',
|
||
'11: Driver ramp-up step time = 3.9 ms',
|
||
'Note: These values are based on typical oscillator frequency of 8.2 MHz. Scale '
|
||
'according to the actual',
|
||
'oscillator frequency.'],
|
||
'reset': '11',
|
||
'rw': 'R/W'},
|
||
{'bits': 'D0',
|
||
'lines': ['0: Weakly driven output common-mode voltage is generated from resistor divider of '
|
||
'the AVDD supply.',
|
||
'1: Reserved'],
|
||
'reset': '0',
|
||
'rw': 'R/W'}]},
|
||
(1, 34): {'fields': [{'bits': 'D7',
|
||
'lines': ['Reserved. Write only the reset value to this bit.'],
|
||
'reset': '0',
|
||
'rw': 'R/W'},
|
||
{'bits': 'D6–D4',
|
||
'lines': ['Speaker power-up wait time (duration based on using internal oscillator)',
|
||
'000: Wait time = 0 ms',
|
||
'001: Wait time = 3.04 ms',
|
||
'010: Wait time = 7.62 ms',
|
||
'011: Wait time = 12.2 ms',
|
||
'100: Wait time = 15.3 ms',
|
||
'101: Wait time = 19.8 ms',
|
||
'110: Wait time = 24.4 ms',
|
||
'111: Wait time = 30.5 ms',
|
||
'Note: These values are based on typical oscillator frequency of 8.2 MHz. Scale '
|
||
'according to the actual',
|
||
'oscillator frequency.'],
|
||
'reset': '000',
|
||
'rw': 'R/W'},
|
||
{'bits': 'D3–D0',
|
||
'lines': ['Reserved. Write only the reset value to these bits.'],
|
||
'reset': '0000',
|
||
'rw': 'R/W'}]},
|
||
(1, 35): {'fields': [{'bits': 'D7–D6',
|
||
'lines': ['00: DAC_L is not routed anywhere.',
|
||
'01: DAC_L is routed to the left-channel mixer amplifier.',
|
||
'10: DAC_L is routed directly to the HPL driver.',
|
||
'11: Reserved'],
|
||
'reset': '00',
|
||
'rw': 'R/W'},
|
||
{'bits': 'D5',
|
||
'lines': ['0: AIN1 input is not routed to the left-channel mixer amplifier.',
|
||
'1: AIN1 input is routed to the left-channel mixer amplifier.'],
|
||
'reset': '0',
|
||
'rw': 'R/W'},
|
||
{'bits': 'D4',
|
||
'lines': ['0: AIN2 input is not routed to the left-channel mixer amplifier.',
|
||
'1: AIN2 input is routed to the left-channel mixer amplifier.'],
|
||
'reset': '0',
|
||
'rw': ''},
|
||
{'bits': 'D3–D2',
|
||
'lines': ['00: DAC_R is not routed anywhere.',
|
||
'01: DAC_R is routed to the right-channel mixer amplifier.',
|
||
'10: DAC_R is routed directly to the HPR driver.',
|
||
'11: Reserved'],
|
||
'reset': '00',
|
||
'rw': 'R/W'},
|
||
{'bits': 'D1',
|
||
'lines': ['0: AIN2 input is not routed to the right-channel mixer amplifier.',
|
||
'1: AIN2 input is routed to the right-channel mixer amplifier.'],
|
||
'reset': '0',
|
||
'rw': 'R/W'},
|
||
{'bits': 'D0',
|
||
'lines': ['0: HPL driver output is not routed to the HPR driver.',
|
||
'1: HPL driver output is routed to the HPR driver input (used for differential output '
|
||
'mode).'],
|
||
'reset': '0',
|
||
'rw': 'R/W'}]},
|
||
(1, 36): {'fields': [{'bits': 'D7',
|
||
'lines': ['0: Left-channel analog volume control is not routed to HPL output driver.',
|
||
'1: Left-channel analog volume control is routed to HPL output driver.'],
|
||
'reset': '0',
|
||
'rw': 'R/W'},
|
||
{'bits': 'D6–D0',
|
||
'lines': ['Left-channel analog volume control gain (non-linear) for the HPL output driver, 0 dB '
|
||
'to –78 dB. See'],
|
||
'reset': '111 1111',
|
||
'rw': 'R/W'}]},
|
||
(1, 37): {'fields': [{'bits': 'D7',
|
||
'lines': ['0: Right-channel analog volume control is not routed to HPR output driver.',
|
||
'1: Right-channel analog volume control is routed to HPR output driver.'],
|
||
'reset': '0',
|
||
'rw': 'R/W'},
|
||
{'bits': 'D6–D0',
|
||
'lines': ['Right-channel analog volume control gain (non-linear) for the HPR output driver, 0 '
|
||
'dB to –78 dB. See'],
|
||
'reset': '111 1111',
|
||
'rw': 'R/W'}]},
|
||
(1, 38): {'fields': [{'bits': 'D7',
|
||
'lines': ['0: Left-channel analog volume control output is not routed to class-D output driver.',
|
||
'1: Left-channel analog volume control output is routed to class-D output driver.'],
|
||
'reset': '0',
|
||
'rw': 'R/W'},
|
||
{'bits': 'D6–D0',
|
||
'lines': ['Left-channel analog volume control output gain (non-linear) for the class-D output '
|
||
'driver, 0 dB to –78',
|
||
'dB. See Table 6-24.'],
|
||
'reset': '111 1111',
|
||
'rw': 'R/W'}]},
|
||
(1, 40): {'fields': [{'bits': 'D7', 'lines': ['Reserved. Write only zero to this bit.'], 'reset': '0', 'rw': 'R/W'},
|
||
{'bits': 'D6–D3',
|
||
'lines': ['0000: HPL driver PGA = 0 dB',
|
||
'0001: HPL driver PGA = 1 dB',
|
||
'0010: HPL driver PGA = 2 dB',
|
||
'...',
|
||
'1000: HPL driver PGA = 8 dB',
|
||
'1001: HPL driver PGA = 9 dB',
|
||
'1010–1111: Reserved. Do not write these sequences to these bits.'],
|
||
'reset': '0000',
|
||
'rw': 'R/W'},
|
||
{'bits': 'D2',
|
||
'lines': ['0: HPL driver is muted.', '1: HPL driver is not muted.'],
|
||
'reset': '0',
|
||
'rw': 'R/W'},
|
||
{'bits': 'D1', 'lines': ['Reserved'], 'reset': '1', 'rw': 'R/W'},
|
||
{'bits': 'D0',
|
||
'lines': ['0: Not all programmed gains to HPL have been applied yet.',
|
||
'1: All programmed gains to HPL have been applied.'],
|
||
'reset': '0',
|
||
'rw': 'R'}]},
|
||
(1, 41): {'fields': [{'bits': 'D7', 'lines': ['Reserved. Write only zero to this bit.'], 'reset': '0', 'rw': 'R/W'},
|
||
{'bits': 'D6–D3',
|
||
'lines': ['0000: HPR driver PGA = 0 dB',
|
||
'0001: HPR driver PGA = 1 dB',
|
||
'0010: HPR driver PGA = 2 dB',
|
||
'...',
|
||
'1000: HPR driver PGA = 8 dB',
|
||
'1001: HPR driver PGA = 9 dB',
|
||
'1010–1111: Reserved. Do not write these sequences to these bits.'],
|
||
'reset': '0000',
|
||
'rw': 'R/W'},
|
||
{'bits': 'D2',
|
||
'lines': ['0: HPR driver is muted.', '1: HPR driver is not muted.'],
|
||
'reset': '0',
|
||
'rw': 'R/W'},
|
||
{'bits': 'D1', 'lines': ["Reserved. Write only '1' to this bit."], 'reset': '1', 'rw': 'R/W'},
|
||
{'bits': 'D0',
|
||
'lines': ['0: Not all programmed gains to HPR have been applied yet.',
|
||
'1: All programmed gains to HPR have been applied.'],
|
||
'reset': '0',
|
||
'rw': 'R'}]},
|
||
(1, 42): {'fields': [{'bits': 'D7–D5',
|
||
'lines': ['Reserved. Write only zeros to these bits.'],
|
||
'reset': '000',
|
||
'rw': 'R/W'},
|
||
{'bits': 'D4–D3',
|
||
'lines': ['00: Class-D driver output stage gain = 6 dB',
|
||
'01: Class-D driver output stage gain = 12 dB',
|
||
'10: Class-D driver output stage gain = 18 dB',
|
||
'11: Class-D driver output stage gain = 24 dB'],
|
||
'reset': '00',
|
||
'rw': 'R/W'},
|
||
{'bits': 'D2',
|
||
'lines': ['0: Class-D driver is muted.', '1: Class-D driver is not muted.'],
|
||
'reset': '0',
|
||
'rw': 'R/W'},
|
||
{'bits': 'D1', 'lines': ['Reserved. Write only zero to this bit.'], 'reset': '0', 'rw': 'R/W'},
|
||
{'bits': 'D0',
|
||
'lines': ['0: Not all programmed gains to the Class-D driver have been applied yet.',
|
||
'1: All programmed gains to the Class-D driver have been applied.'],
|
||
'reset': '0',
|
||
'rw': 'R'}]},
|
||
(1, 44): {'fields': [{'bits': 'D7–D5',
|
||
'lines': ['Debounce time for the headset short-circuit detection',
|
||
'MCLK/DIV (Page 3 /',
|
||
'(1)',
|
||
'register 16) = 1-MHz Internal Oscillator Source',
|
||
'Source',
|
||
'000: Debounce time = 0 μs 0 μs',
|
||
'001: Debounce time = 8 μs 7.8 μs',
|
||
'010: Debounce time = 16 μs 15.6 μs',
|
||
'011: Debounce time = 32 μs 31.2 μs',
|
||
'100: Debounce time = 64 μs 62.4 μs',
|
||
'101: Debounce time = 128 μs 124.9 μs',
|
||
'110: Debounce time = 256 μs 250 μs',
|
||
'111: Debounce time = 512 μs 500 μs',
|
||
'Note: These values are based on a nominal oscillator',
|
||
'frequency of 8.2 MHz. The values scale to the actual',
|
||
'oscillator frequency.'],
|
||
'reset': '000',
|
||
'rw': 'R/W'},
|
||
{'bits': 'D4–D3',
|
||
'lines': ['00: Default mode for the DAC',
|
||
'01: DAC performance increased by increasing the current',
|
||
'10: Reserved',
|
||
'11: DAC performance increased further by increasing the current again',
|
||
'(1) The clock used for the debounce has a clock period = debounce duration / 8.'],
|
||
'reset': '00',
|
||
'rw': 'R/W'},
|
||
{'bits': 'D2',
|
||
'lines': ['0: HPL output driver is programmed as headphone driver.',
|
||
'1: HPL output driver is programmed as lineout driver.'],
|
||
'reset': '0',
|
||
'rw': 'R/W'},
|
||
{'bits': 'D1',
|
||
'lines': ['0: HPR output driver is programmed as headphone driver.',
|
||
'1: HPR output driver is programmed as lineout driver.'],
|
||
'reset': '0',
|
||
'rw': 'R/W'},
|
||
{'bits': 'D0', 'lines': ['Reserved. Write only zero to this bit.'], 'reset': '0', 'rw': 'R/W'}]},
|
||
(1, 46): {'fields': [{'bits': 'D7',
|
||
'lines': ['0: Device software power down is not enabled.',
|
||
'1: Device software power down is enabled.'],
|
||
'reset': '0',
|
||
'rw': 'R/W'},
|
||
{'bits': 'D6–D4',
|
||
'lines': ['Reserved. Write only zeros to these bits.'],
|
||
'reset': '000',
|
||
'rw': 'R/W'},
|
||
{'bits': 'D3',
|
||
'lines': ['0: Programmed MICBIAS is not powered up if headset detection is enabled but headset '
|
||
'is not inserted.',
|
||
'1: Programmed MICBIAS is powered up even if headset is not inserted.'],
|
||
'reset': '0',
|
||
'rw': 'R/W'},
|
||
{'bits': 'D2', 'lines': ['Reserved. Write only zero to this bit.'], 'reset': '0', 'rw': 'R/W'},
|
||
{'bits': 'D1–D0',
|
||
'lines': ['00: MICBIAS output is powered down.',
|
||
'01: MICBIAS output is powered to 2 V.',
|
||
'10: MICBIAS output is powered to 2.5 V.',
|
||
'11: MICBIAS output is powered to AVDD.'],
|
||
'reset': '00',
|
||
'rw': 'R/W'}]},
|
||
(1, 50): {'fields': [{'bits': 'D7',
|
||
'lines': ['0: AIN1 input is floating, if it is not used for the analog bypass.',
|
||
'1: AIN1 input is connected to CM internally, if it is not used for the analog '
|
||
'bypass.'],
|
||
'reset': '0',
|
||
'rw': 'R/W'},
|
||
{'bits': 'D6',
|
||
'lines': ['0: AIN2 input is floating, if it is not used for the analog bypass.',
|
||
'1: AIN2 input is connected to CM internally, if it is not used for the analog '
|
||
'bypass.'],
|
||
'reset': '0',
|
||
'rw': 'R/W'},
|
||
{'bits': 'D5–D0',
|
||
'lines': ['Reserved. Write only zeros to these bits.'],
|
||
'reset': '00 0000',
|
||
'rw': 'R/W'}]},
|
||
(3, 0): {'fields': [{'bits': 'D7–D0',
|
||
'lines': ['0000 0000: Page 0 selected',
|
||
'0000 0001: Page 1 selected',
|
||
'...',
|
||
'1111 1110: Page 254 selected',
|
||
'1111 1111: Page 255 selected',
|
||
'The only register used in page 3 is register 16. The remaining page-3 registers are '
|
||
'reserved and must not',
|
||
'be written to.'],
|
||
'reset': '0000 0000',
|
||
'rw': 'R/W'}]},
|
||
(3, 16): {'fields': [{'bits': 'D7',
|
||
'lines': ['0: Internal oscillator is used for programmable delay timer.',
|
||
'1: External MCLK (1) is used for programmable delay timer.'],
|
||
'reset': '1',
|
||
'rw': 'R/W'},
|
||
{'bits': 'D6–D0',
|
||
'lines': ['MCLK Divider to Generate 1-MHz Clock for the Programmable Delay Timer',
|
||
'000 0000: MCLK divider = 128',
|
||
'000 0001: MCLK divider = 1',
|
||
'000 0010: MCLK divider = 2',
|
||
'...',
|
||
'111 1110: MCLK divider = 126',
|
||
'111 1111: MCLK divider = 127',
|
||
'(1) External clock is used only to control the delay programmed between the '
|
||
'conversions and not used for doing the actual conversion. This',
|
||
'feature is provided in case a more accurate delay is desired because the internal '
|
||
'oscillator frequency varies from device to device.',
|
||
'Default values shown for this page only become valid 100 μs following a hardware or '
|
||
'software reset.'],
|
||
'reset': '000 0001',
|
||
'rw': 'R/W'}]}}
|
||
|
||
ANALOG_VOLUME_DB = [0.0,
|
||
-0.5,
|
||
-1.0,
|
||
-1.5,
|
||
-2.0,
|
||
-2.5,
|
||
-3.0,
|
||
-3.5,
|
||
-4.0,
|
||
-4.5,
|
||
-5.0,
|
||
-5.5,
|
||
-6.0,
|
||
-6.5,
|
||
-7.0,
|
||
-7.5,
|
||
-8.0,
|
||
-8.5,
|
||
-9.0,
|
||
-9.5,
|
||
-10.0,
|
||
-10.5,
|
||
-11.0,
|
||
-11.5,
|
||
-12.0,
|
||
-12.5,
|
||
-13.0,
|
||
-13.5,
|
||
-14.0,
|
||
-14.5,
|
||
-15.0,
|
||
-15.5,
|
||
-16.0,
|
||
-16.5,
|
||
-17.0,
|
||
-17.5,
|
||
-18.1,
|
||
-18.6,
|
||
-19.1,
|
||
-19.6,
|
||
-20.1,
|
||
-20.6,
|
||
-21.1,
|
||
-21.6,
|
||
-22.1,
|
||
-22.6,
|
||
-23.1,
|
||
-23.6,
|
||
-24.1,
|
||
-24.6,
|
||
-25.1,
|
||
-25.6,
|
||
-26.1,
|
||
-26.6,
|
||
-27.1,
|
||
-27.6,
|
||
-28.1,
|
||
-28.6,
|
||
-29.1,
|
||
-29.6,
|
||
-30.1,
|
||
-30.6,
|
||
-31.1,
|
||
-31.6,
|
||
-32.1,
|
||
-32.6,
|
||
-33.1,
|
||
-33.6,
|
||
-34.1,
|
||
-34.6,
|
||
-35.2,
|
||
-35.7,
|
||
-36.2,
|
||
-36.7,
|
||
-37.2,
|
||
-37.7,
|
||
-38.2,
|
||
-38.7,
|
||
-39.2,
|
||
-39.7,
|
||
-40.2,
|
||
-40.7,
|
||
-41.2,
|
||
-41.7,
|
||
-42.1,
|
||
-42.7,
|
||
-43.2,
|
||
-43.8,
|
||
-44.3,
|
||
-44.8,
|
||
-45.2,
|
||
-45.8,
|
||
-46.2,
|
||
-46.7,
|
||
-47.4,
|
||
-47.9,
|
||
-48.2,
|
||
-48.7,
|
||
-49.3,
|
||
-50.0,
|
||
-50.3,
|
||
-51.0,
|
||
-51.4,
|
||
-51.8,
|
||
-52.2,
|
||
-52.7,
|
||
-53.7,
|
||
-54.2,
|
||
-55.3,
|
||
-56.7,
|
||
-58.3,
|
||
-60.2,
|
||
-62.7,
|
||
-64.3,
|
||
-66.2,
|
||
-68.7,
|
||
-72.2,
|
||
-78.3,
|
||
-78.3,
|
||
-78.3,
|
||
-78.3,
|
||
-78.3,
|
||
-78.3,
|
||
-78.3,
|
||
-78.3,
|
||
-78.3,
|
||
-78.3,
|
||
-78.3]
|
||
|
||
PAGE_CONTROL_FIELDS = [
|
||
{
|
||
"bits": "D7–D0",
|
||
"rw": "R/W",
|
||
"reset": "0000 0000",
|
||
"lines": [
|
||
"0000 0000: Page 0 selected",
|
||
"0000 0001: Page 1 selected",
|
||
"...",
|
||
"1111 1110: Page 254 selected",
|
||
"1111 1111: Page 255 selected",
|
||
],
|
||
}
|
||
]
|
||
|
||
for page in (8, 9, 12, 13):
|
||
REGISTER_FIELDS[(page, 0)] = {"fields": PAGE_CONTROL_FIELDS}
|
||
|
||
REGISTER_FIELDS[(8, 1)] = {
|
||
"fields": [
|
||
{
|
||
"bits": "D7–D3",
|
||
"rw": "R/W",
|
||
"reset": "0000 0",
|
||
"lines": ["Reserved. Write only the reset value."],
|
||
},
|
||
{
|
||
"bits": "D2",
|
||
"rw": "R/W",
|
||
"reset": "0",
|
||
"lines": [
|
||
"0: Adaptive filtering disabled in DAC processing block",
|
||
"1: Adaptive filtering enabled in DAC processing block",
|
||
],
|
||
},
|
||
{
|
||
"bits": "D1",
|
||
"rw": "R",
|
||
"reset": "0",
|
||
"lines": [
|
||
"0: In adaptive filter mode, DAC processing block accesses DAC coefficient Buffer A and the external control interface accesses DAC coefficient Buffer B",
|
||
"1: In adaptive filter mode, DAC processing block accesses DAC coefficient Buffer B and the external control interface accesses DAC coefficient Buffer A",
|
||
],
|
||
},
|
||
{
|
||
"bits": "D0",
|
||
"rw": "R/W",
|
||
"reset": "0",
|
||
"lines": [
|
||
"0: DAC coefficient buffers are not switched at the next frame boundary.",
|
||
"1: DAC coefficient buffers are switched at the next frame boundary, if adaptive filtering mode is enabled. This bit self-clears on switching.",
|
||
],
|
||
},
|
||
]
|
||
}
|
||
|
||
PAGE0_GROUPS = {
|
||
7: {"registers": (7, 8), "name": "PLL fractional multiplier D-value", "kind": "pll_d"},
|
||
13: {"registers": (13, 14), "name": "DAC DOSR value", "kind": "dosr"},
|
||
73: {"registers": (73, 74, 75), "name": "Beep length", "kind": "beep_length"},
|
||
76: {"registers": (76, 77), "name": "Beep sin(x)", "kind": "s16"},
|
||
78: {"registers": (78, 79), "name": "Beep cos(x)", "kind": "s16"},
|
||
}
|
||
PAGE0_GROUPED_REGS = {reg for group in PAGE0_GROUPS.values() for reg in group["registers"]}
|
||
|
||
BINARY_ENUM_RANGE_RE = re.compile(r"^([01 ]+)[–-]([01 ]+):\s*(.+)$")
|
||
BINARY_ENUM_EXACT_RE = re.compile(r"^([01 ]+):\s*(.+)$")
|
||
PAIR_COEFF_MSB_RE = re.compile(r"^Coefficient ([A-Z0-9]+)\(15:8\) for (.+)$")
|
||
PAIR_COEFF_LSB_RE = re.compile(r"^Coefficient ([A-Z0-9]+)\(7:0\) for (.+)$")
|
||
PAIR_MSB_RE = re.compile(r"^8 MSBs of (.+)$")
|
||
PAIR_LSB_RE = re.compile(r"^8 LSBs of (.+)$")
|
||
|
||
|
||
def run_command(argv: list[str], *, check: bool = True) -> subprocess.CompletedProcess[str]:
|
||
proc = subprocess.run(argv, capture_output=True, text=True)
|
||
if check and proc.returncode != 0:
|
||
stderr = proc.stderr.strip()
|
||
stdout = proc.stdout.strip()
|
||
detail = stderr or stdout or f"exit status {proc.returncode}"
|
||
raise CommandError(f"{shlex.join(argv)} failed: {detail}")
|
||
return proc
|
||
|
||
|
||
def select_page(bus: int, addr: int, page: int) -> None:
|
||
run_command([
|
||
"i2cset",
|
||
"-y",
|
||
"-f",
|
||
str(bus),
|
||
f"0x{addr:02x}",
|
||
"0x00",
|
||
f"0x{page:02x}",
|
||
])
|
||
|
||
|
||
def read_register(bus: int, addr: int, reg: int) -> int:
|
||
proc = run_command([
|
||
"i2cget",
|
||
"-y",
|
||
"-f",
|
||
str(bus),
|
||
f"0x{addr:02x}",
|
||
f"0x{reg:02x}",
|
||
])
|
||
match = re.search(r"0x([0-9A-Fa-f]{1,2})(?:\s|$)", proc.stdout)
|
||
if not match:
|
||
raise CommandError(f"unexpected i2cget output: {proc.stdout.strip()!r}")
|
||
return int(match.group(1), 16)
|
||
|
||
|
||
def read_page(bus: int, addr: int) -> list[int]:
|
||
i2ctransfer = shutil.which("i2ctransfer")
|
||
if i2ctransfer:
|
||
values: list[int] = []
|
||
for start in range(0, 128, 32):
|
||
proc = run_command([
|
||
i2ctransfer,
|
||
"-y",
|
||
"-f",
|
||
str(bus),
|
||
f"w1@0x{addr:02x}",
|
||
f"0x{start:02x}",
|
||
"r32",
|
||
])
|
||
tokens = re.findall(r"0x([0-9A-Fa-f]{2})(?:\s|$)", proc.stdout)
|
||
if len(tokens) != 32:
|
||
raise CommandError(
|
||
"unexpected i2ctransfer output while reading a page: "
|
||
f"{proc.stdout.strip()!r}"
|
||
)
|
||
values.extend(int(token, 16) for token in tokens)
|
||
return values
|
||
|
||
return [read_register(bus, addr, reg) for reg in range(128)]
|
||
|
||
|
||
def is_reserved_register(page: int, reg: int) -> bool:
|
||
return REGISTER_MAP[page][reg].startswith("Reserved")
|
||
|
||
|
||
def normalize_bits(bits: str) -> str:
|
||
return bits.replace("-", "–")
|
||
|
||
|
||
def bit_range(bits: str) -> tuple[int, int]:
|
||
cleaned = re.sub(r"\s*\(\d+\)", "", normalize_bits(bits))
|
||
match = re.match(r"^D(\d+)(?:[–-]D?(\d+))?$", cleaned)
|
||
if not match:
|
||
raise ValueError(f"unsupported bit spec: {bits!r}")
|
||
hi = int(match.group(1))
|
||
lo = int(match.group(2) or match.group(1))
|
||
if hi < lo:
|
||
hi, lo = lo, hi
|
||
return hi, lo
|
||
|
||
|
||
def bit_width(bits: str) -> int:
|
||
hi, lo = bit_range(bits)
|
||
return hi - lo + 1
|
||
|
||
|
||
def extract_bits(value: int, bits: str) -> int:
|
||
hi, lo = bit_range(bits)
|
||
return (value >> lo) & ((1 << (hi - lo + 1)) - 1)
|
||
|
||
|
||
def format_bit_value(value: int, width: int) -> str:
|
||
return format(value, f"0{width}b")
|
||
|
||
|
||
def to_signed16(value: int) -> int:
|
||
return value - 0x10000 if value & 0x8000 else value
|
||
|
||
|
||
def format_db(value: float) -> str:
|
||
return f"{value:g} dB"
|
||
|
||
|
||
def field_is_reserved(field: dict[str, object]) -> bool:
|
||
lines = field.get("lines", [])
|
||
if not lines:
|
||
return False
|
||
first = str(lines[0]).strip()
|
||
return first.startswith("Reserved")
|
||
|
||
|
||
def decode_special_field(page: int, reg: int, bits: str, raw: int) -> str | None:
|
||
key = (page, reg, normalize_bits(bits))
|
||
|
||
if reg == 0 and normalize_bits(bits) == "D7–D0":
|
||
return f"Page {raw} selected"
|
||
|
||
if key == (0, 5, "D6–D4"):
|
||
return f"PLL divider P = {8 if raw == 0 else raw}"
|
||
if key == (0, 5, "D3–D0"):
|
||
return f"PLL multiplier R = {16 if raw == 0 else raw}"
|
||
if key == (0, 6, "D5–D0"):
|
||
return "Reserved. Do not use" if raw == 0 else f"PLL multiplier J = {raw}"
|
||
if key == (0, 11, "D6–D0"):
|
||
return f"DAC NDAC divider = {128 if raw == 0 else raw}"
|
||
if key == (0, 12, "D6–D0"):
|
||
return f"DAC MDAC divider = {128 if raw == 0 else raw}"
|
||
if key == (0, 26, "D6–D0"):
|
||
return f"CLKOUT divider M = {128 if raw == 0 else raw}"
|
||
if key == (0, 28, "D7–D0"):
|
||
suffix = "" if raw == 1 else "s"
|
||
return f"Offset = {raw} BCLK{suffix}"
|
||
if key == (0, 30, "D6–D0"):
|
||
return f"BCLK divider N = {128 if raw == 0 else raw}"
|
||
if key == (0, 60, "D4–D0"):
|
||
if 1 <= raw <= 25:
|
||
return f"DAC signal-processing block PRB_P{raw}"
|
||
return "Reserved. Do not use"
|
||
if key in {(0, 65, "D7–D0"), (0, 66, "D7–D0")}:
|
||
if raw == 0x80:
|
||
return "Reserved"
|
||
if 0x00 <= raw <= 0x30:
|
||
return f"Digital volume control = {format_db(raw * 0.5)}"
|
||
if 0x81 <= raw <= 0xFF:
|
||
return f"Digital volume control = {format_db(-0.5 * (0x100 - raw))}"
|
||
return "Reserved. Do not use"
|
||
if key == (0, 70, "D7–D4"):
|
||
return f"DRC attack rate = {4 / (2 ** raw):g} dB per DAC word clock"
|
||
if key == (0, 71, "D5–D0"):
|
||
return f"Left-channel beep volume control = {format_db(2 - raw)}"
|
||
if key == (0, 72, "D5–D0"):
|
||
return f"Right-channel beep volume control = {format_db(2 - raw)}"
|
||
if key == (0, 117, "D6–D0"):
|
||
return "Reserved" if raw == 0x7F else f"Gain applied by pin volume control = {format_db(18 - 0.5 * raw)}"
|
||
if key == (1, 36, "D6–D0"):
|
||
return f"Left-channel analog gain to HPL = {format_db(ANALOG_VOLUME_DB[raw])}"
|
||
if key == (1, 37, "D6–D0"):
|
||
return f"Right-channel analog gain to HPR = {format_db(ANALOG_VOLUME_DB[raw])}"
|
||
if key == (1, 38, "D6–D0"):
|
||
return f"Left-channel analog gain to SPK = {format_db(ANALOG_VOLUME_DB[raw])}"
|
||
if key == (1, 40, "D6–D3"):
|
||
return "Reserved. Do not write this sequence" if raw > 9 else f"HPL driver PGA = {format_db(raw)}"
|
||
if key == (1, 41, "D6–D3"):
|
||
return "Reserved. Do not write this sequence" if raw > 9 else f"HPR driver PGA = {format_db(raw)}"
|
||
if key == (3, 16, "D6–D0"):
|
||
return f"MCLK divider = {128 if raw == 0 else raw}"
|
||
|
||
return None
|
||
|
||
|
||
def parse_enum_lines(lines: list[str]) -> tuple[list[str], list[tuple[int, int, str]]]:
|
||
intros: list[str] = []
|
||
enums_mutable: list[list[object]] = []
|
||
for line in lines:
|
||
cleaned = " ".join(str(line).split())
|
||
if not cleaned or cleaned == "...":
|
||
continue
|
||
if cleaned.startswith("(") or cleaned.startswith("Note:") or re.match(r"^6\.\d", cleaned):
|
||
continue
|
||
if cleaned.startswith("The only register used") or cleaned.startswith("The remaining"):
|
||
continue
|
||
if cleaned.startswith("Default values shown"):
|
||
continue
|
||
|
||
match = BINARY_ENUM_RANGE_RE.match(cleaned)
|
||
if match:
|
||
start = int(match.group(1).replace(" ", ""), 2)
|
||
end = int(match.group(2).replace(" ", ""), 2)
|
||
enums_mutable.append([start, end, match.group(3)])
|
||
continue
|
||
|
||
match = BINARY_ENUM_EXACT_RE.match(cleaned)
|
||
if match:
|
||
code = int(match.group(1).replace(" ", ""), 2)
|
||
enums_mutable.append([code, code, match.group(2)])
|
||
continue
|
||
|
||
if enums_mutable:
|
||
enums_mutable[-1][2] = f"{enums_mutable[-1][2]} {cleaned}".strip()
|
||
else:
|
||
intros.append(cleaned)
|
||
|
||
enums = [(int(start), int(end), str(text)) for start, end, text in enums_mutable]
|
||
return intros, enums
|
||
|
||
|
||
def decode_field(page: int, reg: int, field: dict[str, object], value: int) -> str | None:
|
||
bits = str(field["bits"])
|
||
raw = extract_bits(value, bits)
|
||
|
||
special = decode_special_field(page, reg, bits, raw)
|
||
if special is not None:
|
||
return special
|
||
|
||
intros, enums = parse_enum_lines(list(field.get("lines", [])))
|
||
for start, end, text in enums:
|
||
if start <= raw <= end:
|
||
return text
|
||
|
||
if intros:
|
||
return "; ".join(intros)
|
||
|
||
return None
|
||
|
||
|
||
def print_register_value(page: int, reg: int, value: int) -> None:
|
||
name = REGISTER_MAP[page][reg]
|
||
print(f"P{page:02d} R{reg:03d} (0x{reg:02X}) = 0x{value:02X} {name}")
|
||
info = REGISTER_FIELDS.get((page, reg))
|
||
if not info:
|
||
return
|
||
for field in info.get("fields", []):
|
||
if field_is_reserved(field):
|
||
continue
|
||
bits = str(field["bits"])
|
||
raw = extract_bits(value, bits)
|
||
width = bit_width(bits)
|
||
meaning = decode_field(page, reg, field, value)
|
||
if meaning is None:
|
||
continue
|
||
print(f" {bits} = {format_bit_value(raw, width)} -> {meaning}")
|
||
|
||
|
||
def print_register_description(page: int, reg: int) -> None:
|
||
print(f"P{page:02d} R{reg:03d} (0x{reg:02X}) {REGISTER_MAP[page][reg]}")
|
||
|
||
|
||
def print_page0_group_value(start_reg: int, values: list[int]) -> None:
|
||
group = PAGE0_GROUPS[start_reg]
|
||
regs = group["registers"]
|
||
kind = group["kind"]
|
||
name = group["name"]
|
||
|
||
if kind == "pll_d":
|
||
raw = ((values[7] & 0x3F) << 8) | values[8]
|
||
print(f"P00 R007/R008 (0x07/0x08) = 0x{raw:04X} ({raw}) {name}")
|
||
return
|
||
|
||
if kind == "dosr":
|
||
raw = ((values[13] & 0x03) << 8) | values[14]
|
||
if raw == 0:
|
||
meaning = "effective DOSR = 1024"
|
||
elif raw in (1, 0x3FF):
|
||
meaning = "Reserved / invalid DOSR value"
|
||
else:
|
||
meaning = f"effective DOSR = {raw}"
|
||
print(f"P00 R013/R014 (0x0D/0x0E) = 0x{raw:03X} ({raw}) {name}; {meaning}")
|
||
return
|
||
|
||
if kind == "beep_length":
|
||
raw = (values[73] << 16) | (values[74] << 8) | values[75]
|
||
print(f"P00 R073/R074/R075 (0x49/0x4A/0x4B) = 0x{raw:06X} ({raw}) {name} in DAC samples")
|
||
return
|
||
|
||
if kind == "s16":
|
||
msb, lsb = regs
|
||
raw = (values[msb] << 8) | values[lsb]
|
||
signed = to_signed16(raw)
|
||
print(
|
||
f"P00 R{msb:03d}/R{lsb:03d} (0x{msb:02X}/0x{lsb:02X}) = 0x{raw:04X} ({signed:+d}) {name}"
|
||
)
|
||
return
|
||
|
||
raise AssertionError(f"unknown page-0 group kind: {kind}")
|
||
|
||
|
||
def print_page0_group_description(start_reg: int) -> None:
|
||
group = PAGE0_GROUPS[start_reg]
|
||
regs = group["registers"]
|
||
joined_regs = "/".join(f"R{reg:03d}" for reg in regs)
|
||
joined_hex = "/".join(f"0x{reg:02X}" for reg in regs)
|
||
print(f"P00 {joined_regs} ({joined_hex}) {group['name']}")
|
||
|
||
|
||
def pair_label(desc1: str, desc2: str) -> str | None:
|
||
msb_match = PAIR_COEFF_MSB_RE.match(desc1)
|
||
lsb_match = PAIR_COEFF_LSB_RE.match(desc2)
|
||
if msb_match and lsb_match:
|
||
if msb_match.group(1) == lsb_match.group(1) and msb_match.group(2) == lsb_match.group(2):
|
||
return f"Coefficient {msb_match.group(1)} for {msb_match.group(2)}"
|
||
|
||
msb_match = PAIR_MSB_RE.match(desc1)
|
||
lsb_match = PAIR_LSB_RE.match(desc2)
|
||
if msb_match and lsb_match and msb_match.group(1) == lsb_match.group(1):
|
||
return msb_match.group(1)
|
||
|
||
return None
|
||
|
||
|
||
def print_coeff_page_values(page: int, values: list[int]) -> None:
|
||
reg = 0
|
||
while reg < 128:
|
||
if is_reserved_register(page, reg):
|
||
reg += 1
|
||
continue
|
||
|
||
if (page, reg) in REGISTER_FIELDS:
|
||
print_register_value(page, reg, values[reg])
|
||
reg += 1
|
||
continue
|
||
|
||
if reg + 1 < 128 and not is_reserved_register(page, reg + 1):
|
||
label = pair_label(REGISTER_MAP[page][reg], REGISTER_MAP[page][reg + 1])
|
||
if label is not None:
|
||
raw = (values[reg] << 8) | values[reg + 1]
|
||
signed = to_signed16(raw)
|
||
print(
|
||
f"P{page:02d} R{reg:03d}/R{reg + 1:03d} (0x{reg:02X}/0x{reg + 1:02X}) = 0x{raw:04X} ({signed:+d}) {label}"
|
||
)
|
||
reg += 2
|
||
continue
|
||
|
||
print_register_value(page, reg, values[reg])
|
||
reg += 1
|
||
|
||
|
||
def print_coeff_page_descriptions(page: int) -> None:
|
||
reg = 0
|
||
while reg < 128:
|
||
if is_reserved_register(page, reg):
|
||
reg += 1
|
||
continue
|
||
|
||
if (page, reg) in REGISTER_FIELDS:
|
||
print_register_description(page, reg)
|
||
reg += 1
|
||
continue
|
||
|
||
if reg + 1 < 128 and not is_reserved_register(page, reg + 1):
|
||
label = pair_label(REGISTER_MAP[page][reg], REGISTER_MAP[page][reg + 1])
|
||
if label is not None:
|
||
print(
|
||
f"P{page:02d} R{reg:03d}/R{reg + 1:03d} (0x{reg:02X}/0x{reg + 1:02X}) {label}"
|
||
)
|
||
reg += 2
|
||
continue
|
||
|
||
print_register_description(page, reg)
|
||
reg += 1
|
||
|
||
|
||
def print_page_values(page: int, values: list[int]) -> None:
|
||
if page in (8, 9, 12, 13):
|
||
print_coeff_page_values(page, values)
|
||
return
|
||
|
||
for reg in range(128):
|
||
if is_reserved_register(page, reg):
|
||
continue
|
||
if page == 0 and reg in PAGE0_GROUPED_REGS:
|
||
if reg in PAGE0_GROUPS:
|
||
print_page0_group_value(reg, values)
|
||
continue
|
||
print_register_value(page, reg, values[reg])
|
||
|
||
|
||
def print_page_descriptions(page: int) -> None:
|
||
if page in (8, 9, 12, 13):
|
||
print_coeff_page_descriptions(page)
|
||
return
|
||
|
||
for reg in range(128):
|
||
if is_reserved_register(page, reg):
|
||
continue
|
||
if page == 0 and reg in PAGE0_GROUPED_REGS:
|
||
if reg in PAGE0_GROUPS:
|
||
print_page0_group_description(reg)
|
||
continue
|
||
print_register_description(page, reg)
|
||
|
||
|
||
def make_parser() -> argparse.ArgumentParser:
|
||
parser = argparse.ArgumentParser(
|
||
description="Dump TLV320DAC3100 registers and decode their meanings.",
|
||
formatter_class=argparse.ArgumentDefaultsHelpFormatter,
|
||
)
|
||
parser.add_argument("--bus", type=parse_int, default=1, help="I2C bus number")
|
||
parser.add_argument(
|
||
"--addr",
|
||
type=parse_int,
|
||
default=0x18,
|
||
help="7-bit TLV320DAC3100 I2C address",
|
||
)
|
||
parser.add_argument(
|
||
"--pages",
|
||
type=parse_pages,
|
||
default=list(DEFINED_PAGES),
|
||
help="comma-separated page list, or 'all'",
|
||
)
|
||
parser.add_argument(
|
||
"--descriptions-only",
|
||
action="store_true",
|
||
help="do not touch I2C; print only non-reserved registers and grouped fields",
|
||
)
|
||
return parser
|
||
|
||
|
||
def main() -> int:
|
||
parser = make_parser()
|
||
args = parser.parse_args()
|
||
|
||
try:
|
||
print("# TLV320DAC3100 register dump")
|
||
print("# source: hard-coded from tlv320dac3100.pdf (Rev. C)")
|
||
if args.descriptions_only:
|
||
print("# mode: descriptions only (reserved registers omitted)")
|
||
else:
|
||
print(
|
||
f"# mode: live I2C read on bus {args.bus}, addr 0x{args.addr:02x} "
|
||
"(reserved registers omitted)"
|
||
)
|
||
|
||
for page in args.pages:
|
||
print()
|
||
print(f"[page {page}]")
|
||
if args.descriptions_only:
|
||
print_page_descriptions(page)
|
||
continue
|
||
|
||
select_page(args.bus, args.addr, page)
|
||
values = read_page(args.bus, args.addr)
|
||
print_page_values(page, values)
|
||
|
||
if not args.descriptions_only:
|
||
try:
|
||
select_page(args.bus, args.addr, 0)
|
||
except CommandError:
|
||
pass
|
||
|
||
return 0
|
||
except (CommandError, argparse.ArgumentTypeError, ValueError) as exc:
|
||
print(f"error: {exc}", file=sys.stderr)
|
||
return 1
|
||
except KeyboardInterrupt:
|
||
print("interrupted", file=sys.stderr)
|
||
return 130
|
||
|
||
|
||
if __name__ == "__main__":
|
||
sys.exit(main())
|