CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to CCS Technical Support

Question on bit manipulation for data extraction

 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
cbarberis



Joined: 01 Oct 2003
Posts: 172
Location: Punta Gorda, Florida USA

View user's profile Send private message Send e-mail

Question on bit manipulation for data extraction
PostPosted: Fri Jan 04, 2019 6:07 pm     Reply with quote

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: 9221
Location: Greensville,Ontario

View user's profile Send private message

PostPosted: Fri Jan 04, 2019 7:45 pm     Reply with quote

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... Smile

Jay
cbarberis



Joined: 01 Oct 2003
Posts: 172
Location: Punta Gorda, Florida USA

View user's profile Send private message Send e-mail

PostPosted: Fri Jan 04, 2019 8:15 pm     Reply with quote

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: 19499

View user's profile Send private message

PostPosted: Sat Jan 05, 2019 1:25 am     Reply with quote

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: 9221
Location: Greensville,Ontario

View user's profile Send private message

PostPosted: Sat Jan 05, 2019 6:33 am     Reply with quote

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

View user's profile Send private message Send e-mail

PostPosted: Sat Jan 05, 2019 7:31 am     Reply with quote

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: 9221
Location: Greensville,Ontario

View user's profile Send private message

PostPosted: Sat Jan 05, 2019 8:36 am     Reply with quote

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 Smile
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Page 1 of 1

 
Jump to:  
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