This README:
- Introduction
- Architecture
- Invocation and Command Line Options
- API Quick Start
- List of Peripherals
Related Documents:
- apispec.md - API Specification with Sample Programs
- newdriver - How to Create a New Peripheral
- design.txt - pcdaemon Internal Design
Pcdaemon (this repository) gives your high level applications a simple, intuitive interface to FPGA and non-FPGA based peripherals. The daemon starts empty in the sense that the daemon core provides only a command line interface, leaving the real functionality to a set of drivers implemented as loadable shared object libraries (plug-ins). While intended to support FPGA-based peripherals, pcdaemon has several features you'll find useful for any Linux-to-hardware project:
- Simple publish/subscribe mechanism for sensor data
- All commands and data are printable ASCII over TCP (port 8870)
- Only five API commands: set, get, cat, loadso, and list
- Command line tools to view and set plug-in parameters
- Modular plug-ins (drivers) for easy development
- No dependencies (excluding libc)
- Event-driven and C means low CPU/memory footprint
- Supports both FPGA and non-FPGA peripherals
- GPLv2 License.
The following diagram shows the major components in the Demand
Peripherals system. Major components include: daughter cards,
an FPGA card, pcdaemon, and your application.
Pcdaemon provides an API and acts as a multiplexer for packets to and from the FPGA and for data to and from other devices and services. While FPGA based peripherals are the focus, pcdaemon also includes drivers for a gamepad, GPS receiver, voice output, and an IRC client. Once you have pcdaemon controlling FPGA based peripherals you may find you want its API for all of your devices and services.
Build and install pcdaemon with the following commands:
XXXXXXX
git clone XXXXXX
cd pcdaemon
make
sudo make install
The default installation directories are /usr/local/bin and /usr/local/lib/pc. You can examine /usr/local/lib/pc to see the .so files that are the individual peripheral drivers.
Pcdaemon has several options to let you customize its behaviour.
pcdaemon [options]
options:
-e, --stderr Route messages to stderr instead of log even if running in
background (i.e. no stderr redirection).
-v, --verbosity Set the verbosity level of messages: 0 (errors), 1 (+debug),
2 (+ warnings), or 3 (+ info), default = 0.
-d, --debug Enable debug mode.
-f, --foreground Stay in foreground.
-a, --listen_any Use any/all IP addresses for UI TCP connections
-p, --listen_port Listen for incoming UI connections on this TCP port
-r, --realtime Try to run with real-time extensions.
-V, --version Print version number and exit.
-o, --overload Load .so.X file for slot specified, as slotID:file.so
-h, --help Print usage message.
-s, --serialport Use serial port specified not default port.
A typical debugging invocation of pcdaemon might turn on verbose debugging and stay in the foreground.
pcdaemon -efdv3 -s /dev/ttyUSB0
A typical init script invocation would usually let pcdaemon become a real daemon and might turn on the real-time extensions.
/usr/local/bin/pcdaemon -r
Peripheral number zero serves a dual purpose. It has the enumerator, a list of the peripherals in the FPGA image, and it has any FPGA board specific I/O. The enumerator dictates which .so driver files are loaded into pcdaemon when it starts. You can use the "-s" option to override the enumerator list and load a new driver instead of the one specified in the FPGA binary image. For example, say you have a gpio4 in slot 2 and you want to overload it with a driver that you created called bumper.so. You can replace the expected gpio4.so driver with yours using the command:
pcdaemon -ef -s2:bumper
The application programer's interface to pcdaemon consists of lines of ASCII text sent over a TCP connection. Shown below is a simple example that configures the dual DC motor controller peripheral (dc2) and sets its speeds to 50 and 75 percent.
open : (TCP, localhost, port 8870)
write: "pcset dc2 pwm_frequency 20000"
write: "pcset dc2 watchdog 300"
write: "pcset dc2 mode0 forward"
write: "pcset dc2 mode1 forward"
write: "pcset dc2 speed0 50"
write: "pcset dc2 speed1 75"
Configure four GPIO pins as input without "send on change" and read the pins:
write: "pcset gpio4 interrupt 0"
write: "pcset gpio4 direction 0"
write: "pcget gpio4 pins"
Sensors can stream data without being polled using the pccat command. A stream of sensor data dedicates that TCP connection to the stream of data. Typically you'll have one TCP connection per sensor and one more TCP connection for all other command. Configure the dual quadrature decoder and start its stream of data:
open : (TCP, localhost, port 8870)
write: "pcset quad2 update_rate 50"
write: "pccat quad2 counts"
read : "1 0.007472 0 0.000000"
read : "0 0.000000 0 0.000000"
read : "1 0.007476 0 0.000000"
read : "1 0.007474 0 0.000000"
read : "0 0.000000 0 0.000000"
By default pcdaemon will interogate an attached FPGA to find what drivers it needs. Drivers (again, shared object plug-in modules) for non-FPGA based peripherals need to be loaded explicitly. Load the text-to-speech driver, set the voice to awb, and say "hello world".
write: "pcloadso tts.so"
write: "pcset tts voice awb"
write: "pcset tts speak hello world"
Help text and self inspection are part of pcdaemon. The pclist command displays the drivers that are loaded in the system. Giving pclist the name of a driver as a command option displays help text for that driver. This command is normally run at the shell prompt although the underlying program is just a wrapper around the identical API command. Display the list of loaded drivers and get a description of the quadrature decoder peripheral.
~% pclist
~% pclist quad2
Five commands: If the above examples make sense you may consider yourself an expert on the pcdaemon API. It really is that simple.
Below is a list of available drivers with a link to the help text for the peripheral. A "hw" in parenthesis indicates a peripheral for a specific board design. See the boards repository for more information on these peripherals.
Motion Control | |
dc2 | Dual DC motor controller |
quad2 | Dual quadrature decoder |
servo4 | Quad servo motor controller |
servo8 | Octal servo motor controller |
stepu | Unipolar stepper motor controller |
stepb | Bipolar stepper motor controller |
User Interface | |
aamp | Audio amplifier with volume control and mute (hw) |
lcd6 | Six digit LCD display (hw) |
tif | Text LCD and keypad interface (hw) |
ws28 | Quad WS2812 RBG(W) LED interface |
slide4 | Quad slide potentiometer (hw) |
irio | Consumer IR receiver/transmitter |
rcrx | 6/8 channel RC decoder |
roten | Rotary encoder with center button |
tonegen | Audio tone generator |
touch4 | Quad capacitive touch sensor (hw) |
Input/ Output | |
out4 | Quad binary output |
in4 | Quad binary input |
gpio4 | Quad bidirectional I/O |
io8 | Octal input / output (hw) |
out32 | 32 Channel binary output (hw) |
in32 | 32 Channel binary input (hw) |
serout4 | Quad Serial Output |
serout8 | Octal Serial Output |
Sensors | |
adc812 | Octal 12-bit ADC (hw) |
ping4 | Quad Parallax PING))) interface |
sr04 | Octal SRF04 interface (hw) |
count4 | Quad event counter |
qtr4 | Quad Pololu QTR interface |
qtr8 | Octal Pololu QTR interface |
espi | SPI interface (hw) |
ei2c | I2C interface (hw) |
dac8 | Octal 8-bit DAC (hw) |
qpot | Quad digital potentiometer (hw) |
pwmout4 | Quad PWM output |
pwmin4 | Quad PWM input |
rtc | Real-time clock (hw) |
avr | AVR Microcontroller (hw) |
pulse2 | Dual Pulse Generator |
FPGA Board I/O | |
axo2 | Axelsys Mach XO2 |
bb4io | Demand Peripherals Baseboard |
stpxo2 | Step Mach XO2 |
tang4k | Tang Nano 4K |
basys3 | Digilent Basys3 |
Non-FPGA | |
gamepad | Gamepad Interface |
gps | GPS Interface |
hello | Hello World Sample |
irc | IRC Peer-to-Peer Communications |