|
|
View previous topic :: View next topic |
Author |
Message |
cbarberis
Joined: 01 Oct 2003 Posts: 172 Location: Punta Gorda, Florida USA
|
Question on bit manipulation for data extraction |
Posted: Fri Jan 04, 2019 6:07 pm |
|
|
Hello,
I am trying to capture slow SENT data which is somewhat complicated, basically slow SENT data is embedded in the first status nibble of a SENT data frame, bits 3 and 2 are used to create two separate data fields. So I am taking 18 frames of SENT data one bit at a time to build these two 32 bit variables each with 18 bits of data.
The problem here is that this data contains mixed data channels within the 18 bit data field so it becomes rather difficult extracting the data, using a simple bit mask does not do it, I believe you need to use bit mask and bit shift operations to extract this data.
Just to be more descriptive about what I am trying to do is to extract one byte (or 2 nibbles) of data from the 18 bit data below, in this case the value should be 0xFF.
bit 1 is the MSB and bit 18 is the LSB however, bits 13 and bit 18 are always set to 0 or in other words they are not used. Bits 1 through 8 are don’t care bits and can be easily be masked off. So what I am trying to do is extract the data from bit 9-12 for the MS nibble and bits 14 through 17 for the least significant nibble.
I know there is a lot of smart people on this forum that will probably have a simple solution.
Code: |
bit position # -> 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
t value -> x x x x x x x x 1 1 1 1 0 1 1 1 1 0
|
|
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9226 Location: Greensville,Ontario
|
|
Posted: Fri Jan 04, 2019 7:45 pm |
|
|
Ok, I've been staring at this for ...well..too long.... and came up with...
// assign bits for easy manipulations
// one input word, one output word
int16 inpval;
#bit inpval_0 = inpval.0
#bit inpval_1 = inpval.1
#bit inpval_2 = inpval.2
#bit inpval_3 = inpval.3
#bit inpval_4 = inpval.4
#bit inpval_5 = inpval.5
#bit inpval_6 = inpval.6
#bit inpval_7 = inpval.7
#bit inpval_8 = inpval.8
#bit inpval_9 = inpval.9
#bit inpval_10 = inpval.10
#bit inpval_11= inpval.11
#bit inpval_12= inpval.12
#bit inpval_13 = inpval.13
#bit inpval_14= inpval.14
#bit inpval_15= inpval.15
int16 outval;
#bit outval_0 = outval.0
#bit outval_1= outval.1
#bit outval_2 = outval.2
#bit outval_3 = outval.3
#bit outval_4 = outval.4
#bit outval_5 = outval.5
#bit outval_6 = outval.6
#bit outval_7 = outval.7
#bit outval_8 = outval.8
#bit outval_9 = outval.9
#bit outval_10 = outval.10
#bit outval_11= outval.11
#bit outval_12 =outval.12
#bit outval_13= outval.13
#bit outval_14= outval.14
#bit outval_15= outval.15
// disassembly from code that compiled !
111: inpval_3=1; //set bit 3 of input word
0608 8622 BSF 0x22, 0x3, ACCESS
// the actual bit 'transfer'
112: outval_8=inpval_3;
060A 9025 BCF 0x25, 0, ACCESS
060C B622 BTFSC 0x22, 0x3, ACCESS
060E 8025 BSF 0x25, 0, ACCESS
1st line clears the output bit
2nd line tests the input bit,skips next line if clear(0)
3rd line sets output bit if needed
yes ,it's rough but seems to work....
inpval is your 16bit raw data bits...
outval is the data as you want it formatted
to use simply code which input bit is to be sent to what output bit
in my example input bit 3 is set high, then it is transferred to output bit8.
There's probably a more elegant way to do it, but the code is 'tight' and easy to understand.
You'll have to expand for 32 bit data of course.
I'm sure the 'pros' will have a pretty way to do it...
Jay |
|
|
cbarberis
Joined: 01 Oct 2003 Posts: 172 Location: Punta Gorda, Florida USA
|
|
Posted: Fri Jan 04, 2019 8:15 pm |
|
|
Hey Thank you Jay, I will give this a try, so far I did not come up with any elegant ideas. |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19510
|
|
Posted: Sat Jan 05, 2019 1:25 am |
|
|
Code efficient approach relies on realising two things:
1) The first value is simply the low nibble of the upper byte.
2) The second value is the high nibble of the upper byte, if the value has
been shifted down by one bit.
These can be obtained efficiently (both in processor terms, and C terms), with:
Code: |
union {
int32 value;
int8 bytes[4];
} source;
unsigned int8 low, high;
source.value=0x01EF00; //the source value you show
low=source.bytes[1] & 0xF; //Low nibble of high byte
source.value<<=1; //Move down by one bit
high=swap(source.bytes[1]) & 0xF; //high nibble of shifted byte
|
The 'swap' instruction, is a PIC specific bit of CCS code, that uses the
internal swap instruction to swap the low and high nibbles in a byte
in just one instruction.
Doing it this way avoids the huge number of rotations otherwise needed. |
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9226 Location: Greensville,Ontario
|
|
Posted: Sat Jan 05, 2019 6:33 am |
|
|
Here's Mr. T's code disassembled..
Code: |
//presetting input data
122: source.value=0x01EF00; //the source value you show
0610 6A29 CLRF 0x29, ACCESS
0612 0E01 MOVLW 0x1
0614 6E28 MOVWF 0x28, ACCESS
0616 0EEF MOVLW 0xef
0618 6E27 MOVWF 0x27, ACCESS
061A 6A26 CLRF 0x26, ACCESS
123:
// actual parsing
124: low=source.bytes[1] & 0xF; //Low nibble of high byte
061C 5027 MOVF 0x27, W, ACCESS
061E 0B0F ANDLW 0xf
0620 6E2A MOVWF 0x2a, ACCESS
125: source.value<<=1; //Move down by one bit
0622 90D8 BCF 0xfd8, 0, ACCESS
0624 3626 RLCF 0x26, F, ACCESS
0626 3627 RLCF 0x27, F, ACCESS
0628 3628 RLCF 0x28, F, ACCESS
062A 3629 RLCF 0x29, F, ACCESS
126: high=swap(source.bytes[1]) & 0xF; //high nibble of shifted byte
062C 3A27 SWAPF 0x27, F, ACCESS
062E 5027 MOVF 0x27, W, ACCESS
0630 0B0F ANDLW 0xf
0632 6E2B MOVWF 0x2b, ACCESS
127: |
His code is specific for your application, mine 'generic'
Jay |
|
|
cbarberis
Joined: 01 Oct 2003 Posts: 172 Location: Punta Gorda, Florida USA
|
|
Posted: Sat Jan 05, 2019 7:31 am |
|
|
Once again, I thank you all, I never stop learning on this forum. Looking at the solution provided by Ttelmah I just realized that I also had my bit order in terms of MSB and LSB values totally backwards as I failed to see that my first incoming bit eventually gets shifted down to position 17 and because the SENT data comes in as MSB first this would make sense. |
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9226 Location: Greensville,Ontario
|
|
Posted: Sat Jan 05, 2019 8:36 am |
|
|
oopsy ! The easy cure is to use my 'bit by bit' method though I'm sure there's some fancy, convuluted 'reverse-the-bits' code. For that, I'd start with 16 bit data. It just seems easier..
Jay |
|
|
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
Powered by phpBB © 2001, 2005 phpBB Group
|