Your new topic does not fit any of the above??? Check first. Then post here. Thanks.

Moderator: igrr

User avatar
By Mr Mayhem
#56341 Kinda old thread, but I figure worth a try, because my frustration meter has entered the red zone
despite the example working exactly as it should... I am having a headache on morphing it into
my application.

I am successfully running SPISlave_Test.ino on an ESP8266, and
"SPISlave_Master.ino" on a Teensy 3.6.

I set my Rigol oscilloscope to decode the SPI data on MOSI and MISO, triggering on slave select.
OK, fine, I see all the letters decoded, but something is odd, literally.

I see the "Are you alive" on MOSI in one transaction,
and the "Alive for xxx milliseconds" on MISO, in the next transaction.
Looks like half-duplex to me.

Shouldn't these both occur in the same transaction (Full-Duplex)? (I thought SPI was full duplex in normal conditions, that master and slave write to half the transaction time window each respectively, in opposite directions.)

Is the missing transaction interrupt that Vince mentioned responsible for half duplex limitation in the
main spiSlave library? I believe he said that the transfer interrupt he hooked into by adding code, fired on every event, and the other interrupts like data and status fired less often. In the normal Arduino SPI library, SPI.Transfer is where full duplex transfer occurs, no? I would like to Vince's code containing the added interrupt handler, maybe that is full duplex-capable code? Or maybe I confused myself into a corner.

I cannot tell if the half-duplex behavior is happening due to the way the library is set up internally, or a consequence of the way the library is being used in the example sketches. I am stuck from investigating that, because I am stuck more trivial matters, such as string to byte conversion confusions, because the examples are all about strings in and out, "char * weirdness", (sorry, this is the first time I saw that species of string play) and I am trying to avoid using strings.

I an sending an array of sensor values read from a linear photodiode array.
The device has 256 pixels, and I use two bytes per pixel to represent the 10 bit light intensity value for
each pixel. So I am trying to send 512 bytes through the SPI somehow, and then on to Wifi eventually when I get SPI working.

For my application, I want to send 512 bytes of data through the SPI protocol from "master Teensy 3.6" to "slave ESP8266", and don't really care about sending the other direction, except if needed for flow control, etc. If I do a flow control, then this half duplex limitation explained above, may cut transaction event frequency in half versus full duplex transactions?

But first things first. String manipulation code in the examples has me confused. Can someone show me the library being used with simple byte[] arrays? Please show me how to send myBytes[512] through the pipe from master to slave. I am stuck for days on this confusion, and its giving me a headache, because of too many unknowns. I appreciate any help greatly, thanks in advance.
User avatar
By Vicne
#56352
Mr Mayhem wrote:I see the "Are you alive" on MOSI in one transaction,
and the "Alive for xxx milliseconds" on MISO, in the next transaction.
Looks like half-duplex to me.

It's been a few weeks indeed (which is much for my small brains), but as far as I understood it (but I may be wrong as it is basically undocumented), the SPI implemented in the ESP8266 is not just basic SPI like in Arduinos, it's targeted at a specific protocol where a split between "status" and "data" is mandatory.
So basically you say "I'm sending a status", then you send it, or "Please send me your status", then you read it. Same for data. But this logic is in essence half duplex indeed.

Is the missing transaction interrupt that Vince mentioned responsible for half duplex limitation in the main spiSlave library? I believe he said that the transfer interrupt he hooked into by adding code, fired on every event, and the other interrupts like data and status fired less often. In the normal Arduino SPI library, SPI.Transfer is where full duplex transfer occurs, no? I would like to Vince's code containing the added interrupt handler, maybe that is full duplex-capable code? Or maybe I confused myself into a corner.


I'm a bit ashamed to show code because it's half baked. I needed the code to work for a proof-of-concept hack (and it worked), but there was no intent to release it. Anyway, please find attached the modified version triggering only on Trans interrupt. Basically, it replaces the 4 specific interrupts by a single "catch-all" one.
However, in the final version, I discovered that triggering on read status worked equally well for the messages I was interested in.

I cannot tell if the half-duplex behavior is happening due to the way the library is set up internally, or a consequence of the way the library is being used in the example sketches.

In my (limited) experience, I'd say it's happening due to the Espressif's hardware implementation of SPI, or due to my unability to configure it another way.

I am stuck from investigating that, because I am stuck more trivial matters, such as string to byte conversion confusions, because the examples are all about strings in and out, "char * weirdness", (sorry, this is the first time I saw that species of string play) and I am trying to avoid using strings.
...
But first things first. String manipulation code in the examples has me confused. Can someone show me the library being used with simple byte[] arrays? Please show me how to send myBytes[512] through the pipe from master to slave. I am stuck for days on this confusion, and its giving me a headache, because of too many unknowns.


Sorry I don't have code to illustrate sending bytes because first as I said I'm only reading values, not writing any, and second because what I'm getting fits in a single 32-bit value I'm retrieving from the address register.

But, I advise you to forget about the meaning of "char" sounding like "character". Look at a char as an 8-bit value, and just consider an array of char as being an array of bytes.
The only difference is that chars are "signed" while bytes are "unsigned" but that only matters if you print them or compare them. The memory representation is the same : 8 contiguous bits.
https://oscarliang.com/arduino-differen ... igned-cha/
A char * is just a pointer to a such a char in memory.
string (lowercase s) is a name given to array of char when they actually represent characters, but you can treat it as a simple array of bytes.
String (uppercase S) is another beast and it's probably a good idea to avoid them at low level indeed.

Kind regards,

Vicne
You do not have the required permissions to view the files attached to this post.
User avatar
By Mr Mayhem
#56366 Vince,

Thanks for your very quick reply. I have programmed for decades, but never much in c, so yeah, time to learn me some c pointers.

A couple of condensed points:

1. Private me on where to send you the money if you want it, or send me your email, etc and we can work it out. I will probably need to go around a few more times to clarify stuff, but I won't abuse it, and/or I will post some pics of my setup and trial code to benefit the ESP8266 community.

2. I have downloaded the zip you posted above, and will play with it and report back.

3. To try the new code, I assume I just need to back up the original SPISlave directory files and replace them with the new ones from your zip file? I am using Arduino IDE, I see the location of SPISlave directory is:
C:\Users\Me\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\2.3.0\libraries\SPISlave\

4. Newbie question: In SPISlave_Test.ino, (the sketch), how do I move the event handlers out of setup ()?

Example:
SPISlave.onDataSent
in the original code,

or the soon-to-be
SPISlave.onTrans
in the new code.

I noticed the event handlers in setup() end with });
presumably to keep them from running when setup() runs, yet be available.

Having them inside setup() seems kinda unconventional to me, but I don't know if they simply must be in setup() to work, or if its not worth putting them elsewhere because of other implications or performance penalties or extra typing, etc. Can I move them out of setup(), and how? I was getting compile errors earlier when I tried to move them. I don't know how to flatten the }); magic, heh.

5. Could you provide me with a simple example of copying 32 bytes from myBytes[512] array into SPISlave.setData() or similiar? I will make an honest effort to experiment here, but I am more than a little unsure still on the syntax to use, given that pointers are new to me.

I am off to carefully review your reply point by point, and the new code, and to experiment. Thanks again for your quick reply Vince.
User avatar
By Mr Mayhem
#56367 Vince,
Oh, so you are "getting fits" with properly sending 32 bits, not bytes. Sorry, maybe it was premature for me to ask point 5, example code of copying from byteArray[] to the SPI or SPISlave send 'mechanism'. Do you recall what the limit is per transfer? Was it 32 Bits or 32 Bytes? Seems to me if you can send "Hello are you Alive" we are talking 32 bytes as the limit, no? I wonder the boundaries of the "fits" you are getting. Does it do weird stuff when you try to send certain sizes of data?

Or does the "fits" happen from attempting to perform more than one transfer after another in quick succession within a loop or something? That could be a "I need more time in between transfers to handle what I got" kind of issue.