Hi
I tried to play an audio convert file by NRF52840 via I2S, but the sound output was like noise (incorrect):
This is my config I2S:
// Enable transmission NRF_I2S->CONFIG.TXEN = (I2S_CONFIG_TXEN_TXEN_ENABLE << I2S_CONFIG_TXEN_TXEN_Pos); // Enable MCK generator NRF_I2S->CONFIG.MCKEN = (I2S_CONFIG_MCKEN_MCKEN_ENABLE << I2S_CONFIG_MCKEN_MCKEN_Pos); // MCKFREQ = 4 MHz NRF_I2S->CONFIG.MCKFREQ = I2S_CONFIG_MCKFREQ_MCKFREQ_32MDIV11 << I2S_CONFIG_MCKFREQ_MCKFREQ_Pos; // Ratio = 64 NRF_I2S->CONFIG.RATIO = I2S_CONFIG_RATIO_RATIO_128X << I2S_CONFIG_RATIO_RATIO_Pos; // Master mode, 16Bit, left aligned NRF_I2S->CONFIG.MODE = I2S_CONFIG_MODE_MODE_MASTER << I2S_CONFIG_MODE_MODE_Pos; NRF_I2S->CONFIG.SWIDTH = I2S_CONFIG_SWIDTH_SWIDTH_16BIT << I2S_CONFIG_SWIDTH_SWIDTH_Pos; NRF_I2S->CONFIG.ALIGN = I2S_CONFIG_ALIGN_ALIGN_LEFT << I2S_CONFIG_ALIGN_ALIGN_Pos; // Format = I2S NRF_I2S->CONFIG.FORMAT = I2S_CONFIG_FORMAT_FORMAT_I2S << I2S_CONFIG_FORMAT_FORMAT_Pos; // Use stereo NRF_I2S->CONFIG.CHANNELS = I2S_CONFIG_CHANNELS_CHANNELS_STEREO << I2S_CONFIG_CHANNELS_CHANNELS_Pos; // Configure pins // NRF_I2S->PSEL.MCK = (PIN_MCK << I2S_PSEL_MCK_PIN_Pos); NRF_I2S->PSEL.SCK = (PIN_SCK << I2S_PSEL_SCK_PIN_Pos); NRF_I2S->PSEL.LRCK = (PIN_LRCK << I2S_PSEL_LRCK_PIN_Pos); NRF_I2S->PSEL.SDOUT = (PIN_SDOUT << I2S_PSEL_SDOUT_PIN_Pos); NRF_I2S->ENABLE = (I2S_ENABLE_ENABLE_Enabled << I2S_ENABLE_ENABLE_Pos); // Configure data pointer NRF_I2S->TXD.PTR = (uint32_t)&audio_table[0]; NRF_I2S->RXTXD.MAXCNT = sizeof(audio_table) / sizeof(unsigned const char); // Start transmitting I2S data NRF_I2S->EVENTS_TXPTRUPD = 0; NRF_I2S->ENABLE = 1; NRF_I2S->TASKS_START = 1;The audio file I am using "Audacity" audio tool converts with parameters like this
and use Python code to convert to a .h file
from __future__ import print_function import os import struct import wave from builtins import range try: from typing import List except ImportError: pass def get_wave_array_str(filename, target_bits): # type: (str, int) -> str try: wave_read = wave.open(filename, 'r') except wave.Error as e: print(f"Error processing {filename}: {e}") return '' array_str = '' nchannels, sampwidth, framerate, nframes, comptype, compname = wave_read.getparams() sampwidth *= 8 scale_val = (1 << target_bits) - 1 cur_lim = (1 << sampwidth) - 1 for i in range(wave_read.getnframes()): frame_data = wave_read.readframes(1) if sampwidth == 8: val = struct.unpack('<B', frame_data[:1])[0] # 8-bit is unsigned char elif sampwidth == 16: val = struct.unpack('<H', frame_data[:2])[0] # 16-bit is unsigned short elif sampwidth == 24: val = struct.unpack('<I', frame_data[:3] + b'\x00')[0] # 24-bit is unsigned int (little-endian) else: raise ValueError("Unsupported sample width: {}".format(sampwidth)) # scale current data to target bits val = val * scale_val / cur_lim val = int(val + ((scale_val + 1) // 2)) & scale_val array_str += '0x%x, ' % (val) if (i + 1) % 16 == 0: array_str += '\n' wave_read.close() return array_str def gen_wave_table(wav_file_list, target_file_name, scale_bits=8): # type: (List[str], str, int) -> None with open(target_file_name, 'w') as audio_table: print('#include <stdio.h>', file=audio_table) print('const unsigned char audio_table[] = {', file=audio_table) for wav in wav_file_list: print('processing: {}'.format(wav)) wave_data_str = get_wave_array_str(filename=wav, target_bits=scale_bits) if wave_data_str: # Only print non-empty strings print(wave_data_str, file=audio_table) print('};\n', file=audio_table) print('Done...') if __name__ == '__main__': print('Generating audio array...') wav_file = input("Enter the name of the WAV file you want to convert: ") if not os.path.exists(wav_file): print(f"File {wav_file} does not exist.") else: output_file = os.path.splitext(wav_file)[0] + '.h' try: with wave.open(wav_file, 'r') as wave_read: _, sampwidth, _, _, _, _ = wave_read.getparams() sampwidth_bits = sampwidth * 8 except wave.Error as e: print(f"Error processing {wav_file}: {e}") exit(1) gen_wave_table(wav_file_list=[wav_file], target_file_name=output_file, scale_bits=sampwidth_bits)
I used "a logic analyzer" to measure the output signal
Sometimes I use this tool the "DOUT" is empty!!!!