Add mask to a byte-array knowing bits length and starting position

Viewed 552

I have to apply a bit mask to a CAN-bus payload message (8 bytes) to filter a single signal (there are a multiple signals in a message) in Python 3 and my inputs are:

  • Length of the signal I want to filter in binary (think about a set of '1's).
  • The starting position of the signal. The problem is that the signal can start in the middle of a byte and occupy more than 1 byte.

For example I have to filter a signal with starting bit position = 50 and length = 10 The mask will be byte 6 = (00111111) and byte 7 = (11000000). All other bytes set to 0.

I've tried to build an array of bytes with 1's and then apply | with an empty 8-byte length array to have the mask. And also create directly the 8-byte array but can't achieve how to bitwise correctly the starting position. I tried with bitstring module and bytearray but can't find a good solution.

Could anyone help?

Thank you very much.

Edit: adding non-functional code if signal starts in the middle of byte:

my_mask_byte = [0, 0, 0, 0, 0, 0, 0, 0]
message_bit_pos = 50
message_signal_lenght = 10
byte_pos = message_bit_pos // 8
bit_pos = message_bit_pos % 8

for i in range(0, message_signal_lenght):
    if i < 8:
        my_mask_byte[byte_pos + i // 8] = 1 << i + bit_pos | my_mask_byte[byte_pos + i // 8]
    else:
        my_mask_byte[byte_pos + i // 8] = 1 << i-8 | my_mask_byte[byte_pos + i // 8]

for byte in my_mask_byte:
    print(bin(byte))
1 Answers

byte 6 = (00111111) and byte 7 = (11110000)

You missed 2 bits since length is 10.


You can easily achieve this with numpy:

import numpy as np

message_bit_pos = 50
message_signal_length = 10

mask = np.uint64(0)
while message_signal_length > 0:
    mask |= np.uint64(1 << (64-50-message_signal_length))
    message_signal_length -= 1
print(f'mask: 0b{mask:064b}')

n = np.uint64(0b0000000000000000011000000000000000000000000000000011111111000000)
print(f'n:    0b{n:064b}')
n &= mask
print(f'n&m:  0b{n:064b}')

output:

mask: 0b0000000000000000000000000000000000000000000000000011111111110000
n:    0b0000000000000000011000000000000000000000000000000011111111000000
n&m:  0b0000000000000000000000000000000000000000000000000011111111000000
Related