[Main]
Name=peekIO
Type=Function
Subtype=Macro
Header Files=peekpoke.h
Definition=#define peekIO(port) (*((volatile unsigned char*)(long)(port)))

[Description]
Reads a byte from an I/O port.

[Explanation]
<A HREF="$$LINK(peek)">peek</A> is not reliable when reading data from memory-mapped I/O ports.
For example, suppose that the user wants to wait until the programable timer on
the TI-89 (its value may be read from the address 0x600017) reaches the value 255. The
following construction seems quite good:
<PRE>while (peek (0x600017) != 255);
</PRE>
However, it will cause an infinity loop. Namely, the compiler will notice that the
same value is read in the loop. As a normal memory location can not be changed without
explicitely writing to it, and there is nothing in the loop which changes the data at the address
0x600017, the optimizer will move memory reading out of the loop to
make the code more efficient. Such behaviour is correct for ordinary memory locations.
But the compiler does not know anything about the
fact that 0x600017 is not an ordinary memory location but an I/O port, which may be
changed unpredictably (purely by the hardware, without any program control). To prevent
such behaviour, use peekIO instead of <A HREF="$$LINK(peek)">peek</A>, i.e. write
<PRE>while (peekIO (0x600017) != 255);
</PRE>
Basically, peekIO works exactly like <A HREF="$$LINK(peek)">peek</A>, but prevents any unwanted optimizations
generated by the compiler. Always use peekIO for reading memory-mapped I/O ports, else you may have
trouble (especially in short loops). For example, to read the keyboard column mask on TI-89, do
<PRE>key_mask = peekIO (0x60001B);
</PRE>
peekIO may be used even for reading bytes in memory, but <A HREF="$$LINK(peek)">peek</A>
will generate better code when working with memory. However, use peekIO to read any memory
location which may change in a way which is unpredictable from the aspect of a normal program
flow (for example, a memory location which is changed in the body of the interrupt handler).
