Search code examples
arrayscbit-manipulationbitwise-operatorsbit-shift

bit manipulation function does not give the required result


I'm trying to write a function that take a const char array and for every byte I'm trying to get the bits and spread them into 4 bytes where the bits are assigned to bit 2 and 5 of the 4 bytes,

int encryptDataAndSend(const char *logName, const char *data)
{
  const int len = strlen(data);
  printf("data length: %d \n", strlen(data));
  char encryptedData[len * 4 + 1];
  for (uint8_t i = 0; i < len; i++)
  {
    uint8_t v1 = 255;
    uint8_t v2 = 255;
    uint8_t v3 = 255;
    uint8_t v4 = 255;

    int bit0 = data[i] & (1 << 0);
    int bit1 = data[i] & (1 << 1);
    int bit2 = data[i] & (1 << 2);
    int bit3 = data[i] & (1 << 3);
    int bit4 = data[i] & (1 << 4);
    int bit5 = data[i] & (1 << 5);
    int bit6 = data[i] & (1 << 6);
    int bit7 = data[i] & (1 << 7);

    char temp[4] = {0};

    printf("char is %d \n", data[i]);
    printf("bits: %d %d %d %d %d %d %d %d \n", bit7, bit6, bit5, bit4, bit3, bit2, bit1, bit0);

    v1 = (v1 & ~(1 << 2)) | (bit0 << 2);
    v1 = (v1 & ~(1 << 5)) | (bit1 << 5);
    printf("v1 : %d \n", v1);
    v2 = (v2 & ~(1 << 2)) | (bit2 << 2);
    v2 = (v2 & ~(1 << 5)) | (bit3 << 5);
    printf("v2 : %d \n", v2);
    v3 = (v3 & ~(1 << 2)) | (bit4 << 2);
    v3 = (v3 & ~(1 << 5)) | (bit5 << 5);
    printf("v3 : %d \n", v3);
    v4 = (v4 & ~(1 << 2)) | (bit6 << 2);
    v4 = (v4 & ~(1 << 5)) | (bit7 << 5);
    printf("v4 : %d \n", v4);
    temp[0] = v1;
    temp[1] = v2;
    temp[2] = v3;
    temp[3] = v4;
    memcpy(encryptedData + 4 * i, temp, 4);
    // encryptedData[len * 4] = 0;
  }
  printf("encrypted data: %s", encryptedData);
  const int txBytes = uart_write_bytes(UART_NUM_2, encryptedData, strlen(encryptedData));
  ESP_LOGI(logName, "Wrote %d bytes", txBytes);
  ESP_LOG_BUFFER_HEX("SENDDATA_TAG", encryptedData, txBytes);
  return txBytes;
}

The way I call the function is

encryptDataAndSend(TX_TASK_TAG, "BF");

so the results should be 8 bytes where the 8 bits of B is split into 4 bytes and placed in the 2nd and 5th bit positions of the new bytes and then the 8 bits of F is split into 4 bytes and placed in the 2nd and 5th positions of the new bytes.

at the moment I'm not getting the correct results, I always get the same numbers, is the bit setting and checking correct, any help would be appreciated!


Solution

  • Looking at the output:

    data length: 2 
    char is 66 
    bits: 0 64 0 0 0 0 2 0 
    v1 : 219 
    v2 : 219 
    v3 : 219 
    v4 : 219 
    char is 70 
    bits: 0 64 0 0 0 4 2 0 
    v1 : 219 
    v2 : 219 
    v3 : 219 
    v4 : 219 
    

    Your bit0 ... bit7 variables contain the values of the bits that are set, for example bit6 has the value 64 i.e. bit 6 of bit6 is set. When you later try to push that value into the destination:

    v4 = (v4 & ~(1 << 2)) | (bit6 << 2);
    

    bit6 << 2 has the value 256 i.e. bit 9 is set which you then OR into v4.

    Your bitn variables should contain either 0 or 1 if the bit in question is set or not set:

    int bit0 = (data[i] & (1 << 0)) != 0;
    int bit1 = (data[i] & (1 << 1)) != 0;
    int bit2 = (data[i] & (1 << 2)) != 0;
    int bit3 = (data[i] & (1 << 3)) != 0;
    int bit4 = (data[i] & (1 << 4)) != 0;
    int bit5 = (data[i] & (1 << 5)) != 0;
    int bit6 = (data[i] & (1 << 6)) != 0;
    int bit7 = (data[i] & (1 << 7)) != 0;
    

    Output (with extra hex printing):

    data length: 2 
    char is 66 
    bits: 0 1 0 0 0 0 1 0 
    v1 : 251 fb 
    v2 : 219 db 
    v3 : 219 db 
    v4 : 223 df 
    char is 70 
    bits: 0 1 0 0 0 1 1 0 
    v1 : 251 fb 
    v2 : 223 df 
    v3 : 219 db 
    v4 : 223 df 
    

    Also, you're attempting to print encryptedData as a string and call strlen on it, but you don't put a null terminator on it (although you seem to have a statement to do that commented out). Since you know how long your byte array is, just use len * 4 instead of strlen(encryptedData)