bitClear / bitWrite / bitSet / bitRead .. Array ..

Hi.

I've been trying out bit functions.

This is my current state of code:

byte outputBufferA[16] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };     
byte outputBufferB[16] =  { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; 
int bitPosA[16] = { 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3 };
int bitPosB[16] = { 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3 };

void setup() {

  Serial.begin(115200);
  Serial.println("READY!");

}


void loop() {

  for (int i = 0; i < 16; i++) {

    outputBufferA[i] = bitSet(outputBufferA[i], bitPosA[i]);
    outputBufferB[i] = bitClear(outputBufferB[i], bitPosB[i]);

    Serial.println(outputBufferA[i], BIN);
    Serial.println(outputBufferB[i], BIN);

    delay(1000);

  }
}

What I am trying to achieve is that every time the loop is run, eventually all of each buffer is filled with '0's or '1's depending on which array they are set to (IE. outputBufferA - HIGH / outputBufferB - LOW).

However, the readouts via serial just shifts the 0/1 across to the relevant position, and does not retain the change from the previous write..

How do I achieve what I have set out to do?

Thanks in advance.

All the best!!

outputBufferA[i] = bitSet(outputBufferA[i], bitPosA[i]);

What is bitSet(outputBufferA[i], bitPosA[i]); doing on the right hand side of an assignment ?

Hi Helibob.

I'm fairly new to programming, so this especially is all new to me..

I assumed that it would be ok to have it written this way?

I've tried the following, which all yield the same results:

int a = bitSet(outputBufferA[i], bitPosA[i]);
int b = bitClear(outputBufferB[i], bitPosB[i]);
Serial.println(a, BIN);
Serial.println(b, BIN);
bitSet(outputBufferA[i], bitPosA[i]);
bitClear(outputBufferB[i], bitPosB[i]);
Serial.println(outputBufferA[i], BIN);
Serial.println(outputBufferB[i], BIN);
bitSet(outputBufferA[i], bitPosA[i]);
bitClear(outputBufferB[i], bitPosB[i]);
outputBufferA[i] = outputBufferA[i];
outputBufferB[i] = outputBufferB[i];
   
Serial.println(outputBufferA[i], BIN);
Serial.println(outputBufferB[i], BIN);

I have tried to look for tutorials, but am not sure where to look etc?

Also, out of interest / learning, why is it that I should not put the following?

outputBufferA[i] = bitSet(outputBufferA[i], bitPosA[i]);

Thanks in advance!

You need a nested for loop to change all the bits of each byte in your array. I think this sketch does what you intended.

byte outputBufferA[16] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
byte outputBufferB[16] =  { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
//int bitPosA[16] = { 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3 };
//int bitPosB[16] = { 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3 };
int bitPosA[8] = {0, 1, 2, 3, 4, 5, 6, 7};
int bitPosB[8] = {0, 1, 2, 3, 4, 5, 6, 7};
void setup() {

  Serial.begin(9600);
  Serial.println("READY!");

}


void loop() {

  for (int i = 0; i < 16; i++) {

    for (int j = 0; j < 8; j++) {

      outputBufferA[i] = bitSet(outputBufferA[i], bitPosA[j]);
      outputBufferB[i] = bitClear(outputBufferB[i], bitPosB[j]);

      Serial.println(outputBufferA[i], BIN);
      Serial.println(outputBufferB[i], BIN);

      delay(500);
    }
    Serial.println();
    Serial.print(outputBufferA[i], BIN);
    Serial.print('\t');
    Serial.print(outputBufferB[i], BIN);
    Serial.print('\t');
    Serial.print("outputBufferIndex ");
    Serial.println(i);
    Serial.println();
  }
}

If you wanted to set all the bits, what did you think that this was going to do ??

int bitPosA[16] = { 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3 };

Do you actually want to set all the bits, or only half of them ?

I was using "bitPosA" to write to the byte position.

eg.

if (i == 0)
{
bitSet(0x00, 0, HIGH);
bitSet(0xFF, 0, LOW);
}

or

if (i == 12)
{
bitSet(0x00, 3, HIGH);
bitSet(0xFF, 3, LOW);
}

Then store it in to the array so next time around the loop this value gets recalled:

outputBufferA[i] = bitSet(outputBufferA[i], bitPosA[j]);
outputBufferB[i] = bitClear(outputBufferB[i], bitPosB[j]);

I've just tried cattledogs code, and it doesn't remember in the next loop around.

I'm looking to store the bit that has been changed inside the array, so that on the next loop count it still 'exists'.

To explain a bit further (in case I'm being confusing).

I'd like to read the value from the array, change it, store it, then move on to the next part of the array and repeat the process.

At the start of the new loop the same process occurs, but reads the old values.

After trying your code cattledog, it almost does what I need, but the values 'reset' after each round of the loop.

I used '0,1,2,3,0,1...' because these are gate positions in a larger program for a shift register (hence not 0,1,2,3..15).

I'll write up a better example in the morning as it's getting a little late here now.
It should show a bit more of what I am trying to attempt.

Thank you to those that have replied so far.
Hopefully someone can find a solution after I post it as it's driving me around the bend over the last couple of weeks!

cattledog:
Are you saying that you want outputBufferA and outputBufferB to go back their original values after the full array has been inverted?

I think you just need at place at the bottom of the loop

if(i==0){

outputBufferA[16] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };   
outputBufferB[16] =  { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }
}

I am trying to get them to store, so that they next time they are read, they stay in that part of the array.

This isn't the complete code, just one part I've been trying to get rid of the bugs for in one of my home projects.

The idea is that values are read earlier in the loop and then used to switch the bits, but stay in their last position until they are changed back.

The main part of the program needs to take 16 readings, which then get sent to a four part array.

Within the main loop there will be multiple readings taken, all doing different things to this array until the very end of the loop, where it prints out one of the four final values.

I'm not sure if this makes much sense or not, but I will try my best to explain further if I am not being very clear.

I'm not sure if this is what you want, but at the end of one complete loop inverting the two arrays, you can reverse the process of bitSet and bitClear to reset the arrays back to their original states.

byte outputBufferA[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
byte outputBufferB[] =  { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
//int bitPosA[16] = { 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3 };
//int bitPosB[16] = { 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3 };
int bitPosA[8] = {0, 1, 2, 3, 4, 5, 6, 7};
int bitPosB[8] = {0, 1, 2, 3, 4, 5, 6, 7};
void setup() {

  Serial.begin(9600);
  Serial.println("READY!");

}


void loop() {
  static int i = 0;
  static int j = 0;

  for ( i = 0; i < 16; i++) {

    for ( j = 0; j < 8; j++) {

      outputBufferA[i] = bitSet(outputBufferA[i], bitPosA[j]);
      outputBufferB[i] = bitClear(outputBufferB[i], bitPosB[j]);

      Serial.println(outputBufferA[i], BIN);
      Serial.println(outputBufferB[i], BIN);

      delay(100);
    }
    Serial.println();
    Serial.print(outputBufferA[i], BIN);
    Serial.print('\t');
    Serial.print(outputBufferB[i], BIN);
    Serial.print('\t');
    Serial.print("outputBufferIndex ");
    Serial.println(i);
    Serial.println();
    if (i == 15) {
      Serial.println("resetting arrays to original values");
      for (i = 0; i < 16; i++) {
        for (j = 0; j < 8; j++) {
          outputBufferA[i] =  bitClear(outputBufferA[i], bitPosA[j]);
          outputBufferB[i] =  bitSet(outputBufferB[i], bitPosB[j]);
        }
      }
    }
  }
}

I've just written this up to show what I am trying to do, hopefully this will make a little more sense than what I posted before.

// Loop variables
int i;
int k;

// Variable to temporarliy store incoming data
byte dataA;

// Data arrays to compare incoming serial data
int dataAreg[16] = { 0x01, 0x03, 0x05, 0x07, 0x09, 0x0B, 0x0D, 0x0F, 0x11, 0x13, 0x15, 0x17, 0x19, 0x1B, 0x1D, 0x1F };
int dataBreg[16] = { 0x02, 0x04, 0x06, 0x08, 0x0A, 0x0C, 0x0E, 0x10, 0x12, 0x14, 0x16, 0x18, 0x1A, 0x1C, 0x1E, 0x20 };

// Arrays for storing data
unsigned int outputBufferA0[16] = { 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 };
unsigned int outputBufferB0[16] = { 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF };

// Arrays to store four parts of the array to send at the end of loop
unsigned int outputBufferA1[4];
unsigned int outputBufferB1[4];

// Create two bit array registers that we can call on - These are specific non linear values
int outputBitA[16] = { 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3 };
int outputBitB[16] = { 8, 8, 8, 8, 9, 9, 9, 9, 10, 10, 10, 10, 11, 11, 11, 11 };


void setup() {

  Serial.begin(9600);
  Serial.print("READY!");

}



void loop() {

  // Check to see if there is any serial data coming in
  if (Serial.available() > 0) {

    // Store incoming data in to the variable
    dataA = Serial.read();

    // Inititialise i loop
    for (int i = 0; i < 4; i++) {

      // Inititialise k loop
      for (k = 0; k < 16; k++) {

        // Compare incoming data to the array
        if (dataA == dataAreg[k]) {

          // Change a specific bit and store in the buffer array
          outputBufferA1[i] = bitWrite(outputBufferA0[i], outputBitA[k], HIGH);
          outputBufferB1[i] = bitWrite(outputBufferB0[i], outputBitA[k], LOW);

          // Store the new values back in to a four part array for later
          outputBufferA0[k] = outputBufferA1[i];
          outputBufferB0[k] = outputBufferB1[i];

        }

        // Compare incoming data to the array
        if (dataA == dataBreg[k]) {

          // Change a specific bit and store in the buffer array
          outputBufferA1[i] = bitWrite(outputBufferA0[i], outputBitA[k], LOW);
          outputBufferB1[i] = bitWrite(outputBufferB0[i], outputBitB[k], HIGH);

          // Store the new values back in to a four part array for later
          outputBufferA0[i] = outputBufferA1[i];
          outputBufferB0[i] = outputBufferB1[i];

        }

      }

      // Send out the new current values from the four part array
      Serial.println(outputBufferA1[i], BIN);
      Serial.println(outputBufferB1[i], BIN);

    }
    
  }
  
}

outputBufferA1[i] = bitWrite(outputBufferA0[k], outputBitA[k], HIGH);I am still not getting this.
bitWrite() writes a bit with a value, so what is it doing on the righthand side of the assignment ?

Can you please explain in words what that line is supposed to do ?

UKHeliBob:

outputBufferA1[i] = bitWrite(outputBufferA0[k], outputBitA[k], HIGH);

I am still not getting this.
bitWrite() writes a bit with a value, so what is it doing on the righthand side of the assignment ?

Can you please explain in words what that line is supposed to do ?

I'm confused..

Is this:

  outputBufferA1[i] = bitWrite(outputBufferA0[i], outputBitA[k], HIGH);

Not the same as this?

  bitWrite(outputBufferA0[i], outputBitA[k], HIGH);
  outputBufferA1[i] = outputBufferA0[k];

I'm not sure as to how this effects things ? Please could you explain as to why this is incorrect ?

I am trying to change one bit in the current position of the array, and then store it and pass it on to the output..

Expected outputs :

  if (dataA == 0x01)
  {
    outputBufferA0[0] = 0x0001;              // Or B0000000000000001
    outputBufferB0[0] = 0xFEFF;              // Or B1111111011111111
  }

This is then stored in the original array:

outputBufferA1[0] = 0x0001;              // Or B0000000000000001
outputBufferB1[0] = 0xFEFF;              // Or B1111111011111111
outputBufferA0[0] = outputBufferA1[0];
outputBufferB0[0] = outputBufferB1[0];

Then, changing this with a new value:

if (dataA == 0x0A)
{
  outputBufferA0[0] = 0x0000;              // Or B0000000000000000
  outputBufferB0[0] = 0xFFFF;              // Or B1111111111111111
  outputBufferA0[0] = outputBufferA1[4];
  outputBufferB0[0] = outputBufferB1[4];
}

Then, taking the old values and changing it with a new value:

outputBufferA0[0] = 0x0001;
outputBufferB0[0] = 0xFEFF;

if (dataA == 0x11)
{
  outputBufferA0[0] = 0x0001;              // Or B0000000000000001
  outputBufferB0[0] = 0xFAFF;              // Or B1111101011111111
}

Then, if dataA == 0x19 after the last change:

outputBufferA0[0] = 0x0001;
outputBufferB0[0] = 0xFAFF;

if (dataA == 0x19)
{
  outputBufferA0[0] = 0x0001;              // Or B0000000000000001
  outputBufferB0[0] = 0xF2FF;              // Or B1111001011111111
}

I didn't say that what you were doing did not work, rather I wanted to make sure that it was doing what you wanted and that I understood your intentions. I don't know about others here but to me

bitWrite(outputBufferA0[i], outputBitA[k], HIGH);
  outputBufferA1[i] = outputBufferA0[k];

reads more naturally. You are not left wondering what is going on and/or what is intended. Each line of code stands alone, is explicit and it is obvious what will happen and in what order. It is almost certain that the compiler will optimise the code anyway and to me making the source code readable is an important part of writing the program.

UKHeliBob:
I didn't say that what you were doing did not work, rather I wanted to make sure that it was doing what you wanted and that I understood your intentions. I don't know about others here but to me

bitWrite(outputBufferA0[i], outputBitA[k], HIGH);

outputBufferA1[i] = outputBufferA0[k];



reads more naturally. You are not left wondering what is going on and/or what is intended. Each line of code stands alone, is explicit and it is obvious what will happen and in what order. It is almost certain that the compiler will optimise the code anyway and to me making the source code readable is an important part of writing the program.

Cool!

So, what about the issue I'm experiencing?

What can be done to get this to work as expected?

outputBufferA1[i] = bitWrite(outputBufferA0[i], outputBitA[k], HIGH);
          outputBufferB1[i] = bitWrite(outputBufferB0[i], outputBitA[k], LOW);

outputBufferA1 and outputBufferB1 have 4 elements each. You are making them equal to
outPutBufferAO and outputBufferBO (after some bit changes) which have 16 elements each. You are using memory you don't have.

Ok..

So, how can I read the data coming in, compare to the serial in the register (dataA against dataBreg) then make the relevant bit change, store this for the next loop?

I've realised I don't need 16 parts of the array for the buffer, but how do I compare against the register (outputBitA and outputBitB) and then pass this through to the four part array?

..To put it another way.

When 0x01 is fed in, I need that to switch on x bits on bufferA / B.

When the next value comes in, I don't want this to be changed until 0x02 comes in.

So anything else that comes in won't effect the data that's already come in.

For example:

If 0x03, 0x0B and 0x13 (positions 1, 5 and 9 in frame 1) comes through, the data out should then be:

outputBufferA = B 0000 0000 0000 0010
outputBufferB = B 1111 1000 1111 1111

But then, if position 5 is switched off (so that the other bits stay on, and outputBufferB is still active:

outputBufferA = B 0000 0000 0000 0010
outputBufferB = B 1111 1010 1111 1111

This needs to be stored in 4 frames (hence outputBuffer[1-4]) for it to work correctly.

(I've tried to bitwise all of this, but come unstuck in the same manner!)

Robin2 has written an excellent tutorial on reading serial data. Serial Input Basics - Programming Questions - Arduino Forum

If you choose to input characters representing numbers in hex you will need to use strtol with base 16 rather than atoi to convert your character input to numbers.

void setup() {
  Serial.begin(9600);
  int dataAreg[16] = { 0x01, 0x03, 0x05, 0x07, 0x09,
                       0x0B, 0x0D, 0x0F, 0x11, 0x13, 0x15, 0x17, 0x19, 0x1B,
                       0x1D, 0x1F
                     };
  char hex_string[] = "0x1D";
  Serial.println(hex_string);
  long val = strtol(hex_string, NULL, 16);
  Serial.println(val);
  for (int i = 0; i < 15; i++) {
    if (dataAreg[i] == val) {
      Serial.print ("match at index ");
      Serial.println(i);
    }
  }
}

void loop() {}

Since you are really only trying to find an array index matching the input, you could also have dataAreg and dataBreg be 2 dimensional arrays of character strings and use strcmp to test the input without conversion.

void setup() {
  Serial.begin (9600);
  char dataAreg[16][5] = { "0x01", "0x03", "0x05", "0x07", "0x09",
                           "0x0B", "0x0D", "0x0F", "0x11", "0x13", "0x15", "0x17", "0x19", "0x1B",
                           "0x1D", "0x1F"
                         };

  char hex_string[5] = {"0x1D"};
  Serial.println(hex_string);

  for (int i = 0; i < 16; i++) {
    if (strcmp(dataAreg[i], hex_string) == 0)
    {
      Serial.print("match at index ");
      Serial.println(i);
    }
  }
}

void loop() {}

cattledog:
Robin2 has written an excellent tutorial on reading serial data. http://forum.arduino.cc/index.php?topic=288234.0

If you choose to input characters representing numbers in hex you will need to use strtol with base 16 rather than atoi to convert your character input to numbers.

void setup() {

Serial.begin(9600);
  int dataAreg[16] = { 0x01, 0x03, 0x05, 0x07, 0x09,
                      0x0B, 0x0D, 0x0F, 0x11, 0x13, 0x15, 0x17, 0x19, 0x1B,
                      0x1D, 0x1F
                    };
  char hex_string[] = "0x1D";
  Serial.println(hex_string);
  long val = strtol(hex_string, NULL, 16);
  Serial.println(val);
  for (int i = 0; i < 15; i++) {
    if (dataAreg[i] == val) {
      Serial.print ("match at index ");
      Serial.println(i);
    }
  }
}

void loop() {}




Since you are really only trying to find an array index matching the input, you could also have dataAreg and dataBreg be 2 dimensional arrays of character strings and use strcmp to test the input without conversion.


void setup() {
  Serial.begin (9600);
  char dataAreg[16][5] = { "0x01", "0x03", "0x05", "0x07", "0x09",
                          "0x0B", "0x0D", "0x0F", "0x11", "0x13", "0x15", "0x17", "0x19", "0x1B",
                          "0x1D", "0x1F"
                        };

char hex_string[5] = {"0x1D"};
  Serial.println(hex_string);

for (int i = 0; i < 16; i++) {
    if (strcmp(dataAreg[i], hex_string) == 0)
    {
      Serial.print("match at index ");
      Serial.println(i);
    }
  }
}

void loop() {}

I appreciate this...

However, I haven't got a problem with the input. It's translating it to bits. There are 16 options, but I need to fit it in to an array of 4.

One problem I can see is that when I wish to flip some of outputBufferB to low, one's that I need to remain high are then shut off.

I've tried to use outputBufferB1 = outputBufferB1 | outputBufferB0 etc, but this still is not working for me.

When the loop completes it doesn't seem to retain the data in the way that I require.