View Full Version : Wierd result when inverting an input
aratti
- 19th June 2015, 12:00
Bell var portB.0
Report var byte
(PortB.0 is pulled up)
Report = !Bell + 48 or Report = (!Bell) + 48
The value of variable Report = "0" (ascii 48) when portB.0 = True
The value of variable Report = "/" (ascii 47) when portB.0 = False (I was expecting ascii 49)
Is this a bug in PBP3 or I am using wrongly the not notation?
Cheers
Al
Dave
- 19th June 2015, 12:09
Al, I believe you have to use the BITWISE operator of "~" for that operation.
aratti
- 19th June 2015, 12:46
Thank you Dave for the suggestion, but no luck it doesn't work either. With "~" I get ascii 46 when portB.0 is false and the same ascii 47 when the portB.0 is True.
Looking into the manual the character for the NOT is "!", I could not find any reference to "~" as a NOT notation.
Cheers
Al.
Archangel
- 19th June 2015, 17:27
Thank you Dave for the suggestion, but no luck it doesn't work either. With "~" I get ascii 46 when portB.0 is false and the same ascii 47 when the portB.0 is True.
Looking into the manual the character for the NOT is "!", I could not find any reference to "~" as a NOT notation.
Cheers
Al.
The "tilde" character ~ is a BITWISE NOT. pp35 in the old green book, have misplaced my PBP3 book.
This works:
Bell var portB.6
Report var byte
main:
Report = ~~(Bell + 48)
debug report
pause 500
goto main
aratti
- 19th June 2015, 18:46
Bell var portB.6
Report var byte
main:
Report = ~~(Bell + 48)
debug report
pause 500
goto main
Thank you Archangel for your snippet.
I tried with one tilde character ~(Bell + 48) and it does't work. (Just strange characters)
I tried with two tildes, as per your example, and what I get is the original Logic state of the pin. It seems that two tildes are simply ignored.
So, at the moment I have used the IF/THEN/ELSE/ENDIF workaround. Conclusion we cannot invert a pin alias and convert it to ascii using the "!" or the bitwise "~"
Cheers
Al.
Acetronics2
- 19th June 2015, 19:47
It seems that two tildes are simply ignored.
not at all !
PORTB = ~ PORTB ' Invert every bit in PORTB
result = ~ (PORTB & %00001111)
'Invert the result of the & operation
manual $ 3.2.4 ...
if you invert twice ... you get the original value !!!
did you try ...
Report = (~ Bell ) + 48 ...
probably not !
Alain
aratti
- 19th June 2015, 20:22
Alain, the result of your example : Report = (~ Bell ) + 48 gives 46 when input is high and 47 when the input is low.
Cheers
Al.
Dave
- 19th June 2015, 21:24
Al, It makes me wonder if the TRIS register is set correctly for the port? You always get the same response no mater what state you place on it.
Tabsoft
- 19th June 2015, 21:57
Just thinking here....
What you might be seeing is that in a single statement "Report = (~Bell) + 48", is that PBP is treating the combination of the alias and the assignment to "Report" as a byte output computation.
If that is the case, then the output is as expected.
Byte variables are unsigned, so a bitwise not of 0 = 255 and 1 = 254.
Which would give you the 47 and 46 values you are seeing. 255+48=47, 254+48=46
This is most likely also happening for the Logical Not as well.
To test:
Bell var PORTB.6
Report var byte
MyPin var bit
MyPin = Bell
MyPin = ~MyPin 'this will force the bitwise Not at the bit variable level
Report = MyPin + 48
MyPin = Bell
MyPin = !Mypin 'This will force the logical Not at the bit variable level
Report = MyPin + 48
Output the two operations and see what you get then.
Acetronics2
- 19th June 2015, 22:04
Hi, Al
I played somewhat with that and end with ...
Report = 47 - (~Bell)
found funny things like ~N = 65535 - N ...
Have a good night
Alain
aratti
- 19th June 2015, 22:11
Dave, the tris register is set correctly and the pic18f2620 just do what it should do when the inputs change Logic state. I need to invert the Logic state of the display (it is much more simple to have a "True" when the external sensor is close instead having a "False".
As I said in a previous post, I solved the problem using the following workaround:
If Bell = false then
Report = "1"
Else
Report = "0"
ENDIF
Definetly less elegant than the "NOT" notation but at least it works!
Since I always toggle the flashing led with led = !led and it works fine I wrongly assumed that it could work also with an alias. Very likely I should copy the pin state in a bit variable to have it working. I will give a tray (NOT NOW)
Cheers
Al.
aratti
- 19th June 2015, 23:20
MyPin = Bell
MyPin = !Mypin 'This will force the logical Not at the bit variable level
Report = MyPin + 48
Thank you Tabsoft for the above snippet. Tested and it works. I have already replaced the IF/THEN/ELSE code that I could not stand with.
Now that a more elegant workaround has been found, the question remains: PBP3 cannot handle pin alias. Is it a bug?
Cheers
Al
Tabsoft
- 20th June 2015, 00:48
Glad it worked.
I have a theory, but will want to test it and look at the disassembled code to see.
I think it is the fact that the NOT operator (logical or bitwise) against the alias is being evaluated in an assignment statement to a byte.
This may be having the compiler use a generic macro that is handling the NOT operation as a byte or word output.
The test code above should force a two-step process.
1. Force the NOT operation/assignment to a bit variable.
2. Assign the value + 48 to the Report byte variable.
My guess is that since "Report = !Bell + 48" has the Report byte variable on the left, PBP might be assuming that the interim steps are at a byte (or word) level.
We will see, or I could be totally wrong. :-0
Either way I don't think we should have to burn another variable and cycles to perform what should be a simple function.
Tabsoft
- 20th June 2015, 02:04
Well, it was as I expected.
It's all about the assignment statement.
Whatever "Type" the left side of the assignment statement is drives the operation.
If you are assigning the value to a Byte, then the compiler does the steps as a byte.
If you are assigning the value to a BIT, then the compiler does the steps as a bit.
Here is a simple test program.
The "Destination" of the value is tested against a Byte variable or a Bit variable.
The "Source" of the value is tested against a Byte variable, a Port Alias and a Bit Alias.
myBit var bit
myByte var byte
TRISB = $FF
TestPin var PORTB.6
TestByte var byte
TestBit var TestByte.6
'Test Variable Alias with direct assignment to byte variable
TestByte = %01000000
'Assign Logical NOT (!) bit value to byte variable
myByte = !TestBit
'Assign Bitwise NOT (~) bit value to byte variable
myByte = ~TestBit
'Test Port Alias with direct assignment to byte variable
'Assign Logical NOT (!) bit value to byte variable
myByte = !TestPin
'Assign Bitwise NOT (~) bit value to byte variable
myByte = ~TestPin
'Test Variable Alias with direct assignment to bit variable
TestByte = %01000000
'Assign Logical NOT (!) bit value to bit variable
myBit = !TestBit
'Assign Bitwise NOT (~) bit value to bit variable
myBit = ~TestBit
'Test Port Alias with direct assignment to bit variable
'Assign Logical NOT (!) bit value to byte variable
myBit = !TestPin
'Assign Bitwise NOT (~) bit value to byte variable
myBit = ~TestPin
Here is the PBP assembler listing for the above code.
Notice that there are (2) macros for each operator type (! or ~)
LNOT?TB and LNOT?TT (Logical NOT !)
NOT?TB and NOT?TT (Bitwise NOT ~)
The TB stands for biT in and Byte out. The input is a Bit type and the Output is a Byte type.
This is when you get the results that are not what you might expect.
The TT stands for biT in and biT out. The input is a Bit type and the Output is a Bit type.
;assembler variables
_myByte EQU RAM_START + 01Ah
PB01 EQU RAM_START + 01Bh
_TestByte EQU RAM_START + 01Ch
;assembler defines
#define _myBit PB01, 000h
#define _TestPin _PORTB??6
#define _TestBit _TestByte??6
#define _PORTB??6 PORTB, 006h
#define _TestByte??6 _TestByte, 006h
; 00022 TestByte = %01000000
MOVE?CB 040h, _TestByte
; 00025 myByte = !TestBit
LNOT?TB _TestBit, _myByte
; 00028 myByte = ~TestBit
NOT?TB _TestBit, _myByte
; 00033 myByte = !TestPin
LNOT?TB _TestPin, _myByte
; 00036 myByte = ~TestPin
NOT?TB _TestPin, _myByte
; 00039 TestByte = %01000000
MOVE?CB 040h, _TestByte
; 00042 myBit = !TestBit
LNOT?TT _TestBit, _myBit
; 00045 myBit = ~TestBit
NOT?TT _TestBit, _myBit
; 00050 myBit = !TestPin
LNOT?TT _TestPin, _myBit
; 00053 myBit = ~TestPin
NOT?TT _TestPin, _myBit
Here are the actual macros that are called above.
I made some comments, not for everything but some.
NOT?TB macro Regin, Bitin, Bout
CHK?RP Regin
movlw -1 ;load dec 255 into w register
btfsc Regin, Bitin ;If Regin.Bitin = 0, skip the next instruction
movlw -2 ;load dec 254 into w register
MOVE?AB Bout ;Move W to Bout
endm
NOT?TT macro Regin, Bitin, Regout, Bitout
CHK?RP Regin
clrw ;Clear the w register
btfss Regin, Bitin ;If Regin.Bitin = 1, skip the next instruction
addlw 1 ;Load dec 1 into the w Register
CHK?RP Regout
btfsc STATUS, Z
bcf Regout, Bitout ;Clear Regout.Bitout
btfss STATUS, Z
bsf Regout, Bitout ;Set Regout.Bitout
endm
LNOT?TB macro Regin, Bitin, Bout
CHK?RP Regin
clrw
btfss Regin, Bitin
movlw -1
MOVE?AB Bout
endm
LNOT?TT macro Regin, Bitin, Regout, Bitout
CHK?RP Regin
clrw
btfss Regin, Bitin
addlw 1
CHK?RP Regout
btfsc STATUS, Z
bcf Regout, Bitout
btfss STATUS, Z
bsf Regout, Bitout
endm
aratti
- 20th June 2015, 06:42
Thank you Tabsoft for the deep search!
I think that this finding should call for an update of the manual (at least)
Cheers
Al.
Acetronics2
- 20th June 2015, 08:44
BTW,
I remember Darrel had written a post about this kind of behaviour.
he used a "!!" to get rid of the problem.
does somebody remember where it was shown ???
Alain
Tabsoft
- 20th June 2015, 20:44
That post would be interesting to read.
I don't see how it would alleviate the issue.
I think without an interim step to force the assignment to a bit type variable it will perform the operation as a byte.
I might take a look through the PBP library macros for Logical and bitwise NOTs to see if there is another macro that would hand the situation. If there is, it would be a matter of what syntax would cause the compiler to pick that macro instead.
xpa999
- 29th June 2015, 17:27
It would seem that the simple way around this is:
Report = 48 + !Mypin
Wouln't that force
Picbasic to evaluate Report as a byte, not as a bit?
Tabsoft
- 30th June 2015, 03:41
No, not really.
That has been the point of this discussion.
We would not want PBP to do the interim calculations as a byte, we would want PBP to do them as a bit.
The issue is that in this statement "Report = 48 + !Mypin"
Report is a byte variable, 48 will be treated as a constant and Mypin is a bit.
Sounds good so far, but, when PBP looks at this statement it will treat the !Mypin as a byte output in the calculation step.
It does this because "Report" on the left side is a byte variable.
What we want is if Mypin = 0 then Report = 49; If Mypin = 1 then Report = 48.
But here is what happens.
Pseudocode for the PBP ASM Macros used for the following Statement: Report = 48 + !Mypin
Step 1. Perform a Logical NOT on Mypin.
Clear the W register (Set it to 0)
If Mypin is a zero then
Store 255 decimal in the W register 'This is because Report will ultimately get the value, so PBP starts treating all the output variables as bytes
else
Store 0 in W register
endif
Move W register to a temporary "byte" variable T1
Step 2. Add 48 to temporary "byte" variable T1
Step 3. Move Temporary "byte" variable T1 to "byte" variable Report
So if you start with Mypin = 0, then
Step 1. T1 = 255
Step 2. T1 = 255 + 48 = 47 ' This is because a byte variable is unsigned in PBP
Step 3. Report = 47 'We wanted Report to equal 49 not 47
If you start with Mypin = 1
Step 1. T1 = 0
Step 2. T1 = 0 + 48 = 48
Step 3. Report = 48 'This is what we wanted.
So the issue as I can see is that to perform this logic as we "want" it to work, you need to manually perform an interim step
and store the current value of Mypin in a "bit" variable. Then perform a logical NOT on the "bit" variable. Then add 48 and the "bit" variable
and store the answer in report.
myBit var bit
Mypin var PORTB.6
Report var byte
myBit = Mypin
myBit = !myBit
Report = 48 + myBit
This works.
Dave
- 30th June 2015, 12:49
And the answer is....
Mypin var Portb.6
Report var byte
Report = 48 + (Mypin ^ 1)
There is NO need to be changing variable types. Mypin just needs to be inverted. So why not invert it as if it is a bit. Wow all of this typing for something so simple......
Powered by vBulletin® Version 4.1.7 Copyright © 2025 vBulletin Solutions, Inc. All rights reserved.