Page 1 of 1

Store I2S bytes in different order

Posted: Tue Jan 29, 2019 5:32 pm
by goldenDragon
Hi, I am using I2S to retrieve data from an ADC. Each sample is 32 bits and comes MSB first with the frame sync frequency equaling the ADC sampling speed. The two most significant bytes come in as the frame sync signal is high and then the two least significant bytes come in as frame sync is low. The problem is the esp32 seems to put the least significant bytes of the previous ADC sample with the most significant bytes of the current sample in memory (or at least that's what it looks like to me). Does anyone know how to make the esp32 store the bytes with the right channel first followed by the left channel since that is the order in which the bytes are being transferred from my ADC?

Here is what i see from the logic analyzer:
Capture.JPG
Capture.JPG (44.75 KiB) Viewed 3569 times
But this is the order that I get the data when I run the code below:

0: 526d1072
1: 146f7028

Code: Select all

   

void print_adc_data(void)
{
	for(uint32_t i = 0; i < adc.index; i = i+BYTES_PER_SAMPLE)
    	{
		printf("%d: %02x%02x%02x%02x\n",
		(i/BYTES_PER_SAMPLE),(uint8_t)adc.data[i],(uint8_t)adc.data[i+1],(uint8_t)adc.data[i+2],(uint8_t)adc.data[i+3]);
    }   
}  

 
#define NUM_OF_SAMPLES 100
#define BYTES_PER_SAMPLE 4
#define SAMPLE_RATE  125000


typedef struct
{
    int8_t data[NUM_OF_SAMPLES*BYTES_PER_SAMPLE];
    uint32_t index;
} ADC;

ADC adc;

void app_main(void)
{
   i2s_config_t i2s_config = {
        .mode = I2S_MODE_SLAVE | I2S_MODE_RX,                                  
        .sample_rate = SAMPLE_RATE,
        .bits_per_sample = 16,
            .channel_format = I2S_CHANNEL_FMT_RIGHT_LEFT,                         
        .communication_format = I2S_COMM_FORMAT_PCM,
        .dma_buf_count = 4,
        .dma_buf_len = 100,
        .use_apll = false,
        .intr_alloc_flags = ESP_INTR_FLAG_LEVEL1                                //Interrupt level 1
    };
    i2s_pin_config_t pin_config = {
        .bck_io_num = ADC_SCLK,
        .ws_io_num = ADC_FSYNC,
        .data_out_num = -1,
        .data_in_num = ADC_DOUT                                              
    };

    i2s_driver_install(I2S_NUM, &i2s_config, 0, NULL);
    i2s_stop(I2S_NUM);
    i2s_set_pin(I2S_NUM, &pin_config);
    ....
    i2s_read(I2S_NUM, adc.data, NUM_OF_SAMPLES*BYTES_PER_SAMPLE, &br, portMAX_DELAY );
    print_adc_data(void);
 }

Re: Store I2S bytes in different order

Posted: Wed Jan 30, 2019 4:04 am
by ESP_Sprite
The ESP32 is little-endian, so if you let the CPU interpret it as an 16-bit number, the byte swap happens 'automatically':

Code: Select all

printf("%d: %02x %02x\n",
		(i/BYTES_PER_SAMPLE),(uint16_t)adc.data[i/2],(uint16_t)adc.data[i/2+1]);
The only problem then is that the I2S peripheral stores the 16-bit values in the wrong order; unfortunately there's not really a solution for that.