user7392: Background
I'm reading a 24-bit ADC value into a uint32. Using SPI bus, here's the logic:
value = SPI.transfer(0);   // read first 8 bits (MSB first)
value <<= 8;               // shift bits left
value |= SPI.transfer(0);  // read next 8 bits
value <<= 8;               // shift bits left
value |= SPI.transfer(0);  // read final 8 bits

As such I'm left with this ADC reading:
00000000 11111111 11111111 11111111
         MSB                    LSB

(Ignore the leading zeros for now.)
Now I transfer this value over ethernet like so:
client.write((const byte*) &value, sizeof(value));

The problem is this:

The value is stored as MS bit first.
client.write() transmits it LS byte first.

I am using NodeRED as a TCP server. So at the other end, I receive the data like this:
11111111 11111111 11111111 00000000
     LSB          MSB

I understand this is the expected behavior, but I would like to switch the BYTE order around before sending, so that it is read in NodeRed native endianness.

Question
Perhaps I should do some bit shifting at the point of reading the ADC, to accommodate the fact that client.write() sends the least significant byte first, like this:
  byte1 = SPI.transfer(0);
  byte2 = SPI.transfer(0);
  byte3 = SPI.transfer(0);
  response = byte3;
  response <<= 8;
  response = byte2;
  response <<= 8;
  response = byte1;

Is this the most efficient way in terms of clock cycles?
Please note that my MCU is a Teensy 4.1, and I'm transferring 10,000 readings per second. I would like to keep the clock cycles for any necessary bitwise operations to a minimum, so that the timing of ADC readings are affected as little as possible.

user60431: You can use an array of byte to save the shifts at all. This solution should be the one with the least clock cycles, and with no additional memory usage.
static byte value[4] = { 0 };

    /* ... */

    /* value[0] is still 0. */
    value[1] = SPI.transfer(0);
    value[2] = SPI.transfer(0);
    value[3] = SPI.transfer(0);

    client.write(value, sizeof value);

Some notes:

Using an array avoids the re-interpretation of a 32 bit variable as a byte array. You read bytes from SPI, and write() expects a byte array. This circumvents your endianness issue completely.

In the call of write() you don't need to cast the address of value to const byte *, because the const is a qualifier for the called function. It is not allowed to change the bytes pointed to.

Making the array static saves you from zeroing the first byte repeatedly. BTW, it is sufficient to provide the first byte, as all other bytes are zeroed automatically. However, the last bytes will be updated on each transfer.

sizeof is an operator, not a function. However, it is quite common to use it with a type instead of an object, and then you need parentheses because of the syntax. But it is better to use the respective object, actually you mean that.



7392: <p><strong>Background</strong></p>
<p>I'm reading a 24-bit ADC value into a uint32. Using SPI bus, here's the logic:</p>
<pre><code>value = SPI.transfer(0);   // read first 8 bits (MSB first)
value &lt;&lt;= 8;               // shift bits left
value |= SPI.transfer(0);  // read next 8 bits
value &lt;&lt;= 8;               // shift bits left
value |= SPI.transfer(0);  // read final 8 bits
</code></pre>
<p>As such I'm left with this ADC reading:</p>
<pre><code>00000000 11111111 11111111 11111111
         MSB                    LSB
</code></pre>
<p>(Ignore the leading zeros for now.)</p>
<p>Now I transfer this value over ethernet like so:</p>
<pre><code>client.write((const byte*) &amp;value, sizeof(value));
</code></pre>
<p>The problem is this:</p>
<ul>
<li>The value is stored as MS <strong>bit</strong> first.</li>
<li>client.write() transmits it LS <strong>byte</strong> first.</li>
</ul>
<p>I am using NodeRED as a TCP server. So at the other end, I receive the data like this:</p>
<pre><code>11111111 11111111 11111111 00000000
     LSB          MSB
</code></pre>
<p>I understand this is the expected behavior, but I would like to switch the BYTE order around before sending, so that it is read in NodeRed native endianness.</p>
<hr />
<p><strong>Question</strong></p>
<p>Perhaps I should do some bit shifting at the point of reading the ADC, to accommodate the fact that client.write() sends the least significant byte first, like this:</p>
<pre><code>  byte1 = SPI.transfer(0);
  byte2 = SPI.transfer(0);
  byte3 = SPI.transfer(0);
  response = byte3;
  response &lt;&lt;= 8;
  response = byte2;
  response &lt;&lt;= 8;
  response = byte1;
</code></pre>
<p>Is this the most efficient way in terms of clock cycles?</p>
<p>Please note that my MCU is a Teensy 4.1, and I'm transferring 10,000 readings per second. I would like to keep the clock cycles for any necessary bitwise operations to a minimum, so that the timing of ADC readings are affected as little as possible.</p>
 60431: <p>You can use an array of <code>byte</code> to save the shifts at all. This solution should be the one with the least clock cycles, and with no additional memory usage.</p>
<pre class="lang-c prettyprint-override"><code>static byte value[4] = { 0 };

    /* ... */

    /* value[0] is still 0. */
    value[1] = SPI.transfer(0);
    value[2] = SPI.transfer(0);
    value[3] = SPI.transfer(0);

    client.write(value, sizeof value);
</code></pre>
<p>Some notes:</p>
<ol>
<li><p>Using an array avoids the re-interpretation of a 32 bit variable as a byte array. You read bytes from SPI, and <code>write()</code> expects a byte array. This circumvents your endianness issue completely.</p>
</li>
<li><p>In the call of <code>write()</code> you don't need to cast the address of <code>value</code> to <code>const byte *</code>, because the <code>const</code> is a qualifier <em>for the called function</em>. It is not allowed to change the bytes pointed to.</p>
</li>
<li><p>Making the array static saves you from zeroing the first byte repeatedly. BTW, it is sufficient to provide the first byte, as all other bytes are zeroed automatically. However, the last bytes will be updated on each transfer.</p>
</li>
<li><p><code>sizeof</code> is an operator, not a function. However, it is quite common to use it with a type instead of an object, and then you need parentheses because of the syntax. But it is better to use the respective object, actually you mean that.</p>
</li>
</ol>
