PDA

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