For some applications it would be convenient to the able to write an 8-bit byte to a port on the microcontroller in a single operation, or alternatively read a byte from a port. For example, I’m currently experimenting with interfacing an RGB LED Matrix Panel with uLisp which definitely needs something like this.
Existing options
Currently the only ways to do this are:
-
Write a loop calling digitalwrite eight times.
-
Write an assembler routine.
We need a way to read or write an entire byte from/to a port, or define all the bits in a port as outputs or inputs.
There was an earlier discussion about implementing something like this with peek and poke functions, named after the equivalents in BASIC: Adding your own functions. However I would prefer something that is more in the spirit of Lisp, and portable across different platforms.
Most microcontrollers group I/O pins together into ports, called A, B, C etc. Ideally it should be possible to write to a port from uLisp, without knowing the address of the port registers, just by referring to it as, for example, porta.
Proposal
To get the ball rolling here’s one suggestion:
The address of the port registers will be given for a particular processor by keywords; for example:
- :porta-dir - direction register
- :porta-out - output register
- :porta-in - input register
A uLisp function, such as register, will read the port and return the value; for example:
(register :porta-in)
will return the byte on port A.
To write to a port we could either use a third parameter, so we could write:
(register :porta-out #xAA)
or take advantage of the in-place operations such as setf and write:
(setf (register :porta-out) #xAA)
To set the I/O lines on a port as outputs you would do:
(register :porta-dir #xFF)
or:
(setf (reg :porta-dir) #xFF)
Note that on AVR processors these functions would need to read and write the peripheral address space rather than the RAM address space.
Suggestions?