BDigitalPort

Derived from: none

Declared in: be/device/DigitalPort.h

Library: libdevice.so

[method summary]

The BDigitalPort class is an interface to the GeekPort's two digital ports. Each digital port is an 8-bit wide device that can be set for input or output. See The Digital Ports for an illustration of the GeekPort's digital port pins.

To access a digital port, you construct a BDigitalPort object, open it on the port you want, assign the object to work as either an input or an output, and then read or write a series of bytes from or to the object.

In the following example, we open and read from digital port A:

   #include <DigitalPort.h>
   
   void ReadDigitalPortA()
   {
      char val;
      BDigitalPort dPortA;
   
      if (dPortA.Open("DigitalA") <= 0 ||
         dPortA.SetAsInput() != B_NO_ERROR) 
         return;
   
      while ( /* whatever */ ) {
         /* Read() returns the number of bytes that were
          * read; a successful read returns 1.
          */
         if (dPortA.Read(&val) != 1) 
            break;
         ...
         snooze(1000);
      }
      dPortA.Close();
   }

As shown here, the BDigitalPort is constructed without reference to a specific port. It's not until you actually open the object (through Open()) that you have to identify the port that you want. Identification is by name, "DigitalA" or "DigitalB". The Read() function returns only one value per invocation, and is untimed--if you don't provide some sort of tethering (as we do with snooze(), above) the read loop will spin as fast as possible.

To safeguard against an inadvertent burst of equipment-destroying output, the digital port is set to be an input when it's opened, and automatically reset to be an input when you close it.


Using Both Digital Ports at the Same Time

To access both digital ports at the same time, you have to construct two BDigitalPort objects. One of the objects can be used as an output and the other an input, both as outputs, or both as inputs.

In the following example, digital port A is used to write data to an external device, while digital port B is used for acknowledgment signalling: Before each write we set port B to 0, and after the write we wait for port B to be set to 1. We're assuming that the external device will write a 1 to port B when it's ready to receive the next 8-bits of data.

   void WriteAndAck()
   {
      char val;
      BDigitalPort dPortA;
      BDigitalPort dPortB;
   
      if (dPortA.Open("DigitalA") <= 0 ||
         dPortA.SetAsOutput() != B_OK ||
         dPortB.Open("DigitalB") <= 0 ||
         dPortB.SetAsOutput() != B_OK) 
         goto exit_tag;
   
      while ( /* whatever */ ) {
   
         /* Clear the acknowledgment signal. */
         val = 0;
         if (dPortB.Write(&val) != 1) 
            break;
   
         /* Reset val to the data we want to send. */
         val = ...;
   
         if (dPortA.Write(val) != 1) 
            break;
         
         /* Reset digital port B to be an input. */
         if (dPortB.SetAsInput() != B_OK)
            break;
   
         /* Wait for the acknowledgment. */
         while (1) {
            if (dPortB.Read(&val) != 1)
               goto exit_tag;
            if (val == 1)   
               break;
            snooze(1000);
         }
   
         /* Reset digital port B to be an output. */
         if (dPortB.SetAsOutput() != B_OK)
            break;
      }
   exit_tag:
      dPortA.Close();
      dPortB.Close();
   }

Notice that the acknowledgment signal only takes one bit of digital port B. This leaves seven bits that the external device can use to send additional data (triggers or gates, for example). The restriction in this scheme, given the structure shown above, is that this additional data would have to be synchronized with the acknowledgment signal.

By extension, if the data that you want to write to the external device is, at most, only seven-bits wide, then you could rewrite this example to use a single port: You would mask one of the bits as the acknowledgment carrier, and let the other seven bits carry the data, toggling the port between input and output as needed.


Overdriving an Output Pin

One of the features of the digital ports is that you can "overdrive" a pin from the outside. This means that you can set a port to be an output, and then force a voltage back onto the pin from an external device and read that voltage with the Read() function without having to reset the port to be an input. Keep in mind that there's a 1 KOhm resistor behind the pin (on the BeBox side), so your "overdrive" circuit has to be hot enough to balance the resistance.

When you overdrive an output pin, the voltage on the pin is altered for as long as the external force keeps it there. If you write an "opposing" value to an overdriven pin (through Write()), the written value won't pull the pin--the overdriven value will still be enforced. As soon as the overdrive voltage is removed, the pin will produce the voltage that was more recently written to it by the Write() function.


Constructor and Destructor


BDigitalPort()

      BDigitalPort(void) 

Creates a new object that can open one of the digital ports. The particular port is specified in a subsequent Open() call.


~BDigitalPort

      virtual ~BDigitalPort()

Closes the port the object has open and destroys the object.

Deleting a BDigitalPort object sets the port (at the driver level) to be an input. The values at the port's pins are, at that point, undefined.


Member Functions


Open(), IsOpen(), Close()

      status_t Open(const char *name)
      bool IsOpen(void)
      void Close(void)

Open() opens the named digital port; the name argument should be either "DigitalA" or "DigitalB". The Digital Ports shows you where the two ports appear among the GeekPort's pins.

A digital port can only be held open by one BDigitalPort object at a time; you should close the port as soon as you're finished with it. Furthermore, each BDigitalPort object can only hold one port open at a time. When you invoke Open(), the port that the object currently has open is automatically closed--even if the port that you're attempting to open is the port that the object already has open.

When you open a digital port, the device is automatically set to be an input. If you want the port to be an output, you must follow this call with a call to SetAsOutput(). Just to be safe, it couldn't hurt to explicitly set the port to be an input (through SetAsInput()) if that's what you want.

IsOpen() returns true if the object currently has a port open, and false if not.

Close() closes the object's connection to its port. The digital port is set to be an input at the driver level.

RETURN CODES

Open() returns a positive integer if the port is successfully opened; otherwise, it returns B_ERROR.


Read()

      ssize_t Read(uint8 *buf)

Reads the data that currently lies on the digital ports pins, and returns the data in buf. Although you usually read a digital port that's been set to be an input, it's also possible to read an output port. In any case, the port must be open.

RETURN CODES

If the port was successfully read, the function returns 1 (the number of bytes read). Otherwise, it returns B_ERROR.


SetAsInput(), SetAsOutput(), IsInput(), IsOutput()

      status_t SetAsInput(void)
      status_t SetAsOutput(void)
      bool IsInput(void)
      bool IsOutput(void) 

SetAsInput() and SetAsOutput() set the object's port to act as an input or output. They return B_ERROR if the object isn't open, and B_OK otherwise.

IsInput() and IsOutput() tell you the input/output state of the object. They both return false if the object isn't open.


Write()

      ssize_t Write(uint8 value)

Sends value to the object's port. The port continues to produce the value until another Write() call changes the setting. The object must be open as an output for this function to succeed.

RETURN CODES

Write() return B_ERROR if a port isn't open, or if, for any other reason, the write failed. Otherwise it returns 1 (the number of bytes that were read).




The Be Book, in lovely HTML, for BeOS Release 4.

Copyright © 1998 Be, Inc. All rights reserved.

Last modified November 10, 1998.