.. _Digital Ports:

=============
Digital Ports
=============

Atmegas have digital ports each with 8 individual pins. They that can
be configured as input and output pins. To make an easy use of them, amforth
has a small library :file:`bitnames.frt` in the :file:`lib` directory.

The name port indicate that only IO ports can be used with this library.
Since the addresses used are RAM addresses, the whole address can be used, 
not only the IO range. The addresses are accessed on byte level. For single 
bits (portpin: definitions) the bitnumber can exceed the 8 bits a byte can 
hold. In this case the address is increased to a value that contains the 
bit specified: e.g. bit 24 of address 80 is the same as bit 0 of address 83.
Bitmaps are bound to the byte they address.

.. code-block:: forth

  PORTB 1 portpin: led

Output pins
-----------

.. figure:: LED-Basic.*
    :align: right

The simplest hardware is a LED connected to one pin.
The following sequence initializes the pin and turns
the LED on:

.. code-block:: forth

 > PORTB 1 portpin: led
  ok
 > led is_output
  ok
 > led low

To turn it off, simply execute

.. code-block:: forth

  > led high

Input pins
----------

Input pins are used to get the voltage state: High or Low.
A simple hardware would be as follows:

::

             VCC
               ^
               |
              +-+
              | |
              | |
              +-+
   |           |
 0 +-----------+
   |           |
               \
 Port           \
               + \>
               |
               |
             ----
              GND

The resistor is not really needed, the pin can be configured to use an internal
resistor.

.. code-block:: forth

   >  PORTB 0 portpin: mykey
    ok
   >  mykey is_input
    ok
   >  mykey pin_pullup_on

If the key is not pressed, the resistor (either the internal
pull up or the external resistor) drives the voltage to high. If you
read the pin, you will get a 1 in this example:

.. code-block:: forth

   > mykey pin@ .
   1 ok

if the key gets pressed, it will connect the controller pin with
ground level, giving a 0

.. code-block:: forth

  > mykey pin@ .
  0 ok

Bit Pattern
-----------

The library can deal with bit patterns as well.

::

  +-----+-----+-----+-----+-----+-----+-----+-----+
  |  0  |  0  |  0  |  0  |  1  |  1  |  1  |  1  |
  +-----+-----+-----+-----+-----+-----+-----+-----+

.. code-block:: forth

   > addr $0f bitmask: addr-low
   > %01000000 addr c! \ set all bits at addr
   > $ff addr-low pin! \ set only a few bits
   > $03 addr-low pin!

The pin! command changes the bits to the value given
only for those bits which are set to 1 in the bitmask.
In this example, only the lower 4 bits are changed, the
upper ones are left unchanged:

::

  +-----+-----+-----+-----+-----+-----+-----+-----+
  |  0  |  1  |  0  |  0  |  1  |  1  |  1  |  1  |
  +-----+-----+-----+-----+-----+-----+-----+-----+

  +-----+-----+-----+-----+-----+-----+-----+-----+
  |  0  |  1  |  0  |  0  |  0  |  0  |  1  |  1  |
  +-----+-----+-----+-----+-----+-----+-----+-----+

The same masking policy applies to pin@. Internally the
portpin definition is converted into a bitmask. The
words ``high`` and ``low`` which set resp. clear the
bitpositions are optimized versions of pin!:

.. code-block:: forth

   : high $ff rot rot pin! ;
   : low $00 rot rot pin! ;

.. note::

   The extended bit range for single bits are available in amforth 5.3 or 
   later. The file bitnames.frt works with older version too.