Bit(lhs,Rhs)

General FreeBASIC programming questions.
Dinosaur
Posts: 1330
Joined: Jul 24, 2005 1:13
Location: Hervey Bay
Contact:

Bit(lhs,Rhs)

Postby Dinosaur » Nov 05, 2008 21:31

Hi all

In an effort to speed up a project where I have to read hundreds of input bits, and assign them to elements of a udt.I came up with.

Code: Select all

Bz = Inp(Settings.PortAddr(Port))
For Bits = 1 To 8
   BitCount += 1
   Settings.PortBit(BitCount) = Bit(Bz,Bits)
Next
To my disappointment (but documented) Bit returned "-1" if the bit is set. So I cant use it directly in my program logic, I have to convert it to "+1" if it is ON, and leave it at 0, if not.
Going with the theory that two negatives make a positive, i tried

Code: Select all

Settings.PortBit(BitCount) = -Bit(Az,Bits)
Note the minus before Bit. This worked, but my question:
Is this intended behaviour or a fluke.?

Regards
vdecampo
Posts: 2982
Joined: Aug 07, 2007 23:20
Location: Maryland, USA
Contact:

Postby vdecampo » Nov 05, 2008 21:39

Return Value:

Returns an Integer value of `-1` if the bit is set, or `0` if the bit is cleared.


If you want to test for a particular bit you could try...

Code: Select all

Bz = Inp(Settings.PortAddr(Port))
For Bits = 0 To 7
        BitCount += 1
        Settings.PortBit(BitCount) = Bz and (2^Bits)
Next
 


Of course you need to chage PortBit array bounds to 0-7.

-Vince
MichaelW
Posts: 3500
Joined: May 16, 2006 22:34
Location: USA

Postby MichaelW » Nov 05, 2008 22:09

It seems to me that you can use the same index for both, and ANDing with 1 will yield a return value of 0 or 1.

Code: Select all

for i as integer = 0 to 7
    Settings.PortBit(i) = Bit(Bz,i) and 1
next
Dinosaur
Posts: 1330
Joined: Jul 24, 2005 1:13
Location: Hervey Bay
Contact:

Postby Dinosaur » Nov 05, 2008 22:22

Hi all

vdecampo, your suggestion prints the value of the bit, and not 0 or 1.


It seems to me that you can use the same index for both,

That was so obvious, that I should have picked that up. (senior's moment)
What I didnt realise that " -1 And +1" gave the result of +1

Will test for speed difference now.
Does anyone know if the -Bit(lhs,rhs) was intended ?

Regards

Edit: Actually Michael, I was using the separate Bitcount to increment the udt element (from 1 to 384). I also had to break up the task of reading 48 x 8 bit ports, as it was taking 350 mSec to read all of them.
counting_pine
Site Admin
Posts: 6190
Joined: Jul 05, 2005 17:32
Location: Manchester, Lancs

Postby counting_pine » Nov 05, 2008 22:58

BIT() is just a simple macro, designed to return a boolean result for whether the bit is set.
This allows an easy way to test for when a bit is unset by doing "if not bit(a, n) then ..."

You might be wondering why -1 is returned instead of 1, but it's because -1 is a standard BASIC value for True. It's the number you get if you set all the bits in a signed integer, while 0 is what you get if you clear all the bits, and you can easily flip between the two values using the NOT operation.
It just (quasi-)coincidentally happens that -TRUE is -(-1) is 1, which can be convenient sometimes.

BIT() might not be ideal for what you need, but if you want to, it's really easy and more efficient to define your own macro to do what you want, e.g.

Code: Select all

#define bit1(a, n) ( ((a) shr (n)) and 1)

for i as integer = 7 to 0 step -1
    print bit1(91, i);
next
print
Dinosaur
Posts: 1330
Joined: Jul 24, 2005 1:13
Location: Hervey Bay
Contact:

Postby Dinosaur » Nov 06, 2008 21:07

Hi all

counting_pine your suggestion works well, and I ended up using it, however when I tested it for 100,000 reads there was no difference to -Bit(rhs,lhs).
But I wasnt confident that the "-" was intended and/or reliable.

This is the Read of 1 of the 48 x 8 bit ports.

Code: Select all

InCount = 0
If IOCtrl.BrdInstall(1) Then                           'if I/O board installed
    For Port = 0 To 5                                  'A1 to C2
        Cz = 0
        For Az = 1 To 3                                'get average
            Bz = Inp(IOCtrl.PortAddr(Port))'of
            Cz = Cz + Bz                               '3 reads
        Next
        Az = Cz / 3
        IOCtrl.PortByte(Port) = Az                     'Save the byte
        For Bits = 0 To 7                               '
            IOCtrl.PortBit(InCount) = Bit1(Az,Bits)'set Bit to 0 or 1
            Led.State(InCount) = IOCtrl.PortBit(InCount)'update Led
            InCount += 1                                'next bit
        Next
    Next Port
EndIf


I basically put that in a Select case, and increment the case to read 8 boards. That way it only reads 1 board for each program loop.

Regards
Eclipzer
Posts: 432
Joined: Oct 01, 2005 10:50
Location: Maryland
Contact:

Postby Eclipzer » Nov 08, 2008 11:29

You might be wondering why -1 is returned instead of 1, but it's because -1 is a standard BASIC value for True. It's the number you get if you set all the bits in a signed integer, while 0 is what you get if you clear all the bits, and you can easily flip between the two values using the NOT operation.


Isn't this true of most programming languages, for the very reasons stated?
Sisophon2001
Posts: 1704
Joined: May 27, 2005 6:34
Location: Cambodia, Thailand, Lao, Ireland etc.
Contact:

Postby Sisophon2001 » Nov 08, 2008 12:18

This is my understanding.

- In most languages TRUE = 1. For example C.
- In old versions of BASIC TRUE = -1
- Most languages evaluate 0 as FALSE and <> 0 as TRUE in expressions, regardless of the value used for TRUE. This includes both BASIC and C.
- In some languages TRUE and FALSE are BOOLEAN variables, which might or might not evaluate to numerical equivalents.

Read up on the difference between logical and bitwise OR, AND and NOT to get a better understanding. I find it difficult to explain further.

Garvan
counting_pine
Site Admin
Posts: 6190
Joined: Jul 05, 2005 17:32
Location: Manchester, Lancs

Postby counting_pine » Nov 08, 2008 12:21

Eclipzer wrote:
You might be wondering why -1 is returned instead of 1, but it's because -1 is a standard BASIC value for True. It's the number you get if you set all the bits in a signed integer, while 0 is what you get if you clear all the bits, and you can easily flip between the two values using the NOT operation.


Isn't this true of most programming languages, for the very reasons stated?
Well, most (for a given value of "most") programming languages have a proper, non-bitwise NOT operator for working with conditional expressions.

For example, C usually uses 1 for TRUE. It has the '!' operator which returns 1 for a zero value and 0 for a non-zero value. (For bitwise NOTs, it also has the '~' operator.)

Some languages have a more sophisticated system, that don't even consider TRUE/FALSE as numeric values. In these, most values of most types (e.g. 1, 0, "foo", {a, b, c} )will evaluate as TRUE, while FALSE might be something like a specific FALSE object, or an empty list, or Null or something like that.
Dinosaur
Posts: 1330
Joined: Jul 24, 2005 1:13
Location: Hervey Bay
Contact:

Postby Dinosaur » Nov 24, 2008 6:03

Hi all

I have taken two days now to isolate an exception that happens in Dos, but not in Windows.
I took counting_pine's suggestion and used the macro bit1 to do the following.

Code: Select all

For Bits = 0 To 7 'Az holds value from port
    IOCtrl.PortBit(IOCtrl.InCount) = Bit1(Az,Bits)
    Led.State(IOCtrl.InCount) = IOCtrl.PortBit(IOCtrl.InCount)
    IOCtrl.InCount += 1
Next
I put this into a Select Case 1 of 8, so that I dont read 8 boards all at once. This works when I compile for Win.
When I compile for Dos, I get an exception as soon as the program starts.
I isolated it to the line with the Bit1 macro. If I rem out 6 of the 8 cases, then there is no exception. The moment I read a third it bombs out.
By remming out the line with Bit1 on all 8 cases, I can read without an error. So, I wrote a long hand version of what the Macro does.

Code: Select all

Shifter = &b00000001
For Bits = 0 To 7
   If (Az And Shifter) > 0 Then IOCtrl.PortBit(IOCtrl.InCount) = 1 Else IOCtrl.PortBit(IOCtrl.InCount) = 0
   Shifter = Shifter Shl 1
    Led.State(IOCtrl.InCount) = IOCtrl.PortBit(IOCtrl.InCount)        'update Led
    IOCtrl.InCount += 1
Next
This does not cause an exception, and logically should do the same. However the question is why can I run this in Win witout errors, and why can I runonly two cases without an error in Dos.

Is it the repeated calling of the macro that corrupts ?
There doesnt appear to be much of a penalty in time for the long hand code.

Regards
marcov
Posts: 2929
Joined: Jun 16, 2005 9:45
Location: Eindhoven, NL
Contact:

Postby marcov » Nov 24, 2008 21:44

Sisophon2001 wrote:- Most languages evaluate 0 as FALSE and <> 0 as TRUE in expressions,
regardless of the value used for TRUE. This includes both BASIC and C.


In general this is typically a C thing. And descendants. TRUE should not be anything (unless heavily typecast).

Most languages _store_ 0 and 1 for false and true, and values 2..2^(8*sizeof(booltype))-1 are typically undefined.

Return to “General”

Who is online

Users browsing this forum: No registered users and 9 guests