Efficiently dropping some bits from 32 data type variable by bit manipulation - Arduino Due

Hello,
MCU Arduino DUE. A 16bits AD7606 converter is connected in parallel to DUE, which is connected to Port C on DUE. I am trying to read the ADC conversion value from the C port in one command as efficiently as possible due to the time reduction. The read conversion value from AD is (example) uint32_t X= 0b00000000 00000011 11110011 11111100; Bits with log1 are valid conversion bits of the HW connection AD to port C on DUE).
It is necessary to delete bits C11,C10,C1,C0 from the uint32_t number X.
Using direct bit operations, I converted the value X to a 16-bit conversion value, which I need for further processing.

If I do the conversion step by step, the result is OK. However, if I do the conversion with one command, the result is not correct.

void setup() {
  Serial.begin(460800);  
  Serial.println("Program started");  delay(200);
}

void loop() {
  uint32_t X= 0b00000000000011111111001111111100;
  uint32_t A, B, C, D, E, F;
  Serial.print(F("X= ")); Serial.println(X, BIN);
  // This part is OK.
  A= (X >> 2) ;    Serial.print(F("A= ")); Serial.println(A, BIN);
  B= A & 0x3FC00;  Serial.print(F("B= ")); Serial.println(B, BIN);
  C= B>>2;         Serial.print(F("C= ")); Serial.println(C, BIN);
  D= ( (X >> 2) & 0xFF);   Serial.print(F("D= ")); Serial.println(D, BIN);
  E= C | D;        Serial.print(F("E= ")); Serial.println(E, BIN); // RESULT IS OK..16 bit value of ADC conversion

  // This part is incorrect
  F= ( ((((X >> 2)) & 0x3FC0))>>2 ) | ((X >> 2) & 0xFF);         Serial.print(F("F= ")); Serial.println(F, BIN); // RESULT IS NOT OK

  Serial.println(F("=============================")); 

  while(1);
}

Result:
X= 11111111001111111100
A= 111111110011111111
B= 111111110000000000
C= 1111111100000000
D= 11111111
E= 1111111111111111
F= 111111111111

Please advice where I make mistake?
Can anyone advise how to convert the value X as efficiently as possible in terms of conversion time to a 16-bit value (32-bit value) in a single conversion instruction using bitwise operations?

You started a topic in the Uncategorised category of the forum when its description explicitly tells you not to

Your topic has been moved to a relevant category. Please be careful in future when deciding where to start new topics

Different constants?

This

F = ((X >> 2) & 0xff) | ((X >> 4) & 0xff00);

use

  X = 0b11011110001010110100;

see

DEAD

a7

Why add 16 useless bits to a 16 bit starting value?

uint32_t X= 0b00000000000011111111001111111100;
//                        ^^^^^^^^  ^^^^^^^^
//                         UPPER8    LOWER8
uint16_t lower8bits = (X >> 2) & 0xFF;
uint16_t upper8bits = (X >> 10) & 0xFF;
uintt16_t value = (upper8bits << 8) | lower8bits;

with one instruction less.

uint32_t X= 0b00000000000011111111001111111100;
//                        ^^^^^^^^  ^^^^^^^^
//                         UPPER8    LOWER8
X = X >> 2;
//  X= 0b00000000000000111111110011111111;
uint16_t lower8bits = X & 0xFF;
//   lower8bits = 0b0000000011111111
uint16_t upper8bits = (X >> 2) & 0xFF00;
//  upper8bits = 0b1111111100000000
uintt16_t value = upper8bits | lower8bits;
//  value = 0b1111111111111111

Or in one line

uintt16_t value =  ((X >> 4) & 0xFF00) | ( (X >> 2) & 0xFF);
//  note that X is unchanged

That one-liner looks oddly familiar. :expressionless:

a7

1 Like

oops, sorry, missed your solution!

Thanks everyone for the answer. I appreciate your quick response.
I tested your suggestion uint16_t value = ((X >> 4) & 0xFF00) | ( (X >> 2) & 0xFF); and it is OK.

On the Arduino DUE port C, in addition to the pins that are set as inputs for the AD7606 conversion, there are also pins that are set as outputs.

I plan to use your solution to load all 8 channels of the ADC7606:

uint16_t Data[8];
for (uint8_t i = 0; i < 8; i = i + 1) {
   Data[i] = ((PIOC->PIO_PDSR >> 4) & 0xFF00) | ( PIOC->PIO_PDSR >> 2) & 0xFF);
}

My question is, can I safely read the PIOC->PIO_PDSR register, which also contains the 16-bit ADC conversion value, if some pins on port C are set as inputs (pins other than the inputs to which the ADC conversion is stored)?
Is it possible to read PIOC->PIO_PDSR when there is a combination of inputs and outputs on port C without the risk of destroying the DUE?

Thanks in advance for your answer

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.