I am trying to read I2S data (I can set as either slave or master, but that's not important)
The trouble is there is fundamental information missing from the reference - the read() function reads only ONE sample from the I2S data line, however I2S is stereo which obviously means that the data should be in PAIRS - so how do I know which data sample I just read, i.e. LEFT or RIGHT?
I am an Arduino newbie but I have searched on yonder and found no information on this or even the possibility of this troubling anyone so I'm not sure if I'm simply missing something.
Currently I am doing this which seems to work, but other times it receives garbage possibly from the other channel which is muted - so it is a bit hit and miss.
if ( I2S.available() > 1 )
sample_arr[num_samples++] = I2S.read();
I2S.read(); // skip other channel (?)
if ( num_samples >= max_samples )
state = 2; // complete
Secondly I'd like to move to reading on interrupt, so its even more important to know which sample is which on interrupt - if anyone has information on that also, greatly appreciated!
Sorry for the bad news but you only have one channel. You need to identify the packets as either left or right, that is in the protocol you write. You can make them 1 byte longer and preface it with a L or a R. I hope this helps!
However I am not writing any protocol. I am actually attempting to read the output of WM8731 which uses the standard I2S protocol. So how do I know which sample I just read after using the read() function? LEFT or RIGHT? It would make sense also not to muddle these up, let's say if I missed a sample.
I know I could possibly look at the pin state of the WS input, however I assume that the I2S data is buffered and that I am looking at a data point in the past which doesn't necessarily line up with the WS state in the present. Even if the read is not buffered, I am unaware of what moment in time that the read() function returns its value as there is no timing diagram I am aware of that explains this.
It seems that this fundamental information is missing on the read() function as I2S is intrinsically stereo.
The detail on here: I²S - Wikipedia seems to make it clear that the channel being transmitted is related to the World Select Clock as in "For stereo material, the I²S specification states that left audio is transmitted on the low cycle of the word select clock and the right channel is transmitted on the high cycle. It is typically synchronized to the falling edge of the serial clock, as the data is latched on the rising edge."
Thanks for the reply - I understand the I2S specification that left audio is transmitted on the low cycle of the word select clock and right channel is transmitted on the high cycle etc. The problem I have is that this information is not available through the Arduino I2S library. I am reading the samples from a DMA buffer which does not give me the information of which channel each sample was retrieved from.
Anyway I am just going to put the input into both channels to avoid this issue, however this issue is obviously lacking from the library and documentation.
I notice in one of the examples there are 2 writes one following the other with a comment above about writing to the left then right. I just wondered if the read functionality might be implemented in a similar way, ie. first read is left, second is right? Would it be feasible for you to check - I have no idea how?
I have tried this, but it always depends on when you start the read, you might get either all LEFT or all RIGHT, depending on when the first read is started, which may make sense, but is not obvious which channel is the read first (as that sample is still pulled from the DMA buffer). It seems there's no easy way to know this, probably not without rewriting the library to add some extra feature.
There are many example implementation in ArduinoSound, don’t use I2S read directly. All those implementations, like AmplitudeAnalyzer for example, have update method in common that receives byte array of 512 elements. Then depending on your bits per sample you have to convert it to 8 16 or 32 bits array. Your left and right data will be alternating elements, I don’t remember exactly which channel is which, but something like 0,2,4… will be right and 1,3,5 will be left