-
• #2
Easiest way is to get a single
SPI.send
command to transfer a big chunk of data...var sendData = new Uint8Array(256); sendData.fill(0); // now in the loop: var result = SPI2.send(sendData); // result will have 256 bytes in it
-
• #3
You could also include any required SPI commands at the beginning of the sendData array, and could then use ArrayBufferViews to cut out the data you need without a copy:
var sendData = new Uint8Array(4+256); sendData.fill(0); sendData[0] = ...; sendData[1] = ...; sendData[2] = ...; sendData[3] = ...; // now in the loop: var result = SPI2.send(sendData); var data = new Uint8Array(sendData.buffer,4,256);
-
• #4
... and you can write that new array into another array with a simple
arrayTo.set(arrayFrom)
-
• #5
...bothers me that there is still no better solution for this pattern. I suggested a while ago to use the same pattern for SPI.send() as provided for SPI.write(), where an object can be passed which includes the data and a repetition count. That way, no extra memory has to be wasted to just keep the peripheral sending... @Gordon, what's the constraint that does not allow something like that?
-
• #6
Cool, I didn't know it was that simple (and that
spi.send
can return arrays). But if I understand correctly, there is no way to shovel the data from SPI directly into the buffer of the waveform (waveforms bring their own buffers), so I always have to copy it? And I also have to temporarily allocate the space for the outgoing zeros, so effectively I need 3 times as much memory as the received payload? -
• #7
I suggested a while ago to use the same pattern for SPI.send() as provided for SPI.write()
It tries to return a buffer of the same type as the arguments, so it's not quite as easy. It is possible though - I've just had other things on my mind and this is firmly in the 'optimisation' pile of things :)
there is no way to shovel the data from SPI directly into the buffer of the waveform (waveforms bring their own buffers), so I always have to copy
Well, there's
waveform.buffer.set(dataFromSPI)
, which is quite fast.I need 3 times as much memory as the received payload?
If you don't absolutely need zeros, you could just pass the waveform's buffer in?
-
• #8
I got it to work! I posted my findings about waveform streaming here and I also published my module for interfacing Winbond flash memory.
-
• #9
@Gordon, good to know... and I know very well that there are priorities... ;-) In case you get there - even when later than sooner - choosing a reasonable default is good enough for to get started (usually UInt8). After some thinking, the passed object could pass the constructor in addition to data and repeat. As far as I see, @Dennis got it working, and small buffers render better results than large one and the extra memory to drive the sending is not a primary killer. I'm not surprised about the smaller buffer, because garbage collection is one of the primary challenge for real time things... I know that Espruino has a very smart memory management and thus an affordable garbage collect... I noticed though hick-ups when driving steppers (continuously)... which is time sensitive kind of waves a real time thing too.
-
• #10
Oh, garbage collection... yes, that could be the reason for some oddities.
@Gordon, one little tweak with (hopefully) a big impact could be to change the
SPI.write
function so that you can pass a target buffer to it and it will write the results into that buffer instead of returning a new one. -
• #11
...or buffer object, that would hold information about last (read and) written byte. Withe the read information the buffer can become cyclic.
-
• #12
I'd been wondering about that. I wonder whether thats almost another function call that's needed though? I think it would be hard to implement in a nice way with the existing
SPI.send
orSPI.write
? -
• #13
The existing functions could take additional optional arguments, and they could do the same as before if these arguments are omitted.
I'm not so much in favor of having a multitude of functions doing essentially the same thing in different ways; I find flexible calling patterns more elegant. But it's not that important, and if dedicated functions are more efficient, maybe that's the way to go.
-
• #14
I like the idea of being able to give it a buffer to fill too (or to have it send stuff from a buffer, while stuffing the response data into the same buffer?)
-
• #15
Yes - the send+receive into the same buffer seems like a great idea really. Nice and flexible.
I want to stream a waveform from an external SPI flash RAM (Winbond). Once the RAM has been prepared, reading back sequential data into is just a loop of
SPI2.send(0)
instructions whose return values are sequentially written into a uInt8Array.As mentioned in the docs, a function containing SPI calls cannot be compiled... how can I speed it up?