[Fixed]V1.40: problem with bit manipulation in byte?

Beta Testing discussion on mikroPascal PRO for PIC.
Post Reply
Author
Message
Dany
Posts: 3854
Joined: 18 Jun 2008 11:43
Location: Nieuwpoort, Belgium
Contact:

[Fixed]V1.40: problem with bit manipulation in byte?

#1 Post by Dany » 18 Apr 2009 19:12

Fixed in bèta v1.50 :D

Hi, in v1.40 there are apparently still problems when manipulating (setting/resetting) a bit from a byte when the bitnumber is a variable. The problems do not occur when the bitnumber is a literal.
e.g.:

Code: Select all

var I, J: byte;
  ...
  I := %01010101; // bit 2 is "1",  bit 3 = "0"
  J := 2;
  I.J := not I.J;  // does not work (resetting a bit does not work?)
  I.J := not I.J;  // does not work
  J := 3;
  I.J := not I.J;  // OK, setting a bit does work
  I.J := not I.J;  // does not work
(**) Also simple setting/resetting goes sometimes wrong:

Code: Select all

var I, J: byte;
  ...
  I := %01010101;
  J := 3;
  I.J := 1; // results in I=%00001000 (only bit 3 set, all others cleared)
  I.J := 0; // results in I=%00000000 (all bits reset)
(**) The same strange result is obtained when using "SetBit" and "ClearBit":

Code: Select all

var I, J: byte;
  ...
  I := %01010101;
  J := 3;
  SetBit(I, J); // results in I=%00001000 (only bit 3 set, all others cleared)
  ClearBit(I, J); // results in I=%00000000 (all bits reset)
Is it not allowed in mP to use a variable as bitnumber? (The help says it can be a variable or a literal).

Thanks in advance! :D

p.s. code was compiled for P16F877A

(**)
[erratum 20-4-2009]
Apparently the reason why the items marked with "(**)" give a wrong result is the declaration of a "bit" variable (that was not used furtheron) just before the declaration of I and J:

Code: Select all

var Bt: bit;  // <--- this one
    I, J: byte;
If that declaration is removed all works well. It does not affect however the results of the first code in the post. Thanks for testing Stefan!
[/erratum]
Last edited by Dany on 13 May 2009 14:47, edited 13 times in total.
Kind regards, Dany.
Forget your perfect offering. There is a crack in everything, that's how the light gets in... (L. Cohen)
Remember when we were young? We shone like the sun. (David Gilmour)

yo2lio
Posts: 1878
Joined: 19 Sep 2006 12:57
Location: Romania, Arad City
Contact:

#2 Post by yo2lio » 19 Apr 2009 06:37

Hello,

Yes, don't work.

I never used instruction like this :

Code: Select all

I.J := not I.J;
To prevent problems I use this :

Code: Select all

  mask := 1 shl J;
  I := I xor mask;
and is applicable to byte, word and dword type.
Best regards, Florin Andrei Medrea.

http://www.microelemente.ro/
http://www.microelemente.ro/produse-si-servicii/
http://www.microelemente.ro/custom-software/

mail : florin@microelemente.ro

Dany
Posts: 3854
Joined: 18 Jun 2008 11:43
Location: Nieuwpoort, Belgium
Contact:

#3 Post by Dany » 19 Apr 2009 08:18

Thanks. :D
Kind regards, Dany.
Forget your perfect offering. There is a crack in everything, that's how the light gets in... (L. Cohen)
Remember when we were young? We shone like the sun. (David Gilmour)

Dany
Posts: 3854
Joined: 18 Jun 2008 11:43
Location: Nieuwpoort, Belgium
Contact:

#4 Post by Dany » 19 Apr 2009 08:49

The contents of this post was moved to the first one in this thread to have it all together (and I can not delete this one). :oops:
Kind regards, Dany.
Forget your perfect offering. There is a crack in everything, that's how the light gets in... (L. Cohen)
Remember when we were young? We shone like the sun. (David Gilmour)

Stefan Uhlemayr
Posts: 158
Joined: 17 Jan 2009 21:33

#5 Post by Stefan Uhlemayr » 20 Apr 2009 10:24

Dany wrote:

Code: Select all

var I, J: byte;
  ...
  I := %01010101;
  J := 3;
  I.J := 1;
I would not expect from a pascal-compiler to accept this construct. Of course, it should lead into a error-message (turbo-pascal for example gives "invalid qualifier" at the point between I and J).
Dany wrote: The same strange result is obtained when using "SetBit" and "ClearBit":

Code: Select all

var I, J: byte;
  ...
  I := %01010101;
  J := 3;
  SetBit(I, J); // results in I=%00001000 (only bit 3 set, all others cleared)
  ClearBit(I, J); // results in I=%00000000 (all bits reset)
Can't reproduce this problem (test-program with just these instructions), neither on PIC16 nor on PIC18-architecture. Only if it is following the previous (pretty strange) construct (i.j:=1;), then it doesn't work. This looks like a similar bug with the internal variables (R1..R16) in the compiler like I've posted in this thread about the (really bad) way, how calculations are realized now (calculation depends on the type of the left-side-variable): http://www.mikroe.com/forum/viewtopic.php?t=18938

Greetings,
Stefan

EDIT: Just detected, that the correct function of SETBIT and CLEARBIT does not depend, if there is a previous instruction like "i.j:=1;". This assumption was caused by the behaviour of the software-debugger, which needs to be restarted, when there is a change in the source-code. The real reason Dany detected meanwhile, and he mentioned it in the first post of this thread.
Last edited by Stefan Uhlemayr on 20 Apr 2009 11:44, edited 2 times in total.

Dany
Posts: 3854
Joined: 18 Jun 2008 11:43
Location: Nieuwpoort, Belgium
Contact:

#6 Post by Dany » 20 Apr 2009 10:42

Stefan Uhlemayr wrote:I would not expect from a pascal-compiler to accept this construct. Of course, it should lead into a error-message (turbo-pascal for example gives "invalid qualifier" at the point between I and J).
Hi Stefan, I think this construction should give no problems according to the help (mikroPascal for PIC specfics, Accessing individual bits):
Accessing Individual Bits Of Variables
...
Also, you can simply use the direct member selector (.) with a variable, followed by a primary exression. Primary expression can be variable, constant, function call or an expression enclosed by parentheses.

Code: Select all

// expression as bit designator
// Set bit 6 in STATUS register 
i := 5;
STATUS.(i+1) := 1;
Kind regards, Dany.
Forget your perfect offering. There is a crack in everything, that's how the light gets in... (L. Cohen)
Remember when we were young? We shone like the sun. (David Gilmour)

Stefan Uhlemayr
Posts: 158
Joined: 17 Jan 2009 21:33

#7 Post by Stefan Uhlemayr » 20 Apr 2009 10:57

Dany wrote:Hi Stefan, I think this construction should give no problems according to the help (mikroPascal for PIC specfics, Accessing individual bits):
Accessing Individual Bits Of Variables
If you are familiar with a particular MCU, you can access bits by name:

Code: Select all

// Clear Global Interrupt Bit (GIE) 
GIE_bit := 0;
Also, you can simply use the direct member selector (.) with a variable, followed by a primary exression. Primary expression can be variable, constant, function call or an expression enclosed by parentheses.
In this case, you've detected a pretty serious bug. I wasn't aware of this extension of mP compared to other pascal-compilers.

But what's the reason for the SETBIT- and CLEARBIT-functions (which I would prefer to use, as they are more "pascal-like" in my eyes) then???

Thanks for clarifying,
Stefan

Dany
Posts: 3854
Joined: 18 Jun 2008 11:43
Location: Nieuwpoort, Belgium
Contact:

#8 Post by Dany » 20 Apr 2009 10:59

Stefan Uhlemayr wrote:
Dany wrote: The same strange result is obtained when using "SetBit" and "ClearBit":

Code: Select all

var I, J: byte;
  ...
  I := %01010101;
  J := 3;
  SetBit(I, J); // results in I=%00001000 (only bit 3 set, all others cleared)
  ClearBit(I, J); // results in I=%00000000 (all bits reset)
Can't reproduce this problem (test-program with just these instructions), neither on PIC16 nor on PIC18-architecture. Only if it is following the previous (pretty strange) construct (i.j:=1;), then it doesn't work. This looks like a similar bug with the internal variables (R1..R16) in the compiler like I've posted in this thread about the (really bad) way, how calculations are realized now (calculation depends on the type of the left-side-variable): http://www.mikroe.com/forum/viewtopic.php?t=18938
Hi Stefan, thanks for your testing. And indeed you are right. With only above code all is OK.
It goes wrong with my code, because I have, just before the declaration of I and J, a "bit" declaration of varaible "Bt", furtheron not used any more. Adding this declaration results in the error discribed.

Code: Select all

var Bt: bit; // <-- this is the extra bit declaration that causes the problem
    I, J: byte;
  ...
  I := %01010101;
  J := 3;
  SetBit(I, J);   //  I becomes %00001000
  ClearBit(I,J);  //  I becomes %00000000
Apparently the declaration of bit "Bt" was also the reason why this code gave a wrong result:

Code: Select all

I := %01010101;
  J := 3;
  I.J := 1; // results in I=%00001000 (only bit 3 set, all others cleared)
  I.J := 0; // results in I=%00000000 (all bits reset)
p.s. I added an erratum to the first post in this thread to reflect this findings.

Thanks Stefan! :D
Kind regards, Dany.
Forget your perfect offering. There is a crack in everything, that's how the light gets in... (L. Cohen)
Remember when we were young? We shone like the sun. (David Gilmour)

Stefan Uhlemayr
Posts: 158
Joined: 17 Jan 2009 21:33

#9 Post by Stefan Uhlemayr » 20 Apr 2009 15:25

Dany wrote: It goes wrong with my code, because I have, just before the declaration of I and J, a "bit" declaration of varaible "Bt", furtheron not used any more. Adding this declaration results in the error discribed.

Code: Select all

var Bt: bit; // <-- this is the extra bit declaration that causes the problem
    I, J: byte;
  ...
  I := %01010101;
  J := 3;
  SetBit(I, J);   //  I becomes %00001000
  ClearBit(I,J);  //  I becomes %00000000
One more strange point here: if this declaration of the bit-variable is placed AFTER the byte-variables, it works fine, but if the bit-variable (its name is not of relevance) is placed BEFORE the byte-variables (like in your example), the generated code is bigger and wrong...

Hope this helps to solve the problem,
Stefan

janni
Posts: 5373
Joined: 18 Feb 2006 13:17
Contact:

#10 Post by janni » 20 Apr 2009 17:24

Stefan Uhlemayr wrote:But what's the reason for the SETBIT- and CLEARBIT-functions (which I would prefer to use, as they are more "pascal-like" in my eyes) then???
They were introduced before it was possible to use the 'dot' bit designators. (I personally like the latter more than SetBit/ClearBit procedures and they may be used in expressions other than simple assignment).
One may think of bits as record fields of a byte variable and then there's nothing strange in notation like byte_var.B1 :wink: .

As to the problem in hand, compiler indeed mixes any bit variable into other bit calculations if it's declared first. There is generally a problem with bit arithmetic - for example

Code: Select all

var  i,j,k,n: byte;

begin
   n:=3;
   i.n:=1;
   j.n:=0;
   k.n:=1;
leads to the third and fourth assignments being infuenced by the value of i. Source of the problem seems to be the same as with the bit variable - wrong variable is used in final evaluation (always the first declared).

User avatar
srdjan
mikroElektronika team
Posts: 1552
Joined: 28 Dec 2005 12:47
Location: Serbia

#11 Post by srdjan » 21 Apr 2009 12:48

var I, J: byte;
...
I := %01010101; // bit 2 is "1", bit 3 = "0"
J := 2;
I.J := not I.J; // does not work (resetting a bit does not work?)
I.J := not I.J; // does not work
J := 3;
I.J := not I.J; // OK, setting a bit does work
I.J := not I.J; // does not work
Fixed.
var Bt: bit; // <-- this is the extra bit declaration that causes the problem
I, J: byte;
...
I := %01010101;
J := 3;
SetBit(I, J); // I becomes %00001000
ClearBit(I,J); // I becomes %00000000
Fixed.
var i,j,k,n: byte;

begin
n:=3;
i.n:=1;
j.n:=0;
k.n:=1;
Fixed.
Thank you all.

Dany
Posts: 3854
Joined: 18 Jun 2008 11:43
Location: Nieuwpoort, Belgium
Contact:

#12 Post by Dany » 21 Apr 2009 14:02

Thanks srdjan! :D
Kind regards, Dany.
Forget your perfect offering. There is a crack in everything, that's how the light gets in... (L. Cohen)
Remember when we were young? We shone like the sun. (David Gilmour)

Post Reply

Return to “mikroPascal PRO for PIC Beta Testing”