muhammadrefa/NAU881x-stm32-C

Fantastic library!

Closed this issue · 3 comments

Hey, this is a great library! Do you have an example of getting the NAU881x into a working state (any working state at all). It would be helpful to see a starting configuration :)

Thanks! I have edited the README.md to add some sample code. The code will route the audio from the mic directly to the speaker via its internal bypass route. It is useful to make sure the codec works without adding any i2s codes to the program

Hope it helps :)

Thank you, I appreciate that.

Feel free to close & ignore the following part; but, it's not always easy to find someone who's brought up a random IC.

I am working on bringing up this pcb with the NAU8810, and I am not observing reasonable behavior. Although the nau8810 is respecting the physical I2C protocol, I am reading all zero registers except for 0x0C, 0x0D, 0x1C, 0x1D, 0x24, and 0x25, which have the value 1.

Did you see weird things when communicating with the device before you did something? I'm giving it a stable supply of 3V for the analog side (LDO for mssr) and 3.3V for the digital side. No worries if you haven't seen anything like this!

EDIT: I found this linux kernel discussion where they are saying this device is weird because it's a 7x9 codec instead of 7x8. I am porting your code to esp32/esphome, so I just changed the I2C functions to:

#define NAU881X_REG_WRITE(handle, reg, val) nau8810_I2C_Write(handle, NAU881X_I2C_ADDRESS, reg, val)
#define NAU881X_REG_READ(handle, reg) nau8810_I2C_Read(handle, NAU881X_I2C_ADDRESS, reg)

and

void nau8810_I2C_Write(esphome::nau8810::NAU8810Component * c, uint8_t i2c_address, uint8_t reg, uint16_t value)
{
    if (!c->write_byte_16(reg, value)) {
        c->status_set_warning();
    }
}

uint16_t nau8810_I2C_Read(esphome::nau8810::NAU8810Component * c, uint8_t i2c_address, uint8_t reg)
{
    uint16_t result;
    if (!c->read_byte_16(reg, &result)) {
        c->status_set_warning();
    }
    return result;
}

I reread the datasheet, and it turns out I implmented I2C read/write incorrectly. Here's the correct implementation (on ESP32):

void nau8810_I2C_Write(esphome::nau8810::NAU8810Component * c, uint8_t i2c_address, uint8_t reg, uint16_t value)
{
    uint8_t reg_, value_;
    reg_ = reg * 2;
    reg_ |= (value >> 8) & 0x1;
    value_ = (uint8_t) value;
    if (!c->write_byte(reg_, value_)) {
        c->status_set_warning();
    }
}

uint16_t nau8810_I2C_Read(esphome::nau8810::NAU8810Component * c, uint8_t i2c_address, uint8_t reg)
{
    reg *= 2;
    uint16_t result;
    if (!c->read_byte_16(reg, &result)) {
        c->status_set_warning();
    }
    return result;
}

Here's a reddit comment with the reasoning: https://www.reddit.com/r/AskElectronics/comments/13v6e7h/comment/jm5ays2/?utm_source=share&utm_medium=web2x&context=3

Figure 22 in section 12.9.1.1 of the datasheet explains that one must treat the register address as a 7 bit value, shifting it one bit higher. For reads, the LSB should be zero, and for writes, the LSB of the register address is the MSB of the data.

I've now managed to play sound from the NAU8810 using your driver with these functions on the ESP32/Esphome platform.

Thanks again for writing this!