Post Go back to editing

No Audio, interfacing with CM108B USB codec

Thread Summary

The user is troubleshooting a MAX98390 amplifier with a CM108B USB codec, experiencing no audio and no speaker output toggling. The final answer confirms the MAX98390 can run with just BCLK, LRCLK, and DIN I2S signals and suggests verifying power supply settings, particularly DVDD. The user should also ensure the correct sequence of disabling and enabling the speaker and DSP, and consider decoupling I2S from I2C writes to isolate the issue.
AI Generated Content
Category: Hardware
Product Number: MAX98390

Hello, I am interfacing a Cmedia CM108B USB codec to a MAX98390 amp and I get no audio at all, and speaker + and - outputs do not toggle.

I am breadboarding this for now to validate the circuit before incorporating into an existing board design.

So the Windows demo SW and board works and DSM enabled sounds great! I generated a register list for 48 kHz sampling using DSM Sound Studio. Now to match up with the CM108B codec's I2S format (48 kHz, 16-bit data, 32 clocks per LRCLK) I modified the register values.

I am using a small MCU board to program the I2C registers. I verified that the I2C reads and writes are working correctly by verifying the written values, and also reading default register values. I am using a MOSFET style level translator to convert its 3.3V logic down to 1.8V. The MicroPython code is attached. Lines with # in front are commented out.

I've attached a protocol analyzer capture of the CM108B's I2S output into the MAX chip. I am only using BCLK, LRCLK and DIN  signals into the MAX98390. I confirmed that it can run without the master clock by wiring the AUDINT3 and MAX board with jumper wires and only connecting these I2S signals (and I2C).

I am using a TXB0108B level translator to drop the 3.3V I2S from the CM108B to 1.8V for the MAX chip. Scope plots look good. Scope shows ground bounce (typical of breadboards), but the I2S signals are well within valid logic levels so should not be an issue.

I get no sound and no toggling of the speaker + and - outputs at all. I put the demo HW setup back using the AUDINT3 board and it works, so the HW is not damaged.

I've tried reading various fault registers and I don't see any warning of UVLO, overtemp, whatever.

  1. Any ideas on what could be wrong or things to try?
  2. Can you double check my registers, see if I have a wrong value or missing something?
  3. Can the MAX chip run with just the the bare 3 I2S signals?
  4. Any registers I can check to confirm that it's actually seeing the I2S data?
  5. Any registers I can check to see why it has no output (error or faults)

Thanks for your help! -Vince

# This MicroPython running on an RP2040 MCU board
# Configure the MAX98390 I2C registers for CM108B USB codec:
#   48 kHz sampling, 16-bit data, 32 clocks per LRCLK


from machine import Pin, I2C

i2c = I2C(1, scl=Pin(15), sda=Pin(14), freq=100_000)

lst = i2c.scan()
print(f"I2C devices found: {lst}")

#MAX_ADDR = 0x70
MAX_ADDR = 0x38   # Different addressing scheme, needs 0x70 right shifted 1 bit

dat = i2c.readfrom_mem(MAX_ADDR, 0x24FF, 1, addrsize=16)
print(f"MAX Rev ID: 0b{dat[0]:08b}")
DATA_48k = [
    [0x2000, 0x00],
    [0x2002, 0x00],
    [0x2003, 0x00],
    [0x2004, 0x00],
    [0x2005, 0x00],
    [0x2006, 0x1c],
    [0x2007, 0x05],
    [0x2008, 0x00],
    [0x2009, 0x00],
    [0x200a, 0x00],
    [0x200b, 0xf0],
    [0x200c, 0x00],
    [0x200d, 0x00],
    [0x200e, 0x00],
    [0x200f, 0x00],
    [0x2010, 0x00],
    [0x2011, 0x01],
    [0x2012, 0x6c],
    [0x2014, 0x00],
    [0x2015, 0x00],
    [0x2016, 0x00],
    [0x2017, 0x75],
    [0x2018, 0x8c],
    [0x2019, 0x08],
    [0x201a, 0x55],
    [0x201b, 0x03],
    [0x201c, 0x00],
    [0x201d, 0x03],
    [0x201e, 0x00],
    [0x201f, 0xfc],
    [0x2020, 0xff],
    [0x2021, 0x10],
    [0x2022, 0x10],
    [0x2023, 0x00],

    #[0x2024, 0xc0], # Chan is 32 bits, I2S mode, data on BCLK rising, falling LRCLK=chan 0
    [0x2024, 0x40],  # Data is 16 bits ("must be programmed to be less than or equal to the channel length")
    [0x2025, 0x1c], # BCLK clock source, 12.288MHz, Slave mode
    #[0x2025, 0x14],  # BCLK clock source, 11.2896MHz MCLK, Slave Mode
    #[0x2026, 0x44],
    [0x2026, 0x22],  # 32 BCLK per LRCLK (must be 2x the data width)
    [0x2027, 0x08],  # 48 kHz PCM (LRCLK freq)

    [0x202c, 0x00],
    [0x202d, 0x00],
    [0x202e, 0x00],
    [0x202f, 0x00],
    [0x2030, 0x00],
    [0x2031, 0x00],
    [0x2032, 0x00],
    [0x2033, 0x00],
    [0x2039, 0x0f],
    [0x203a, 0x81],
    [0x203b, 0x00],
    [0x203c, 0x00],
    [0x203d, 0x05],
    [0x203e, 0x85],
    [0x203f, 0x03],
    [0x2040, 0xf7],
    [0x2041, 0x1c],
    [0x2042, 0x01],
    [0x2043, 0x40],
    [0x2044, 0x07],
    [0x2045, 0x00],
    [0x2046, 0x23],
    [0x2047, 0x00],
    [0x2048, 0x00],
    [0x2049, 0x00],
    [0x204a, 0x00],
    [0x204b, 0x00],
    [0x204c, 0x00],
    [0x204d, 0x68],
    [0x204e, 0x00],
    [0x204f, 0x2a],
    [0x2050, 0x2c],
    [0x2051, 0x00],
    [0x2052, 0x66],
    [0x2053, 0x00],
    [0x2054, 0x00],
    [0x2055, 0x00],
    [0x2056, 0x00],
    [0x2057, 0x00],
    [0x2058, 0x00],
    [0x2059, 0x00],
    [0x205a, 0x00],
    [0x205b, 0x00],
    [0x205c, 0x00],
    [0x205d, 0x00],
    [0x205e, 0x00],
    [0x205f, 0x1f],
    [0x2060, 0x00],
    [0x2061, 0x00],
    [0x2062, 0x00],
    [0x2063, 0x00],
    [0x2064, 0x00],
    [0x2065, 0x00],
    [0x2066, 0x00],
    [0x2067, 0x00],
    [0x2068, 0x00],
    [0x2069, 0x00],
    [0x206a, 0x00],
    [0x206b, 0x00],
    [0x206c, 0x00],
    [0x206d, 0x00],
    [0x206e, 0x00],
    [0x206f, 0x00],
    [0x2070, 0x00],
    [0x2071, 0x00],
    [0x2072, 0x00],
    [0x2073, 0x00],
    [0x2074, 0x00],
    [0x2075, 0x00],
    [0x2076, 0x0e],
    [0x2077, 0x84],
    [0x2078, 0x07],
    [0x2079, 0x07],
    [0x207a, 0x01],
    [0x207b, 0x00],
    [0x207c, 0x46],
    [0x207d, 0x2b],
    [0x207e, 0x08],
    [0x207f, 0x00],
    [0x2080, 0x03],
    [0x2081, 0x03],
    [0x2082, 0x07],
    [0x2083, 0x00],
    [0x2084, 0x01],
    [0x2090, 0x00],
    [0x23b9, 0x00],
    [0x23ba, 0xa0],
    [0x23e0, 0x00],
    [0x23e1, 0x00],
    [0x23ff, 0x01]]

print("Writing MAX98390 registers")
n = 0
for reg, dat in DATA_48k:
    n += 1
    print(f"  Reg: 0x{reg:04X}, Dat: 0x{dat:02X}", end="")
    i2c.writeto_mem(MAX_ADDR, reg, dat.to_bytes(), addrsize=16)
    print("\r", end="")
print(f"\n{n} registers written")

  • Hello Vince,

    Sorry to hear that you are having issues with the MAX98390.

    Let me address some of your questions:

    a) Can the MAX chip run with just the the bare 3 I2S signals? Yes, you can run the MAX98390C or MAX98390D with just 3 inputs for I2S (BCLK, LRCLK, and Data).

    b) Any registers I can check to confirm that it's actually seeing the I2S data? Yes, there is a number of interrupt registers that monitor the MAX98390, the registers can be found between 0x2002 and 0x200A. In particular, check for PWRUP_DONE, BCLK_RATE_ERR and LRCLK_RATE_ERR. If the I2S clocks are operating correctly and match with the settings on the device, then PWRUP_DONE will flag, this is power up done. If the LRCLKS or BCLKs are off, then the LRCLK_RATE or BCLK_RATE will flag. Reading the registers and interrupts can be facilitated by using the MAX98390 Evaluation Software.

    c) Can you double check my registers, see if I have a wrong value or missing something? I loaded your register set and was able to pass quality audio through the device at 16bits/48kHz. There is a protocol for writing to the register, in particular set SPK_EN = 0, DSP_GLOBAL_EN = 0, GLOBAL_EN =0 before writing the registers, then set SPK_EN = 1 and GLOBAL_EN = 1 at the end.

    c) Any ideas on what could be wrong or things to try? Verify that all the power supplies are set correctly, in particular DVDD as this supply is usually provided by the AUDINT3 board. If the AUDINT3 board is not connected to the J1 connector on the MAX98390 Development Board then DVDD will need to be powered externally.

    Best regards,

    Andrew

  • Thank you so much for the detailed reply, Andrew!

    I changed the order of the writes to follow the prescribed sequence you showed. Still nothing.

    What I do notice is that the DSM GUI writes using blocks, like <i2c_addr><reg_addr><data><data><data>... using internal automatic address increment.

    I'm writing <i2c_addr><reg_addr><data><stop> and repeating over and over. And also there's gaps in the address sequence even though it's monotonic.

    It seems to me it should not make a difference.

    Also, yes, I'm providing 1.8V to the DVDD of the chip and to the level translators.

    Also, enabling all IRQ bits and reading the IRQ status bits, I get all zeros.

    I reconnected the demo board back to AUDINT3 and it works fine.

    Also, I am not "stopping the audio stream" during I2C configuration as recommended. Is that really necessary? The USB codec gets enumerated by the PC and BCLK and LRCLK are always toggling. Any other thoughts?

    So I changed the order of my writes

    # This MicroPython running on an RP2040 MCU board
    # Configure the MAX98390 I2C registers for CM108B USB codec:
    #   48 kHz sampling, 16-bit data, 32 clocks per LRCLK
    
    from machine import Pin, I2C
    import time
    
    i2c = I2C(1, scl=Pin(15), sda=Pin(14), freq=100_000)
    
    lst = i2c.scan()
    print(f"I2C devices found: {lst}")
    
    
    #MAX_ADDR = 0x70
    MAX_ADDR = 0x38   # Different addressing scheme, needs 0x70 right shifted 1 bit
    dat = i2c.readfrom_mem(MAX_ADDR, 0x24FF, 1, addrsize=16)
    print(f"MAX Rev ID: 0b{dat[0]:08b}")
    
    DATA_48k_NONDSM = [
        # None-DSM registers are from 0x2000 to 0x2084
        [0x2000, 0x00],
        [0x2002, 0x00],
        [0x2003, 0x00],
        [0x2004, 0x00],
        [0x2005, 0x00],
        [0x2006, 0x1c],
        [0x2007, 0x05],
        [0x2008, 0x00],
        [0x2009, 0x00],
        [0x200a, 0x00],
        [0x200b, 0xf0],
        [0x200c, 0x00],
        [0x200d, 0x00],
        [0x200e, 0x00],
        [0x200f, 0x00],
        [0x2010, 0x00],
        [0x2011, 0x01],
        [0x2012, 0x6c],
        [0x2014, 0x00],
        [0x2015, 0x00],
        [0x2016, 0x00],
        [0x2017, 0x75],
        [0x2018, 0x8c],
        [0x2019, 0x08],
        [0x201a, 0x55],
        [0x201b, 0x03],
        [0x201c, 0x00],
        [0x201d, 0x03],
        [0x201e, 0x00],
        [0x201f, 0xfc],
        [0x2020, 0xff],
        [0x2021, 0x10],
        [0x2022, 0x10],
        [0x2023, 0x00],
    
        #[0x2024, 0xc0], # Chan is 32 bits, I2S mode, data on BCLK rising, falling LRCLK=chan 0
        [0x2024, 0x40],  # Data is 16 bits ("must be programmed to be less than or equal to the channel length")
        [0x2025, 0x1c], # BCLK clock source, 12.288MHz, Slave mode
        #[0x2025, 0x14],  # BCLK clock source, 11.2896MHz MCLK, Slave Mode
        #[0x2026, 0x44],
        [0x2026, 0x22],  # 32 BCLK per LRCLK (must be 2x the data width)
        [0x2027, 0x08],  # 48 kHz PCM (LRCLK freq)
    
        [0x202c, 0x00],
        [0x202d, 0x00],
        [0x202e, 0x00],
        [0x202f, 0x00],
        [0x2030, 0x00],
        [0x2031, 0x00],
        [0x2032, 0x00],
        [0x2033, 0x00],
        [0x2039, 0x0f],
        [0x203b, 0x00],
        [0x203c, 0x00],
        [0x203d, 0x05],
        [0x203e, 0x85],
        [0x203f, 0x03],
        [0x2040, 0xf7],
        [0x2041, 0x1c],
        [0x2042, 0x01],
        [0x2043, 0x40],
        [0x2044, 0x07],
        [0x2045, 0x00],
        [0x2046, 0x23],
        [0x2047, 0x00],
        [0x2048, 0x00],
        [0x2049, 0x00],
        [0x204a, 0x00],
        [0x204b, 0x00],
        [0x204c, 0x00],
        [0x204d, 0x68],
        [0x204e, 0x00],
        [0x204f, 0x2a],
        [0x2050, 0x2c],
        [0x2051, 0x00],
        [0x2052, 0x66],
        [0x2053, 0x00],
        [0x2054, 0x00],
        [0x2055, 0x00],
        [0x2056, 0x00],
        [0x2057, 0x00],
        [0x2058, 0x00],
        [0x2059, 0x00],
        [0x205a, 0x00],
        [0x205b, 0x00],
        [0x205c, 0x00],
        [0x205d, 0x00],
        [0x205e, 0x00],
        [0x205f, 0x1f],
        [0x2060, 0x00],
        [0x2061, 0x00],
        [0x2062, 0x00],
        [0x2063, 0x00],
        [0x2064, 0x00],
        [0x2065, 0x00],
        [0x2066, 0x00],
        [0x2067, 0x00],
        [0x2068, 0x00],
        [0x2069, 0x00],
        [0x206a, 0x00],
        [0x206b, 0x00],
        [0x206c, 0x00],
        [0x206d, 0x00],
        [0x206e, 0x00],
        [0x206f, 0x00],
        [0x2070, 0x00],
        [0x2071, 0x00],
        [0x2072, 0x00],
        [0x2073, 0x00],
        [0x2074, 0x00],
        [0x2075, 0x00],
        [0x2076, 0x0e],
        [0x2077, 0x84],
        [0x2078, 0x07],
        [0x2079, 0x07],
        [0x207a, 0x01],
        [0x207b, 0x00],
        [0x207c, 0x46],
        [0x207d, 0x2b],
        [0x207e, 0x08],
        [0x207f, 0x00],
        [0x2080, 0x03],
        [0x2081, 0x03],
        [0x2082, 0x07],
        [0x2083, 0x00],
        [0x2084, 0x01],
        [0x2090, 0x00],
        ]
    
    DATA_48k_DSM = [
        # DSM registers are from 0x2100 to 0x23E0
        [0x23b9, 0x00],
        [0x23ba, 0xa0],
        [0x23e0, 0x00],
        ]
    
    def read_reg(reg):
        word = i2c.readfrom_mem(MAX_ADDR, reg, 1, addrsize=16)
        return word[0]
    def write_reg(reg, dat):
        i2c.writeto_mem(MAX_ADDR, reg, dat.to_bytes(), addrsize=16)
        return
    
    def write_list(lst):
        n = 0
        print(f"Writing registers...")
        for reg, dat in lst:
            n += 1
            print(f"  Reg: 0x{reg:04X}, Dat: 0x{dat:02X}", end="")
            #i2c.writeto_mem(MAX_ADDR, reg, dat.to_bytes(), addrsize=16)
            write_reg(reg, dat)
            print("\r", end="")
        print(f"  {n} registers written", " "*10)
    
    
    #-------------------------------------------------------------------------
    # MAIN
    #-------------------------------------------------------------------------
    
    write_reg(0x2000, 0x01)    # Soft reset
    time.sleep(0.1)
    
    # First disable speaker, special sequence
    write_reg(0x23ff, 0x00)    # Disable GLOBAL_EN
    time.sleep(0.05)           # Wait at least 50 ms
    write_reg(0x203a, 0x80)    # Disable SPKR_EN
    write_reg(0x23e1, 0x00)    # Disable DSP_GLOBAL_EN
    
    # Write Non-DSM registers, then DSM registers
    write_list(DATA_48k_NONDSM)
    write_list(DATA_48k_DSM)
    
    # Enable speaker, special sequence
    write_reg(0x23e1, 0x01)    # Enable DSP_GLOBAL_EN
    write_reg(0x203a, 0x81)    # Enable SPKR_EN
    write_reg(0x23ff, 0x01)    # Enable GLOBAL_EN
    
    word = read_reg(0x2084)
    print(f"SPK_SPEEDUP is 0x{word:04x}")
    

  • Hello Vince,

    An experiment to consider would be to decouple the I2S from the I2C writes. The AUDINT3 can have its I2S capabilities disabled, so that it can be used only for programming the device with I2C, then the I2S digital audio section can be checked using the external micro-controller. If you still are not getting any interrupts off the device, then the issue may be related to I2S.

    To do this experiment:

    1) Have the AUDINT3 connected to the MAX98390 Evaluation Board.

    2) Configure the MAX98390 using a PC and the desired register file.

    3) Verify that the output is functioning. Here it can be seen that "Power Up Done" has asserted.

    4) In the MAX98390 Evaluation Software, click on the "Options" text in the top upper left, then click on "Audio Interface 3 (Advanced Users)"

    5) This will bring up a window for the Windows audio feature for the AUDINT3. Uncheck all the boxes to turn off the I2S from the AUDINT3. Verify with oscilloscope that the clocks are off.

     

    6) Apply BCLK, LRCLK, and DIN from the micro-controler to the MAX98390 Evaluation Board using the 0.1" jumpers on J2. Be sure that the wires are short and twisted with a ground wire. J2 has a row of grounds next to the clocks for this purpose.

    7) Disable, the re-enable the MAX98390, I2C is still available from the AUDINT3 and the MAX98390 Evaluation Software. Play I2S audio from the micro-controller and see the results. 

    8) The I2S feature of the AUDINT3 can be re-enabled by repeating steps 4 and 5, and checking the clocks. The AUDINT3 will also reset to its default conditions if the micro-USB cable is removed and reattached.

    Best regards,

    Andrew

  • Hi Andrew, the GUI you show looks more advanced. I can only use the old version.

    When I installed the newer MAX98390EVSwSetupV1_5_1_0.zip, I get all sorts of errors about the FTDI driver, so I found the MAX98380EVSwSetupV1_0_0_0.zip and at least I get sound on the DSM Studio demo.

    Some screenshots below. Can you tell me how to fix the FTDI issues on the new GUI so I can try your suggestions?

  • Hello Vince,

    Sorry that you are having issues with the latest version of the MAX98390C Evaluation Software. A windows update has triggered the FTDI error, but the FTDI drivers are not needed when using the AUDINT3 interface board. When the software opens (ver. 1.5.1.0), just click OK on the errors until the main GUI opens, it should operate correctly from there.

    Best regards,

    Andrew

  • Hi Andrew, got it working! Thanks so much for your help!

    I installed SW v1.5 on top of v1.0 and this time it did not complain about the FTDI driver and worked perfectly.

    It might also be that I did Remote Desktop to install v1.5 initially (using Remmina from a Linux client). Not sure if related.

    So I think my problem was that I had set the BCLK/LRCLK to 32 bits. This causes wrong value and UVLO and/or current limit errors and causes the amp to shutdown immediately.

    I thought it was number of BCLK per 1/2 clock (per channel). But CM108B puts out 64 BCLK pulses per LRCLK period.

    Ok, I'm all set now. Thank you so much for your help!

  • Hello Vince,

    Perfect, I am glad that you were able to track down the issue.

    Best regards,

    Andrew

Before You Switch


Switching languages will make ADI Explorer unavailable. Resume your session by switching back to English and reopening ADI Explorer.