Jump to content
Sign in to follow this  
twomers

Mapping To Bit Number

Recommended Posts

Hi,

 

Just a quick question there.

I know you can map variables to registers like this:

volatile bit RA1 @ PORTA.1;

But what I was wondering is if there's a way to do this for general variables:

unsigned char shift_reg;
volatile bit shift_reg0 @ shift_reg.0;
volatile bit shift_reg1 @ shift_reg.3;

I suppose what I'm really asking is if this (if it worked):

something = shift_reg0^shift_reg1;

is more efficient than doing something like:

something = test_bit(shift_reg,0)^test_bit(shift_reg,1);

or

something = shift_reg.0^shift_reg.1;

Edited by twomers

Share this post


Link to post
Share on other sites
Hi,

 

Just a quick question there.

I know you can map variables to registers like this:

volatile bit RA1 @ PORTA.1;

But what I was wondering is if there's a way to do this for general variables:

unsigned char shift_reg;
volatile bit shift_reg0 @ shift_reg.0;
volatile bit shift_reg1 @ shift_reg.3;

I suppose what I'm really asking is if this (if it worked):

something = shift_reg0^shift_reg1;

is more efficient than doing something like:

something = test_bit(shift_reg,0)^test_bit(shift_reg,1);

or

something = shift_reg.0^shift_reg.1;

 

You might be better off doing something like:

 

	something = ((shift_reg>>3) ^ shift_reg) & 0x01;

 

I do similar in one of my projects:

 

	if ( (((RXProtocolByte >> 1) ^ TXProtocolByte) & (1<<SEQBIT)) == 0 )

 

Try them all and see what gives shorter code...

 

Orin.

Share this post


Link to post
Share on other sites

Thanks for your reply, Orin. I'll try that out later on and report back during the weekend.

 

When you say "You might be better off doing" does that mean that what I proposed can be done? Or that your alternative should be as efficient? I know you probably don't believe me but really anything that can be saved is best!

 

Actually, I'll test it now. Hmm. This is the code that I used.

#define PORTA_BIT_A 1
#define PORTA_BIT_B 3

void main( void ) {  
 // Config timer in option reg
 clear_bit( option_reg, T0CS );
 clear_bit( option_reg, T0SE );

 // Set up interrupt control
 set_bit( intcon, T0IE );
 set_bit( intcon, GIE );

 volatile bit ra1 @ PORTA.PORTA_BIT_A;
 volatile bit ra3 @ PORTA.PORTA_BIT_B;

 while( true ) {
if ( ra1 ^ ra3 ) {
  portb = 1;
}

if ( ((porta>>PORTA_BIT_B) ^ (porta>>PORTA_BIT_A)) & 0x01 ) {
  portb = 1;
}
 }
}

By monitoring tmr0 in the register bar the first statement takes 10 tmr0 cycles while the second takes 17. I know 7 ticks isn't that many. But 7*2*8 is 112 ticks which is 112 more than I would like.

 

>> Try them all and see what gives shorter code...

Alas @ing does. I suppose I could find a redundant register for my code and use that :( Hmm. Don't seem to be using intcon

Edited by twomers

Share this post


Link to post
Share on other sites
Thanks for your reply, Orin. I'll try that out later on and report back during the weekend.

 

When you say "You might be better off doing" does that mean that what I proposed can be done? Or that your alternative should be as efficient? I know you probably don't believe me but really anything that can be saved is best!

 

Actually, I'll test it now. Hmm. This is the code that I used.

#define PORTA_BIT_A 1
#define PORTA_BIT_B 3

void main( void ) {  
 // Config timer in option reg
 clear_bit( option_reg, T0CS );
 clear_bit( option_reg, T0SE );

 // Set up interrupt control
 set_bit( intcon, T0IE );
 set_bit( intcon, GIE );

 volatile bit ra1 @ PORTA.PORTA_BIT_A;
 volatile bit ra3 @ PORTA.PORTA_BIT_B;

 while( true ) {
if ( ra1 ^ ra3 ) {
  portb = 1;
}

if ( ((porta>>PORTA_BIT_B) ^ (porta>>PORTA_BIT_A)) & 0x01 ) {
  portb = 1;
}
 }
}

By monitoring tmr0 in the register bar the first statement takes 10 tmr0 cycles while the second takes 17. I know 7 ticks isn't that many. But 7*2*8 is 112 ticks which is 112 more than I would like.

 

>> Try them all and see what gives shorter code...

Alas @ing does. I suppose I could find a redundant register for my code and use that :( Hmm. Don't seem to be using intcon

 

Actually, I wasn't commenting on whether your proposal worked or not, just adding another alternative.

 

Try:

 

	if ( ((porta>>(PORTA_BIT_B-PORTA_BIT_A)) ^ porta) & (0x01<<PORTA_BIT_A) ) {
  portb = 1;
}

 

It shifts porta such that the bits of interest overlap, xors them together and tests the overlapping bit. It does assume that PORTA_BIT_B > PORTA_BIT_A... It only does two shifts rather than 4, a saving of 4 ticks for the shifts alone. It might avoid a second temporary variable and load/store for additional savings. This method will only work for bits that are close together BTW or you spend more time shifting than the alternatives would take.

 

Orin.

Share this post


Link to post
Share on other sites
Actually, I wasn't commenting on whether your proposal worked or not, just adding another alternative.

 

Try:

 

	if ( ((porta>>(PORTA_BIT_B-PORTA_BIT_A)) ^ porta) & (0x01<<PORTA_BIT_A) ) {
  portb = 1;
}

 

It shifts porta such that the bits of interest overlap, xors them together and tests the overlapping bit. It does assume that PORTA_BIT_B > PORTA_BIT_A... It only does two shifts rather than 4, a saving of 4 ticks for the shifts alone. It might avoid a second temporary variable and load/store for additional savings. This method will only work for bits that are close together BTW or you spend more time shifting than the alternatives would take.

 

Orin.

Heh. I was just about to post solution! For me this now operates at 12 cycles (while the @ing is now 9 for some reason), so it reduces it by a deascent amount! Assuming the B value is greater than the A value is fine. That's not a restriction or anything.

 

In fact this:

	if ( porta.PORTA_BIT_A ^ porta.PORTA_BIT_B ) {
  portb = 1;
}

Performs as well as the @ operator... I must have mis-read my code when I analysed it before:

	if ( ra1 ^ ra3 ) {
0018  3000	  MOVLW 0x00
0019  1985	  BTFSC main_1_ra3,3
001A  3001	  MOVLW 0x01
001B  1885	  BTFSC main_1_ra1,1
001C  3A01	  XORLW 0x01
001D  39FF	  ANDLW 0xFF
001E  1903	  BTFSC STATUS,Z
001F  2823	  GOTO	label2

And:

	if ( porta.PORTA_BIT_A ^ porta.PORTA_BIT_B ) {
0036  3000	  MOVLW 0x00
0037  1985	  BTFSC gbl_porta,3
0038  3001	  MOVLW 0x01
0039  1885	  BTFSC gbl_porta,1
003A  3A01	  XORLW 0x01
003B  39FF	  ANDLW 0xFF
003C  1903	  BTFSC STATUS,Z
003D  2840	  GOTO	label4

 

This is great. I always thought that operator was not a good way of accessing bits. And seeing as the bits I'm accessing are constant for the duration of execution this is perfect.

 

Thanks again for your input, Orin. Much appreciated.

Share this post


Link to post
Share on other sites
Actually, I wasn't commenting on whether your proposal worked or not, just adding another alternative.

 

Try:

 

	if ( ((porta>>(PORTA_BIT_B-PORTA_BIT_A)) ^ porta) & (0x01<<PORTA_BIT_A) ) {
  portb = 1;
}

 

It shifts porta such that the bits of interest overlap, xors them together and tests the overlapping bit. It does assume that PORTA_BIT_B > PORTA_BIT_A... It only does two shifts rather than 4, a saving of 4 ticks for the shifts alone. It might avoid a second temporary variable and load/store for additional savings. This method will only work for bits that are close together BTW or you spend more time shifting than the alternatives would take.

 

Orin.

Heh. I was just about to post solution! For me this now operates at 12 cycles (while the @ing is now 9 for some reason), so it reduces it by a deascent amount! Assuming the B value is greater than the A value is fine. That's not a restriction or anything.

 

In fact this:

	if ( porta.PORTA_BIT_A ^ porta.PORTA_BIT_B ) {
  portb = 1;
}

Performs as well as the @ operator... I must have mis-read my code when I analysed it before:

	if ( ra1 ^ ra3 ) {
0018  3000	  MOVLW 0x00
0019  1985	  BTFSC main_1_ra3,3
001A  3001	  MOVLW 0x01
001B  1885	  BTFSC main_1_ra1,1
001C  3A01	  XORLW 0x01
001D  39FF	  ANDLW 0xFF
001E  1903	  BTFSC STATUS,Z
001F  2823	  GOTO	label2

And:

	if ( porta.PORTA_BIT_A ^ porta.PORTA_BIT_B ) {
0036  3000	  MOVLW 0x00
0037  1985	  BTFSC gbl_porta,3
0038  3001	  MOVLW 0x01
0039  1885	  BTFSC gbl_porta,1
003A  3A01	  XORLW 0x01
003B  39FF	  ANDLW 0xFF
003C  1903	  BTFSC STATUS,Z
003D  2840	  GOTO	label4

 

This is great. I always thought that operator was not a good way of accessing bits. And seeing as the bits I'm accessing are constant for the duration of execution this is perfect.

 

Thanks again for your input, Orin. Much appreciated.

 

I was just about to post a similar comment. Yes, for constant bits, "porta.PORTA_BIT_A ^ porta.PORTA_BIT_B" seems to be best. (Future compiler optimization? If the compiler uses instructions that set the zero flag at addresses 0036 and 0038, (eg: ANDLW 0x00 and IORLW 0x01), it could omit the ANDLW at address 003B.)

 

I couldn't access bits this way as I was accessing a structure member and the compiler doesn't accept structure.member.bit (yet?).

 

Orin.

Edited by Orin

Share this post


Link to post
Share on other sites

Ah. I see. But remember pointers are always friendly:

 

typedef struct _thing {
 unsigned char ch;
} thing;

void main( void ) {	
 unsigned char *ptr;

 thing i_thing1, i_thing2;

 while( true ) {
ptr = &i_thing1.ch;

if ( ptr.0 ^ ptr.4 )
  portb = 0;

ptr = &i_thing2.ch;

if ( ptr.0 ^ ptr.4 )
  portb = 0;
 }
}

If feasible. The pointer assignment takes 5 or 6 clock cycles while the xoring takes a few. So it is probably feasible to do this, especially if pointing to the same variable for more than one comparison.

Share this post


Link to post
Share on other sites

Join the conversation

You are posting as a guest. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
Sign in to follow this  

×
×
  • Create New...