pub fn read(&mut self, address: u8, buffer: &mut [u8]) -> Result<(), Error> {
        // Check size constraints
        if buffer.len() > 254 {
            return Err(Error::ExceedingFifo);
        }

        let mut cmd_iterator = CommandRegister::COMD0;

        self.add_cmd_lp(&mut cmd_iterator, Command::Start)?;

        // Load device address
        self.write_fifo((address << 1) | OperationType::Read as u8);

        self.add_cmd_lp(
            &mut cmd_iterator,
            Command::Write {
                ack_exp: Ack::Ack,
                ack_check_en: true,
                length: 1_u8,
            },
        )?;

        self.enable_interrupts(
            (1 << LP_I2C_TRANS_COMPLETE_INT_ST_S) | (1 << LP_I2C_END_DETECT_INT_ST_S),
        );

        let mut remaining_bytes = buffer.len();

        while remaining_bytes > 0 {
            let fifo_size = if remaining_bytes < LP_I2C_FIFO_LEN as usize {
                remaining_bytes
            } else {
                LP_I2C_FIFO_LEN as usize
            };
            remaining_bytes -= fifo_size;

            if fifo_size == 1 {
                // Read one byte and send NACK
                self.add_cmd_lp(
                    &mut cmd_iterator,
                    Command::Read {
                        ack_value: Ack::Nack,
                        length: 1, // which is `fifo_size`
                    },
                )?;
                // Send STOP command after reading
                self.add_cmd_lp(&mut cmd_iterator, Command::Stop)?;
            } else if fifo_size > 1 && remaining_bytes == 0 {
                // This means it is the last transaction
                // Read all but the last byte and send ACKs
                self.add_cmd_lp(
                    &mut cmd_iterator,
                    Command::Read {
                        ack_value: Ack::Ack,
                        length: (fifo_size - 1) as u8,
                    },
                )?;
                // Read the last byte and send NACK
                self.add_cmd_lp(
                    &mut cmd_iterator,
                    Command::Read {
                        ack_value: Ack::Nack,
                        length: 1,
                    },
                )?;
                // Send STOP command after reading
                self.add_cmd_lp(&mut cmd_iterator, Command::Stop)?;
            } else {
                // This means we have to read data more than we can fit into the Rx FIFO
                // Read fifo_size bytes and send ACKs
                self.add_cmd_lp(
                    &mut cmd_iterator,
                    Command::Read {
                        ack_value: Ack::Ack,
                        length: fifo_size as u8,
                    },
                )?;
                // Send END command signaling more data to come
                self.add_cmd_lp(&mut cmd_iterator, Command::End)?;
            }

            self.lp_i2c_update();

            // Initiate I2C transfer
            self.i2c.ctr().modify(|_, w| w.trans_start().set_bit());

            // Await for completion (This function or mechanism should handle waiting for
            // the I2C transfer to complete)
            self.wait_for_completion()?;

            // Read from FIFO into the current chunk
            for byte in buffer.iter_mut() {
                *byte = self.read_fifo();
            }
        }
        Ok(())
    }
Reads enough bytes from slave with given `address` to fill `buffer`
esp-lp-hal/src/i2c.rs