11/29/2015

What about UPnP Networking

UPnP history

Universal Plug and Play (UPnP) saw the light in the late 1990s. Networks were just becoming popular. Several vendors were coming up with solutions to make networks  and networked applications easier to manage. One early attempt was Sun's JINI. As a reaction to JINI (or so I was told) Microsoft came with UPnP. The first Microsoft products to ship with UPnP were Windows Millenium Edition and Windows XP. Since then there have been a lot of programs and devices that depend on UPnP (Live Messenger, Playstation, X-Box) and millions of networked devices that have implemented UPnP, such as routers and, increasingly, media players and media servers.

Early versions of the Microsoft UPnP software suffered from a few buffer overflows. Until 2006 these were the most widely known UPnP bugs. In 2006 at the SANE 2006 conference in Delft, the Netherlands, I presented a paper about bugs in other UPnP devices, which are hard to fix and detect for normal users. In January 2008 the GNUcitizen hacker group used a flaw in the Adobe Flash plugin for Internet Explorer to reconfigure routers with UPnP (but only some stacks) and turned a (mostly) local attack into a remote attack.

With more UPnP enabled devices on the market, and more people taking desktop security serious (well, to some extent) some of the focus is shifting towards other devices on the network, such as access points, routers and firewalls, although at the moment it seems that right now desktops are still the prime targets. I have the feeling this will change in the future.

What is UPnP?

The main goal of UPnP is to make adding network devices and networked programs to a network as easy as it is to plug in a piece of hardware into a PC (or even easier, as that is often error prone). The devices and programs find out about the network setup and other networked devices and programs through discovery and advertisements of services and configure themselves accordingly. In short: UPnP is a framework to build networked applications.

The use of the name UPnP has caused a lot of confusion. Product specifications often mention something like 'UPnP support', but are totally unclear about what kind of support. Technically, just implementing device discovery would make a product UPnP compatible.

Depending on the context 'UPnP' can mean completey different things. For a router this often means that the Internet Gateway Device Profile is implemented. For a media device it means that MediaServer, MediaRenderer or RemoteUI is implemented.

UPnP stack layout

The UPnP stack consists of 6 layers, one of which is optional:
  1. Discovery
  2. Description
  3. Control
  4. Eventing
  5. Presentation
The extra, optional, step is 'addressing'.

Addressing

By default a UPnP-capable device tries to get an IP address through DHCP. If no IP address can be obtained through DHCP an address is chosen in the special link local address range (169.254.0.0/16), similar to what is described in RFC 3927.

Discovery

When a UPnP capable device joins a network and wants to know what UPnP services are available on the network, it sends out a discovery message to the multicast address 239.255.255.250 on port 1900 via the UDP protocol. This message contains a header, similar to a HTTP request. This protocol is sometimes referred to as HTTPU (HTTP over UDP):

M-SEARCH * HTTP/1.1
HOST: 239.255.255.250:1900
MAN: ssdp:discover
MX: 10
ST: ssdp:all

All other UPnP devices or programs are required to respond to this message by sending a similar message back to the device, using a UDP unicast, announcing which UPnP profiles the device or program implements. An interesting quirk: it is sent back with UDP unicast to the port the device discovery message was sent from. For every profile it implements one message is sent:

HTTP/1.1 200 OK
CACHE-CONTROL:max-age=1800
EXT:
LOCATION:http://10.0.0.138:80/IGD.xml
SERVER:SpeedTouch 510 4.0.0.9.0 UPnP/1.0 (DG233B00011961)
ST:urn:schemas-upnp-org:service:WANPPPConnection:1
USN:uuid:UPnP-SpeedTouch510::urn:schemas-upnp-org:service:WANPPPConnection:1

The above is a slightly edited response that is sent by an Alcatel/Thomson Speedtouch ADSL modem, which implements the WANPPPConnection profile.

At a regular interval UPnP capable devices or programs have to send a message to announce their services. A notification message is more or less the same as a response message to a discovery, but are sent to the UPnP multicast address 239.255.255.250 on port 1900 via UDP and have the ST header replaced by a similar header called NT.

Description

Every profile offers a description of itself and the services it offers and makes this available via XML. The response message from the discovery phase contains a header called LOCATION (case insensitive), which is a URL where a file in XML format can be downloaded. This file describes (or rather: should describe) the profile that the device or program implements, specifically the URLs that the control and eventing phase should send commands to, but possibly also other meta information about a device, such as an icon that should be displayed by Windows Explorer, the manufacturer of the device, and so on.

There is no default value for this header. In fact, in some devices, especially based on a Broadcom chipset, it is set dynamically at boot time. The only way to be completely sure is to always do device discovery.

Control

The third step in the protocol is "control": a device or program can ask another device or program to perform an action on the client's behalf, using SOAP. SOAP is a protocol that runs over HTTP and uses XML to describe remote procedure calls to a server and return results from those calls. SOAP is mainly used for web based services. For every major programming language libraries are available that can be used to implement SOAP requests and process SOAP responses.

Requesting a service is done by sending a SOAP request to the so called "control URL" of the control point, with the right parameters. The control URL for a specific profile can be found inside the tag in the XML file found at the URL in the LOCATION header from the Description stage. The tag from the Thomson Speedtouch 510 for the WANPPPConnection profile looks like this:


  urn:schemas-upnp-org:service:WANPPPConnection:1
  urn:upnp-org:serviceId:wanpppc:pppoa
  /upnp/control/wanpppcpppoa
  /upnp/event/wanpppcpppoa
  /WANPPPConnection.xml


For sending SOAP requests only the URL inside the controlURL tag is necessary.  It depends on the profile which actions can be performed. The URL found at the URL in the SCPDURL tag is the so called "URL for service description". It describes which SOAP methods can be performed for that profile and what the so-called state variables for the profile are.  What is in this file should match the services that are offered by the device, but in practice they don't always seem to match.

Eventing

In UPnP there is the concept of so called "state variables". These variables are, as the name says, used for keeping some form of state in UPnP devices and programs. A program can subscribe to state changes: when a state variable is changed, the new state is sent to all programs/devices that have subscribed to the event. A program/device can subscribe to the state variables of a service by subscribing to a URL, which can be found in the URL pointed to by LOCATION.


  urn:schemas-upnp-org:service:WANPPPConnection:1
  urn:upnp-org:serviceId:wanpppc:pppoa
  /upnp/control/wanpppcpppoa
  /upnp/event/wanpppcpppoa
  /WANPPPConnection.xml


The eventing protocol in UPnP is based on GENA.

Presentation

The presentation layer in UPnP refers to the human controllable interface, for example, the webinterface on a router. It is surprising to see that these interfaces often don't match with the functionality that you can use through SOAP. For example, it is often impossible to even see on a router which portmappings are active, let alone change them.

UPnP profiles

Actions and state variables can form a so called 'profile'. The UPnP standardization organizations have standardized a few profiles, which are in widespread use. The most used profiles are:
  • Internet Gateway Device (IGD)
  • Audio/Video (A/V), basis for DLNA
Many profiles have subprofiles, which implement specific behaviour, such as the WANIPConnection subprofile in the Internet Gateway Device profile. A device can sometimes implement one (sub)profile multiple times. Top level profiles are usually just containers for several subprofiles.

Implementation caveats

There are a few things you should keep in mind, if you want to implement UPnP functionality for whatever reason.

The most important one is that devices will send responses to M-SEARCH requests to the port that was used for sending the request. You will need to have a program listening on that port. A good solution is to send from UD port 1900 and reuse the socket. There are some incompatibilities between operating systems how you should do this. An extra benefit is that this will also capture a lot of the announcements that are sent regularly over the network.

CREDIT: Armijn Hemel/upnp-hacks.org

8/25/2015

51 Open Source Tools for the Internet of Things


51 Open Source Tools for the Internet of Things


These open source software and hardware projects make it easy for hobbyists, startups and established companies to develop new IoT devices and applications.

According to the market researchers at IDC, there were 9.1 billion Internet of Things (IoT) devices installed at the end of 2013. They expect that number to grow 17.5 percent each year and hit 28.1 billion in 2020, when the total IoT market could be worth more than $7 trillion.
The open source community has been at the forefront of this new trend, creating software and hardware designs that enable nearly anyone to experiment with IoT devices and applications. And the number of open source projects dedicated to IoT has been growing rapidly. Last year, we put together a list of 35 open source IoT projects, and this year, we've extended it to 51 tools.
As always, if you know of additional open source projects that you think should be on our list, feel free to make note in the comments section below.

Operating Systems

1. Contiki
This open source IoT operating system boasts highly efficient memory allocation, full IP networking, power awareness, standards support, dynamic module loading, support for a wide variety of hardware and more. There are a wide variety of papers, books and other support materials to help users and developers get started using it.
2. eLinux
A number of IoT devices run the Linux kernel (or a portion of it). This site provides extensive information about using Linux in embedded systems.
With millions of deployments, FreeRTOS claims to be "the market leading real time operating system (or RTOS), and the de-facto standard solution for microcontrollers and small microprocessors." Optional commercial licensing and support are available.
4. mbed
Developed by ARM and its partners, mbed is an operating system designed for IoT devices that run on ARM processors. It includes a C++ application framework, and the company also offers other development tools and a related device server.
Raspbian is a variation of Debian Linux optimized to run on the Raspberry Pi. It includes more than 35,000 applications that can run on the device.
6. RIOT
RIOT calls itself "the friendly operating system for the Internet of Things," and it aims to be developer-friendly, resource-friendly, and IoT-friendly. Key features include support for C and C++, partial POSIX compliance, multi-threading, energy efficiency and more.
Ubuntu is one of the most popular distributions of Linux, and this variation brings Ubuntu to the Internet of Things. It can run on cloud computing services like Microsoft Azure, Google Compute Engine and Amazon Elastic Compute, as well as on IoT devices like the BeagleBone Black and the Raspberry Pi.
8. TinyOS
Downloaded more than 35,000 times per year, TinyOS is a popular operating system designed for low-power wireless devices, such as those in IoT deployments. It boasts excellent support for networking and low-power operation.
9. Tizen
Governed by the Linux Foundation, Tizen is a Linux-based operating system for mobile and connected devices, and it comes in versions for vehicles, smartphones and tablets, TV and wearables. Samsung sells several products based on the operating system and has been one of its largest supporters.


IoT Platforms

10. Arduino
One of the best-known names among open source IoT projects, Arduino is a platform that encompasses both hardware and software. The software includes an integrated development environment (IDE) for writing code in the Arduino language.
This project aims to be "the go-to platform for makers" and "the universal interface for Internet of Things and M2M." It includes tools for data gathering and analysis, remote control and event-based alerting, and it allows users to control many different devices from a single dashboard. Paid enterprise versions and support are available.
This toolkit includes a smart object API gateway service reference implementation, an HTTP- to-CoAP semantic mapping proxy, gateway-as-a-service deployment, application framework, embedded software agents, semantic discovery and linkage, linked data compatibility, tools for multiple sensor net clients, and Raspberry Pi and cloud micro-instance deployment images. The project also sponsors a meetup group in Silicon Valley.
13. OpenWSN
OpenWSN is the repository for IoT hardware and software projects underway at the University of California Berkeley. Its ultimate goal is to provide a complete standards-based open source IoT stack.
14. Particle
Formerly known as Spark, Particle is a full suite of hardware and software for building IoT devices, applications and services. Particle boards start at just $19, and the software is available on GitHub
15. SiteWhere
SiteWhere aims to help companies build scalable IoT applications and speed their time-to-market with new products and services. It integrates with MongoDB, HBase, Hortonworks, Clouder, Apache Solr and Twilio, and it supports deployment on nearly any cloud computing platform.
This IoT application and API makes it possible to collect and process data from remote devices. Key features include real-time data collection, geolocation data support, data processing, data visualizations and device status messages.
17. Webinos
Webinos is a web-based application platform for the internet of things. Its goal is to enable developers to write applications that run on any device, including IoT devices, cars, TVs and smartphones.
18. Zetta
Based on Node.js, Zetta can create IoT servers that link to various devices and sensors. The website includes a page devoted to projects built with betta that includes a car speed tracker and home security systems.


Hardware

Sold by Arduino's sister organization Genuino, this open source board includes two separate processors: the ATmega32u4 microcontroller that runs Arduino and the Atheros AR9331 that runs a specialized Linux distribution called OpenWrt-Yun. It includes 16 MB of Flash memory, 64 MB RAM, Ethernet, WiFI, USB and a Micro-SD card reader.
This organization offers several different open-source boards, all of which are about the size of a credit card. Their flagship product, the BeagleBone Black promises that users will be able to boot Linux in under 10 seconds and get started with development projects in less than 5 minutes. Their boards can run Linux or Android.
21. Flutter
Designed for hobbyists, students and engineers, Flutter offers a fast ARM processor and long-range wireless communication. It also includes built-in battery charging capabilities and a built-in security chip. It runs Arduino, and prices start at $36 for the basic model.
While many IoT boards rely on ARM processors, Intel also offers a IoT development board known as Galileo. It's Arduino-compatible and boasts a wider range of ports than most similar boards.
Working with the AllSeen Alliance, Local Motors has developed a Rally Car, which they are using as the platform for their Connected Car project. The open source design includes an automotive grade Linux distribution, a Raspberry Pi board, several Arduino relay boards, and Octoblu open source software.
Microduino offers a range of extremely small boards that are about the size of a quarter and start at just $8. They are currently taking orders for their new mCookie modules which stack like Lego blocks. A variety of extension boards and application kits are also available for purchase on the website.
25. OpenADC
Sold by a company called NewAE Technology, OpenADC is an open source hardware platform with an emphasis on hardware security. The company is also behind the CHipWhisperer hardware security project and offers hardware security training.
26. OpenMote
OpenMote offers three different boards: Open-Mote-CC2538, OpenBase and OpenBattery. They can be purchased separately or in kits for complete IoT deployments.
OpenPicus offers several different open source system on a module (SoM) boards, all of which come with the company's free IDE. You can choose from three different kinds of connectivity—Wi-Fi, GPRS or Ethernet. Modules start at €35.
28. Pinoccio
This company sells very small wireless boards that it calls Scouts. Connect your Scouts together into a mesh network called a Troup and then connect the Lead Scout to the Web. Compatible with Arduino.
29. RasWIK
Ciseco (not to be confused with Cisco) offers a Raspberry Pi Wireless Inventors Kit, or RasWIK. It promises that you "can build wireless devices in just a matter of minutes," and it comes with 29 projects for you to try. Prices for the kit start at £49.99.
30. SODAQ
SODAQ, which stands for "Solar-Powered Data Acquisition," offers Arduino-compatible boards that are easy to connect together. The organization's newest offering is called the Mbili (which means "two" in Swahili), and it includes the Atmel ATmega 1284P microcontroller. It's a low-power board that can run on solar energy.
31. Tessel
This open source IoT hardware platform features a modular design that makes prototyping easy. The Tessel 2, which begins shipping in September, costs just $35 and is compatible with Node.js for fast development. Available modules include Accelerometer, Ambient, Relay, Climate, Infrared, Servo, RFID, GPS, MicroSD, Camera, Audio, Lights, Keypad, Motors, Pulse and more.
32. UDOO
Udoo offers several different open source boards that can run Android, Arduino and the UDOObuntu distribution of Linux, as well as some other operating systems. Prices for boards start at $99, or you can use the provided specs to build your own.
33. WeIO
This group wants to make creating Internet-connected objects as easy as creating websites. Its award-winning devices support HTML5 and Python, and prices start at $69.
34. WIZnet
WIZnet makes chips and IoT boards based on those chips. The link above includes details and specifications for its open source hardware products.


Connectivity Software

DeviceHive is a machine-to-machine (M2M) communication framework for smart energy, home automation, remote sensing, telemetry, remote control and monitoring software and other IoT applications. It supports Java, C++, .NET, Python, Javascript, and other platforms.
36. IoTivity
Sponsored by the Open Interconnect Consortium, The IoTivity software allows for device-to-device connectivity. It is an implementation of the OIC's standard specification. Operating System: Linux, Arduino, Tizen


Database

37. InfluxDB
InfluxDB is a "distributed time series database with no external dependencies." That makes it ideal for collecting data from IoT sensors; in fact, it can track data from tens of thousands of sensors sampling more than once per second. Operating System: Linux, OS X


Development Tools

The Eclipse Foundation has a long list of IoT-related projects that include standards and development frameworks. The project also offers a wealth of videos, tutorials, sandboxes and other tools to help new IoT developers get started on their first projects.
39. KinomaJS
The Kinoma platform encompasses both hardware and software tools for prototying IoT devices and applications. KinomaJS, its JavaScript-based application framework, is available under an open source license. Operating System: Windows, Linux, OS X
Based on Java and the Apache Cassandra NoSQL database, Mainspring describes itself as "an open source application framework for building machine to machine (M2M) applications such as remote monitoring, fleet management or smart grid." Features include flexible device modeling, device configuration, communication between devices and applications, data validation and normalization, long-term data storage and data retrieval. Operating System: Windows, Linux, OS X
41. Node-RED
This "visual tool for wiring the Internet of Things" simplifies the process of connect IoT devices with APIs and online services. It is built on Node.js and includes a browser-based flow editor. Operating System: Windows, Linux, OS X


Home Automation Software

42. OpenHAB
This Java-based open source home automation software promises a vendor-agnostic way to control all the IoT devices in your home through a single interface. It allows users to set up their own rules and control their home environment. You can download the software from the site or use it through the my.openHAB cloud service. Operating System: Windows, Linux, OS X, Android
The Thing System's website says, "Today, you have to fight your things. They don't talk to each other, the apps don't work, it's a tower of babel. Our solution — the Thing System — is open source. We'll talk to anything, you can hack the system, it has an open API." It supports a huge list of IoT devices, including those made by Cube Sensors, Parrot, Next, Oregon Scientific, Samsung, Telldus, Aeon Labs, Insteon, Roku, Google, Apple and other manufacturers. Operating System: Windows, Linux, OS X, others


Middleware

44. AllJoyn
Sponsored by the AllSeen Alliance, whose members include the Linux Foundation, Microsoft, LG, Qualcomm, Sharp, Panasonic, Cisco, Symantec and many others, AllJoyn is a "collaborative open-source software framework that makes it easy for devices and apps to discover and communicate with each other." It has supports bindings for C, C++, Objective-C and Java, and it includes per-to-per encryption and authentication. Operating System: Windows, Linux, OS X, Android, iOS Arduino, others
45. Kaa
Focused on speeding IoT projects, Kaa describes itself as "a production-ready, multi-purpose middleware platform for building complete end-to-end IoT solutions, connected applications, and smart products." It enables communication and monitoring between IoT devices and back-end infrastructure, and it can be easily deployed on Amazon's cloud. Operating System: Linux
46. Mango
Mango automation software offers features like data acquisition, real-time monitoring, a high-performance NoSQL database, security and much more. It is available in both a free open source version and paid enterprise versions. Operating System: Windows, Linux, OS X
47. Nimbits
Nimbits describes itself as "a Data Logging Service and Rule Engine Platform for connecting people, sensors and software to the cloud and one another." It includes server software, an open source Java library, an Android client and a public cloud that runs Nimbits Server.
48. OpenIoT
Funded in part by the EU, OpenIoT describes itself as a "blueprint middleware infrastructure for implementing/integrating Internet-of-Things solutions." The project's goals are to be able to collect and process data from nearly any IoT device, stream that data to the cloud and analyze and visualize the collected data. Operating System: Windows, Linux, OS X
This award-winning project boasts users like Philips, Trust Digital Lifestyle Accessories, Ooma, VolkerWessels and others. Free and paid versions are available.


Monitoring

50. Freeboard
This project promises "ridiculously simple dashboards for your devices." It offers a widget-based, drag-and-drop development tool that makes it easy to track the data from your IoT devices. Both free and paid plans are available. Operating system: OS Independent


Printing

This unusual project makes it possible to create your own small, internet-connected printer. Want to talk to the project owners? You can send a message or draw a picture that will be printed on the Exciting Printer in their office.


SOURCE: http://www.datamation.com/mobile-wireless/51-open-source-tools-for-the-internet-of-things-1.html

8/23/2015

Lazarus on Raspberry Pi

Lazarus on Raspberry Pi

Lazarus on Raspbian Wheezy.
Lazarus on Raspbian Wheezy
Raspberry Pi Logo.png
This article applies to Raspberry Pi only.
SOURCE: http://wiki.freepascal.org/Lazarus_on_Raspberry_Pi
The Raspberry Pi is a credit-card-sized single-board computer. It has been developed in the UK by the Raspberry Pi Foundation with the intention of stimulating the teaching of basic computer science in schools. Raspberry Pis are also used for multiple other purposes that are as different as media servers, robotics and control engineering.
The Raspberry Pi Foundation recommends Raspbian Wheezy as standard operating system. Alternative systems running on RPI include RISC OS and various Linux distributions, as well as Android.
Lazarus runs natively under the Raspbian operating system.

Contents

 [hide

Installing and compiling Lazarus

Simple installation under Raspbian

Raspberry Pi 1

In the Raspbian OS it is easy to install Lazarus and Free Pascal. In order to do this simply open a terminal window and type:
sudo apt-get update
sudo apt-get upgrade
sudo apt-get install fpc
sudo apt-get install lazarus
This installs a precompiled, stable version of FPC and Lazarus on the Raspberry Pi. Of course, a network connection is required. Installation may take about 30 minutes, but major portions of this process take place automatically. After installation you may instantly start Lazarus from the "Programming" section of the LXDE start menu.
If you need a newer version, or if Lazarus complains about a broken leakview, here.

Raspberry Pi 2

Since June 2015 the regular "out of the box" installation method also works for Raspberry Pi 2 Model B. The version that gets installed is, however, quite old. For those looking to build the latest FPC and Lazarus IDE see this article.

Cross compiling for the Raspberry Pi from Windows

1. Using fpcup
One way is to use fpcup to set up a cross compiler; follow these instructions: fpcup#Linux_ARM_cross_compiler
2. Using scripts
Alternatively, for a more manual approach using batch files, you can follow these steps.
2.1 Prerequisites
FPC 2.7.1 or higher installed with sourcecode
Install the Windows version from the Linaro binutils for linux gnueabihf into %FPCPATH%/bin/win32-armhf-linux [1]
2.2 Example Build Script (adapt paths as needed)
set PATH=C:\pp\bin\i386-win32;%PATH%;
set FPCMAKEPATH=C:/pp
set FPCPATH=C:/pp
set OUTPATH=C:/pp271
%FPCMAKEPATH%/bin/i386-win32/make distclean OS_TARGET=linux CPU_TARGET=arm  CROSSBINDIR=%FPCPATH%/bin/win32-armhf-linux CROSSOPT="-CpARMV6 -CfVFPV2 -OoFASTMATH" FPC=%FPCPATH%/bin/i386-win32/ppc386.exe
 
%FPCMAKEPATH%/bin/i386-win32/make all OS_TARGET=linux CPU_TARGET=arm CROSSBINDIR=%FPCPATH%/bin/win32-armhf-linux CROSSOPT="-CpARMV6 -CfVFPV2 -OoFASTMATH" FPC=%FPCPATH%/bin/i386-win32/ppc386.exe
if errorlevel 1 goto quit
%FPCMAKEPATH%/bin/i386-win32/make crossinstall CROSSBINDIR=%FPCPATH%/bin/win32-armhf-linux CROSSOPT="-CpARMV6 -CfVFPV2 -OoFASTMATH" OS_TARGET=linux CPU_TARGET=arm FPC=%FPCPATH%/bin/i386-win32/ppc386.exe INSTALL_BASEDIR=%OUTPATH%
 
:quit
pause
With the resulting ppcrossarm.exe and ARM RTL you will be able to build a cross Lazarus version as usual and compile FPC projects for the Raspberry Pi and other armhf devices. Remember that not all - especially Windows - libraries are available for Linux arm.

Compiling from sources

You may want to compile Lazarus from subversion sources. See Michell Computing: Lazarus on the Raspberry Pi for details.
Compiling from sources on Raspberry with Gentoo (and other distro)

If you want to install the latest stable release of fpc and, additional and isolated, the trunk fpc compiler: you can read the following guide. It was written using gentoo but this guide will be useful with any distro: Install fpc on Raspberry with Gentoo

Accessing external hardware

Raspberry Pi pinout
Raspberry Pi pinout of external connectors
One of the goals in the development of Raspberry Pi was to facilitate effortless access to external devices like sensors and actuators. There are five ways to access the I/O facilities from Lazarus and Free Pascal:
  1. Direct access using the BaseUnix unit
  2. Access through encapsulated shell calls
  3. Access through the wiringPi library.
  4. Access through Unit rpi_hal.
  5. Access through Unit PiGpio.
  6. Access through the PascalIO library.

1. Native hardware access

Simple test program for acessing the GPIO port on Raspberry Pi
Test circuit for GPIO access with the described program
Simple demo implementation of the circuit from above on a breadboard
This method provides access to external hardware that doesn't require additional libraries. The only requirement is the BaseUnix library that is part of Free Pascal's RTL.

Switching a device via the GPIO port

The following example lists a simple program that controls the GPIO pin 17 as output to switch an LED, transistor or relais. This program contains a ToggleBox with name GPIO17ToggleBox and for logging return codes a TMemo called LogMemo.
For the example, the anode of a LED has been connected with Pin 11 on the Pi's connector (corresponding to GPIO pin 17 of the BCM2835 SOC) and the LED's cathode was wired via a 68 Ohm resistor to pin 6 of the connector (GND) as previously described by Upton and Halfacree. Subsequently, the LED may be switched on and off with the application's toggle box.
The code requires to be run as root, i.e. either from a root account (not recommended) or via su.
Controlling unit:
unit Unit1;
 
{Demo application for GPIO on Raspberry Pi}
{Inspired by the Python input/output demo application by Gareth Halfacree}
{written for the Raspberry Pi User Guide, ISBN 978-1-118-46446-5}
 
{$mode objfpc}{$H+}
 
interface
 
uses
  Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, StdCtrls,
  Unix, BaseUnix;
 
type
 
  { TForm1 }
 
  TForm1 = class(TForm)
    LogMemo: TMemo;
    GPIO17ToggleBox: TToggleBox;
    procedure FormActivate(Sender: TObject);
    procedure FormClose(Sender: TObject; var CloseAction: TCloseAction);
    procedure GPIO17ToggleBoxChange(Sender: TObject);
  private
    { private declarations }
  public
    { public declarations }
  end;
 
const
  PIN_17: PChar = '17';
  PIN_ON: PChar = '1';
  PIN_OFF: PChar = '0';
  OUT_DIRECTION: PChar = 'out';
 
var
  Form1: TForm1;
  gReturnCode: longint; {stores the result of the IO operation}
 
implementation
 
{$R *.lfm}
 
{ TForm1 }
 
procedure TForm1.FormActivate(Sender: TObject);
var
  fileDesc: integer;
begin
  { Prepare SoC pin 17 (pin 11 on GPIO port) for access: }
  try
    fileDesc := fpopen('/sys/class/gpio/export', O_WrOnly);
    gReturnCode := fpwrite(fileDesc, PIN_17[0], 2);
    LogMemo.Lines.Add(IntToStr(gReturnCode));
  finally
    gReturnCode := fpclose(fileDesc);
    LogMemo.Lines.Add(IntToStr(gReturnCode));
  end;
  { Set SoC pin 17 as output: }
  try
    fileDesc := fpopen('/sys/class/gpio/gpio17/direction', O_WrOnly);
    gReturnCode := fpwrite(fileDesc, OUT_DIRECTION[0], 3);
    LogMemo.Lines.Add(IntToStr(gReturnCode));
  finally
    gReturnCode := fpclose(fileDesc);
    LogMemo.Lines.Add(IntToStr(gReturnCode));
  end;
end;
 
procedure TForm1.FormClose(Sender: TObject; var CloseAction: TCloseAction);
var
  fileDesc: integer;
begin
  { Free SoC pin 17: }
  try
    fileDesc := fpopen('/sys/class/gpio/unexport', O_WrOnly);
    gReturnCode := fpwrite(fileDesc, PIN_17[0], 2);
    LogMemo.Lines.Add(IntToStr(gReturnCode));
  finally
    gReturnCode := fpclose(fileDesc);
    LogMemo.Lines.Add(IntToStr(gReturnCode));
  end;
end;
 
procedure TForm1.GPIO17ToggleBoxChange(Sender: TObject);
var
  fileDesc: integer;
begin
  if GPIO17ToggleBox.Checked then
  begin
    { Swith SoC pin 17 on: }
    try
      fileDesc := fpopen('/sys/class/gpio/gpio17/value', O_WrOnly);
      gReturnCode := fpwrite(fileDesc, PIN_ON[0], 1);
      LogMemo.Lines.Add(IntToStr(gReturnCode));
    finally
      gReturnCode := fpclose(fileDesc);
      LogMemo.Lines.Add(IntToStr(gReturnCode));
    end;
  end
  else
  begin
    { Switch SoC pin 17 off: }
    try
      fileDesc := fpopen('/sys/class/gpio/gpio17/value', O_WrOnly);
      gReturnCode := fpwrite(fileDesc, PIN_OFF[0], 1);
      LogMemo.Lines.Add(IntToStr(gReturnCode));
    finally
      gReturnCode := fpclose(fileDesc);
      LogMemo.Lines.Add(IntToStr(gReturnCode));
    end;
  end;
end;
 
end.
Main program:
program io_test;
 
{$mode objfpc}{$H+}
 
uses
  {$IFDEF UNIX}{$IFDEF UseCThreads}
  cthreads,
  {$ENDIF}{$ENDIF}
  Interfaces, // this includes the LCL widgetset
  Forms, Unit1
  { you can add units after this };
 
{$R *.res}
 
begin
  Application.Initialize;
  Application.CreateForm(TForm1, Form1);
  Application.Run;
end.

Reading the status of a pin

Demo program for reading the status of a GPIO pin
Test circuit for GPIO access with the described program
Possible implementation of this test circuit
Of course it is also possible to read the status of e.g. a switch that is connected to the GPIO port.
The following simple example is very similar to the previous one. It controls the GPIO pin 18 as input for a binary device like a switch, transistor or relais. This program contains a CheckBox with nameGPIO18CheckBox and for logging return codes a TMemo called LogMemo.
For the example, one pole of a push-button has been connected to Pin 12 on the Pi's connector (corresponding to GPIO pin 18 of the BCM2835 SOC) and via a 10 kOhm pull-up resistor with pin 1 (+3.3V, see wiring diagram). The other pole has been wired to pin 6 of the connector (GND). The program senses the status of the button and correspondingly switches the CheckBox on or off, respectively.
Note that the potential of pin 18 is high if the button is released (by virtue of the connection to pin 1 via the pull-up resistor) and low if it is pressed (since in this situation pin 18 is connected to GND via the switch). Therefore, the GPIO pin signals 0 if the button is pressed and 1 if it is released.
This program has again to be executed as root.
Controlling unit:
unit Unit1;
 
{Demo application for GPIO on Raspberry Pi}
{Inspired by the Python input/output demo application by Gareth Halfacree}
{written for the Raspberry Pi User Guide, ISBN 978-1-118-46446-5}
 
{This application reads the status of a push-button}
 
{$mode objfpc}{$H+}
 
interface
 
uses
  Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, StdCtrls,
  ButtonPanel, Unix, BaseUnix;
 
type
 
  { TForm1 }
 
  TForm1 = class(TForm)
    ApplicationProperties1: TApplicationProperties;
    GPIO18CheckBox: TCheckBox;
    LogMemo: TMemo;
    procedure ApplicationProperties1Idle(Sender: TObject; var Done: Boolean);
    procedure FormActivate(Sender: TObject);
    procedure FormClose(Sender: TObject; var CloseAction: TCloseAction);
  private
    { private declarations }
  public
    { public declarations }
  end;
 
const
  PIN_18: PChar = '18';
  IN_DIRECTION: PChar = 'in';
 
var
  Form1: TForm1;
  gReturnCode: longint; {stores the result of the IO operation}
 
implementation
 
{$R *.lfm}
 
{ TForm1 }
 
procedure TForm1.FormActivate(Sender: TObject);
var
  fileDesc: integer;
begin
  { Prepare SoC pin 18 (pin 12 on GPIO port) for access: }
  try
    fileDesc := fpopen('/sys/class/gpio/export', O_WrOnly);
    gReturnCode := fpwrite(fileDesc, PIN_18[0], 2);
    LogMemo.Lines.Add(IntToStr(gReturnCode));
  finally
    gReturnCode := fpclose(fileDesc);
    LogMemo.Lines.Add(IntToStr(gReturnCode));
  end;
  { Set SoC pin 18 as input: }
  try
    fileDesc := fpopen('/sys/class/gpio/gpio18/direction', O_WrOnly);
    gReturnCode := fpwrite(fileDesc, IN_DIRECTION[0], 2);
    LogMemo.Lines.Add(IntToStr(gReturnCode));
  finally
    gReturnCode := fpclose(fileDesc);
    LogMemo.Lines.Add(IntToStr(gReturnCode));
  end;
end;
 
procedure TForm1.ApplicationProperties1Idle(Sender: TObject; var Done: Boolean);
var
  fileDesc: integer;
  buttonStatus: string[1] = '1';
begin
  try
    { Open SoC pin 18 (pin 12 on GPIO port) in read-only mode: }
    fileDesc := fpopen('/sys/class/gpio/gpio18/value', O_RdOnly);
    if fileDesc > 0 then
    begin
      { Read status of this pin (0: button pressed, 1: button released): }
      gReturnCode := fpread(fileDesc, buttonStatus[1], 1);
      LogMemo.Lines.Add(IntToStr(gReturnCode) + ': ' + buttonStatus);
      LogMemo.SelStart := Length(LogMemo.Lines.Text) - 1;
      if buttonStatus = '0' then
        GPIO18CheckBox.Checked := true
      else
        GPIO18CheckBox.Checked := false;
    end;
  finally
    { Close SoC pin 18 (pin 12 on GPIO port) }
    gReturnCode := fpclose(fileDesc);
    LogMemo.Lines.Add(IntToStr(gReturnCode));
    LogMemo.SelStart := Length(LogMemo.Lines.Text) - 1;
  end;
end;
 
procedure TForm1.FormClose(Sender: TObject; var CloseAction: TCloseAction);
var
  fileDesc: integer;
begin
  { Free SoC pin 18: }
  try
    fileDesc := fpopen('/sys/class/gpio/unexport', O_WrOnly);
    gReturnCode := fpwrite(fileDesc, PIN_18[0], 2);
    LogMemo.Lines.Add(IntToStr(gReturnCode));
  finally
    gReturnCode := fpclose(fileDesc);
    LogMemo.Lines.Add(IntToStr(gReturnCode));
  end;
end;
 
end.
The main program is identical to that of the example from above.

2. Hardware access via encapsulated shell calls

Another way to access the hardware is by encapsulating terminal commands. This is achieved by using the fpsystem function. This method gives access to functions that are not supported by the BaseUnix unit. The following code implements a program that has the same functionality as the program resulting from the first listing above.
Controlling unit:
unit Unit1;
 
{Demo application for GPIO on Raspberry Pi}
{Inspired by the Python input/output demo application by Gareth Halfacree}
{written for the Raspberry Pi User Guide, ISBN 978-1-118-46446-5}
 
{$mode objfpc}{$H+}
 
interface
 
uses
  Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, StdCtrls, Unix;
 
type
 
  { TForm1 }
 
  TForm1 = class(TForm)
    LogMemo: TMemo;
    GPIO17ToggleBox: TToggleBox;
    procedure FormActivate(Sender: TObject);
    procedure FormClose(Sender: TObject; var CloseAction: TCloseAction);
    procedure GPIO17ToggleBoxChange(Sender: TObject);
  private
    { private declarations }
  public
    { public declarations }
  end;
 
var
  Form1: TForm1;
  gReturnCode: longint; {stores the result of the IO operation}
 
implementation
 
{$R *.lfm}
 
{ TForm1 }
 
procedure TForm1.FormActivate(Sender: TObject);
begin
  { Prepare SoC pin 17 (pin 11 on GPIO port) for access: }
  gReturnCode := fpsystem('echo "17" > /sys/class/gpio/export');
  LogMemo.Lines.Add(IntToStr(gReturnCode));
  { Set SoC pin 17 as output: }
  gReturnCode := fpsystem('echo "out" > /sys/class/gpio/gpio17/direction');
  LogMemo.Lines.Add(IntToStr(gReturnCode));
end;
 
procedure TForm1.FormClose(Sender: TObject; var CloseAction: TCloseAction);
begin
  { Free SoC pin 17: }
  gReturnCode := fpsystem('echo "17" > /sys/class/gpio/unexport');
  LogMemo.Lines.Add(IntToStr(gReturnCode));
end;
 
procedure TForm1.GPIO17ToggleBoxChange(Sender: TObject);
begin
  if GPIO17ToggleBox.Checked then
  begin
    { Swith SoC pin 17 on: }
    gReturnCode := fpsystem('echo "1" > /sys/class/gpio/gpio17/value');
    LogMemo.Lines.Add(IntToStr(gReturnCode));
  end
  else
  begin
    { Switch SoC pin 17 off: }
    gReturnCode := fpsystem('echo "0" > /sys/class/gpio/gpio17/value');
    LogMemo.Lines.Add(IntToStr(gReturnCode));
  end;
end;
 
end.
The main program is identical to that of the example above. This program has to be executed with root privileges, too.

3. wiringPi procedures and functions

Alex Schaller's wrapper unit for Gordon Henderson's Arduino compatible wiringPi library provides a numbering scheme that resembles that of Arduino boards.
Function wiringPiSetup:longint: Initializes wiringPi system using the wiringPi pin numbering scheme.
Procedure wiringPiGpioMode(mode:longint): Initializes wiringPi system with the Broadcom GPIO pin numbering scheme.
Procedure pullUpDnControl(pin:longint; pud:longint): controls the internal pull-up/down resistors on a GPIO pin.
Procedure pinMode(pin:longint; mode:longint): sets the mode of a pin to either INPUT, OUTPUT, or PWM_OUTPUT.
Procedure digitalWrite(pin:longint; value:longint): sets an output bit.
Procedure pwmWrite(pin:longint; value:longint): sets an output PWM value between 0 and 1024.
Function digitalRead(pin:longint):longint: reads the value of a given Pin, returning 1 or 0.
Procedure delay(howLong:dword): waits for at least howLong milliseconds.
Procedure delayMicroseconds(howLong:dword): waits for at least howLong microseconds.
Function millis:dword: returns the number of milliseconds since the program called one of the wiringPiSetup functions.

4. rpi_hal-Hardware Abstraction Library (GPIO, I2C and SPI functions and procedures)

This Unit with around 1700 Lines of Code provided by Stefan Fischer, delivers procedures and functions to access the rpi HW I2C, SPI and GPIO:
Just an excerpt of the available functions and procedures:
procedure gpio_set_pin (pin:longword;highlevel:boolean); { Set RPi GPIO pin to high or low level; Speed @ 700MHz -> 0.65MHz }
function gpio_get_PIN (pin:longword):boolean; { Get RPi GPIO pin Level is true when Pin level is '1'; false when '0'; Speed @ 700MHz -> 1.17MHz }
procedure gpio_set_input (pin:longword); { Set RPi GPIO pin to input direction }
procedure gpio_set_output(pin:longword); { Set RPi GPIO pin to output direction }
procedure gpio_set_alt (pin,altfunc:longword); { Set RPi GPIO pin to alternate function nr. 0..5 }
procedure gpio_set_gppud (mask:longword); { set RPi GPIO Pull-up/down Register (GPPUD) with mask }
...
function rpi_snr :string; { delivers SNR: 0000000012345678 }
function rpi_hw  :string; { delivers Processor Type: BCM2708 }
function rpi_proc:string; { ARMv6-compatible processor rev 7 (v6l) }
...
function i2c_bus_write(baseadr,reg:word; var data:databuf_t; lgt:byte; testnr:integer) : integer;
function i2c_bus_read (baseadr,reg:word; var data:databuf_t; lgt:byte; testnr:integer) : integer;
function i2c_string_read(baseadr,reg:word; var data:databuf_t; lgt:byte; testnr:integer) : string;
function i2c_string_write(baseadr,reg:word; s:string; testnr:integer) : integer;
...
procedure SPI_Write(devnum:byte; reg,data:word);
function SPI_Read(devnum:byte; reg:word) : byte;
procedure SPI_BurstRead2Buffer (devnum,start_reg:byte; xferlen:longword);
procedure SPI_BurstWriteBuffer (devnum,start_reg:byte; xferlen:longword); { Write 'len' Bytes from Buffer SPI Dev startig at address 'reg' }
...

Test Program (testrpi.pas):
//Simple Test program, which is using rpi_hal;
 
  program testrpi;
  uses rpi_hal;
  begin
    writeln('Show CPU-Info, RPI-HW-Info and Registers:');
    rpi_show_all_info;
    writeln('Let Status LED Blink. Using GPIO functions:');
    GPIO_PIN_TOGGLE_TEST;
    writeln('Test SPI Read function. (piggy back board with installed RFM22B Module is required!)');
    Test_SPI;
  end.

5. PiGpio Low-level native pascal unit (GPIO control instead of wiringPi c library)

This Unit (pigpio.pas[2]) with 270 Lines of Code provided by Gabor Szollosi, works very fast (for ex. GPIO pin output switching frequency 8 MHz) :
unit PiGpio;
{
 BCM2835 GPIO Registry Driver, also can use to manipulate cpu other registry areas
 
 This code is tested only Broadcom bcm2835 cpu, different arm cpus may need different
 gpio driver implementation
 
 2013 Gabor Szollosi
}
{$mode objfpc}{$H+}
 
interface
 
uses
  Classes, SysUtils;
 
const
  REG_GPIO = $20000;//bcm2835 gpio register 0x2000 0000. new fpMap uses page offset, one page is 4096bytes
  // hex 0x1000 so simply calculate 0x2000 0000 / 0x1000  = 0x2000 0
  PAGE_SIZE = 4096;
  BLOCK_SIZE = 4096;
    // The BCM2835 has 54 GPIO pins.
// BCM2835 data sheet, Page 90 onwards.
// There are 6 control registers, each control the functions of a block
// of 10 pins.
 
  CLOCK_BASE = (REG_GPIO + $101);
  GPIO_BASE =  (REG_GPIO + $200);
  GPIO_PWM =   (REG_GPIO + $20C);
 
     INPUT = 0;
     OUTPUT = 1;
     PWM_OUTPUT = 2;
     LOW = False;
     HIGH = True;
     PUD_OFF = 0;
     PUD_DOWN = 1;
     PUD_UP = 2;
 
   // PWM
 
  PWM_CONTROL = 0;
  PWM_STATUS  = 4;
  PWM0_RANGE  = 16;
  PWM0_DATA   = 20;
  PWM1_RANGE  = 32;
  PWM1_DATA   = 36;
 
  PWMCLK_CNTL = 160;
  PWMCLK_DIV  = 164;
 
  PWM1_MS_MODE    = $8000;  // Run in MS mode
  PWM1_USEFIFO    = $2000; // Data from FIFO
  PWM1_REVPOLAR   = $1000;  // Reverse polarity
  PWM1_OFFSTATE   = $0800;  // Ouput Off state
  PWM1_REPEATFF   = $0400;  // Repeat last value if FIFO empty
  PWM1_SERIAL     = $0200;  // Run in serial mode
  PWM1_ENABLE     = $0100;  // Channel Enable
 
  PWM0_MS_MODE    = $0080;  // Run in MS mode
  PWM0_USEFIFO    = $0020;  // Data from FIFO
  PWM0_REVPOLAR   = $0010;  // Reverse polarity
  PWM0_OFFSTATE   = $0008;  // Ouput Off state
  PWM0_REPEATFF   = $0004;  // Repeat last value if FIFO empty
  PWM0_SERIAL     = $0002;  // Run in serial mode
  PWM0_ENABLE     = $0001;  // Channel Enable
 
 
type
 
  { TIoPort }
 
  TIoPort = class // IO bank object
  private         //
 
    //function get_pinDirection(aPin: TGpIoPin): TGpioPinConf;
 
  public
   FGpio: ^LongWord;
   FClk: ^LongWord;
   FPwm: ^LongWord;
   procedure SetPinMode(gpin, mode: byte);
   function GetBit(gpin : byte):boolean;inline; // gets pin bit}
   procedure ClearBit(gpin : byte);inline;// write pin to 0
   procedure SetBit(gpin : byte);inline;// write pin to 1
   procedure SetPullMode(gpin, mode: byte);
   procedure PwmWrite(gpin : byte; value : LongWord);inline;// write pin to pwm value
  end;
 
  { TIoDriver }
 
  TIoDriver = class
  private
 
  public
    destructor Destroy;override;
    function MapIo:boolean;// creates io memory mapping
    procedure UnmapIoRegisrty(FMap: TIoPort);// close io memory mapping
    function CreatePort(PortGpio, PortClk, PortPwm: LongWord):TIoPort; // create new IO port
  end;
 
var
 
    fd: integer;// /dev/mem file handle
procedure delayNanoseconds (howLong : LongWord);
 
 
implementation
 
uses
  baseUnix, Unix;
 
procedure delayNanoseconds (howLong : LongWord);
var
  sleeper, dummy : timespec;
begin
  sleeper.tv_sec  := 0 ;
  sleeper.tv_nsec := howLong ;
  fpnanosleep (@sleeper,@dummy) ;
end;
{ TIoDriver }
//*******************************************************************************
destructor TIoDriver.Destroy;
begin
  inherited Destroy;
end;
//*******************************************************************************
function TIoDriver.MapIo: boolean;
begin
 Result := True;
 fd := fpopen('/dev/mem', O_RdWr or O_Sync); // Open the master /dev/memory device
  if fd < 0 then
  begin
    Result := False; // unsuccessful memory mapping
  end;
 //
end;
//*******************************************************************************
procedure TIoDriver.UnmapIoRegisrty(FMap:TIoPort);
begin
  if FMap.FGpio <> nil then
 begin
   fpMUnmap(FMap.FGpio,PAGE_SIZE);
   FMap.FGpio := Nil;
 end;
 if FMap.FClk <> nil then
 begin
   fpMUnmap(FMap.FClk,PAGE_SIZE);
   FMap.FClk := Nil;
 end;
 if FMap.FPwm <> nil then
 begin
   fpMUnmap(FMap.FPwm ,PAGE_SIZE);
   FMap.FPwm := Nil;
 end;
end;
//*******************************************************************************
function TIoDriver.CreatePort(PortGpio, PortClk, PortPwm: LongWord): TIoPort;
begin
  Result := TIoPort.Create;// new io port, pascal calls new fpMap, where offst is page sized 4096 bytes!!!
  Result.FGpio := FpMmap(Nil, PAGE_SIZE, PROT_READ or PROT_WRITE, MAP_SHARED, fd, PortGpio); // port config gpio memory
  Result.FClk:= FpMmap(Nil, PAGE_SIZE, PROT_READ or PROT_WRITE, MAP_SHARED, fd, PortClk);; // port clk
  Result.FPwm:= FpMmap(Nil, PAGE_SIZE, PROT_READ or PROT_WRITE, MAP_SHARED, fd, PortPwm);; // port pwm
end;
//*******************************************************************************
procedure TIoPort.SetPinMode(gpin, mode: byte);
var
  fSel, shift, alt : byte;
  gpiof, clkf, pwmf : ^LongWord;
begin
  fSel := (gpin div 10)*4 ;  //Select Gpfsel 0 to 5 register
  shift := (gpin mod 10)*3 ;  //0-9 pin shift
  gpiof := Pointer(LongWord(Self.FGpio)+fSel);
  if (mode = INPUT) then
    gpiof^ := gpiof^ and ($FFFFFFFF - (7 shl shift))  //7 shl shift komplemens - Sets bits to zero = input
  else if (mode = OUTPUT) then
  begin
    gpiof^ := gpiof^ and ($FFFFFFFF - (7 shl shift)) or (1 shl shift);
  end
  else if (mode = PWM_OUTPUT) then
  begin
    Case gpin of
      12,13,40,41,45 : alt:= 4 ;
      18,19          : alt:= 2 ;
      else alt:= 0 ;
    end;
    If alt > 0 then
    begin
      gpiof^ := gpiof^ and ($FFFFFFFF - (7 shl shift)) or (alt shl shift);
      clkf := Pointer(LongWord(Self.FClk)+PWMCLK_CNTL);
      clkf^ := $5A000011 or (1 shl 5) ;                  //stop clock
      delayNanoseconds(200);
      clkf := Pointer(LongWord(Self.FClk)+PWMCLK_DIV);
      clkf^ := $5A000000 or (32 shl 12) ; // set pwm clock div to 32 (19.2/3 = 600KHz)
      clkf := Pointer(LongWord(Self.FClk)+PWMCLK_CNTL);
      clkf^ := $5A000011 ;                               //start clock
      Self.ClearBit(gpin);
      pwmf := Pointer(LongWord(Self.FPwm)+PWM_CONTROL);
      pwmf^ := 0 ;            // Disable PWM
      delayNanoseconds(200);
      pwmf := Pointer(LongWord(Self.FPwm)+PWM0_RANGE);
      pwmf^ := $400 ;                             //max: 1023
      delayNanoseconds(200);
      pwmf := Pointer(LongWord(Self.FPwm)+PWM1_RANGE);
      pwmf^ := $400 ;                             //max: 1023
      delayNanoseconds(200);
      // Enable PWMs
      pwmf := Pointer(LongWord(Self.FPwm)+PWM0_DATA);
      pwmf^ := 0 ;                                //start value
      pwmf := Pointer(LongWord(Self.FPwm)+PWM1_DATA);
      pwmf^ := 0 ;                                //start value
      pwmf := Pointer(LongWord(Self.FPwm)+PWM_CONTROL);
      pwmf^ := PWM0_ENABLE or PWM1_ENABLE ;
    end;
  end;
end;
//*******************************************************************************
procedure TIoPort.SetBit(gpin : byte);
var
   gpiof : ^LongWord;
begin
  gpiof := Pointer(LongWord(Self.FGpio) + 28 + (gpin shr 5) shl 2);
  gpiof^ := 1 shl gpin;
end;
//*******************************************************************************
procedure TIoPort.ClearBit(gpin : byte);
var
   gpiof : ^LongWord;
begin
  gpiof := Pointer(LongWord(Self.FGpio) + 40 + (gpin shr 5) shl 2);
  gpiof^ := 1 shl gpin;
end;
//*******************************************************************************
function TIoPort.GetBit(gpin : byte):boolean;
var
   gpiof : ^LongWord;
begin
  gpiof := Pointer(LongWord(Self.FGpio) + 52 + (gpin shr 5) shl 2);
  if (gpiof^ and (1 shl gpin)) = 0 then Result := False else Result := True;
end;
//*******************************************************************************
procedure TIoPort.SetPullMode(gpin, mode: byte);
var
   pudf, pudclkf : ^LongWord;
begin
  pudf := Pointer(LongWord(Self.FGpio) + 148 );
  pudf^ := mode;   //mode = 0, 1, 2 :Off, Down, Up
  delayNanoseconds(200);
  pudclkf := Pointer(LongWord(Self.FGpio) + 152 + (gpin shr 5) shl 2);
  pudclkf^ := 1 shl gpin ;
  delayNanoseconds(200);
  pudf^ := 0 ;
  pudclkf^ := 0 ;
end;
//*******************************************************************************
procedure TIoPort.PwmWrite(gpin : byte; value : Longword);
var
   pwmf : ^LongWord;
   port : byte;
begin
  Case gpin of
      12,18,40 : port:= PWM0_DATA ;
      13,19,41,45 : port:= PWM1_DATA ;
      else exit;
  end;
  pwmf := Pointer(LongWord(Self.FPwm) + port);
  pwmf^ := value and $FFFFFBFF; // $400 complemens
end;
//*******************************************************************************
end.
Controlling Lazarus unit:(Project files[3])
unit Unit1;
 
{Demo application for GPIO on Raspberry Pi}
{Inspired by the Python input/output demo application by Gareth Halfacree}
{written for the Raspberry Pi User Guide, ISBN 978-1-118-46446-5}
 
{$mode objfpc}{$H+}
 
interface
 
uses
  Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, StdCtrls,
  ExtCtrls, Unix, PiGpio;
 
type
 
  { TForm1 }
 
  TForm1 = class(TForm)
    GPIO25In: TButton;
    SpeedButton: TButton;
    LogMemo: TMemo;
    GPIO23switch: TToggleBox;
    Timer1: TTimer;
    GPIO18Pwm: TToggleBox;
    Direction: TToggleBox;
    procedure DirectionChange(Sender: TObject);
    procedure GPIO18PwmChange(Sender: TObject);
    procedure GPIO25InClick(Sender: TObject);
    procedure FormActivate(Sender: TObject);
    procedure FormClose(Sender: TObject; var CloseAction: TCloseAction);
    procedure GPIO23switchChange(Sender: TObject);
    procedure SpeedButtonClick(Sender: TObject);
    procedure Timer1Timer(Sender: TObject);
  private
    { private declarations }
  public
    { public declarations }
  end;
 
const
     INPUT = 0;
     OUTPUT = 1;
     PWM_OUTPUT = 2;
     LOW = False;
     HIGH = True;
     PUD_OFF = 0;
     PUD_DOWN = 1;
     PUD_UP = 2;
 // Convert Raspberry Pi P1 pins (Px) to GPIO port
     P3 = 0;
     P5 = 1;
     P7 = 4;
     P8 = 14;
     P10 = 15;
     P11 = 17;
     P12 = 18;
     P13 = 21;
     P15 = 22;
     P16 = 23;
     P18 = 24;
     P19 = 10;
     P21 = 9;
     P22 = 25;
     P23 = 11;
     P24 = 8;
     P26 = 7;
 
var
  Form1: TForm1;
  GPIO_Driver: TIoDriver;
  GpF: TIoPort;
  PWM :Boolean;
  i, d : integer;
  Pin,Pout,Ppwm : byte;
 
implementation
 
{$R *.lfm}
 
{ TForm1 }
 
procedure TForm1.FormActivate(Sender: TObject);
begin
  if not GPIO_Driver.MapIo then
  begin
     LogMemo.Lines.Add('Error mapping gpio registry');
  end
  else
  begin
    GpF := GpIo_Driver.CreatePort(GPIO_BASE, CLOCK_BASE, GPIO_PWM);
  end ;
  Timer1.Enabled:= True;
  Timer1.Interval:= 25;     //25 ms controll interval
  Pin := P22;
  Pout := P16;
  Ppwm := P12;
  i:=1;
  GpF.SetPinMode(Pout,OUTPUT);
  GpF.SetPinMode(Pin,INPUT);
  GpF.SetPullMode(Pin,PUD_Up);    // Input PullUp High level
end;
 
procedure TForm1.GPIO25InClick(Sender: TObject);
begin
  If GpF.GetBit(Pin) then LogMemo.Lines.Add('In: '+IntToStr(1))
                     else LogMemo.Lines.Add('In: '+IntToStr(0));
end;
 
procedure TForm1.GPIO18PwmChange(Sender: TObject);
begin
  if GPIO18Pwm.Checked then
  begin
    GpF.SetPinMode(Ppwm,PWM_OUTPUT);
    PWM := True;                          //PWM on
  end
  else
  begin
    GpF.SetPinMode(Ppwm,INPUT);
    PWM := False;                          //PWM off
  end;
end;
 
procedure TForm1.DirectionChange(Sender: TObject);
begin
  if Direction.Checked then d:=10 else d:=-10;
end;
 
 
procedure TForm1.FormClose(Sender: TObject; var CloseAction: TCloseAction);
begin
    GpF.SetPinMode(Ppwm,INPUT);
    GpF.ClearBit(Pout);
    GpIo_Driver.UnmapIoRegisrty(GpF);
end;
 
procedure TForm1.GPIO23switchChange(Sender: TObject);
 
Begin
  Timer1.Enabled := False;
  if GPIO23switch.Checked then
  begin
    GpF.SetBit(Pout); //Turn LED on
  end
  else
  begin
    GpF.ClearBit(Pout); //Turn LED off
  end;
  Timer1.Enabled := True;
end;
 
procedure TForm1.SpeedButtonClick(Sender: TObject);
var
  i,p,k,v: longint;
  ido:TDateTime;
begin
  ido:= Time;
  k:= TimeStampToMSecs(DateTimeToTimeStamp(ido));
  LogMemo.Lines.Add('Start: '+TimeToStr(ido));
  p:=10000000 ;
  For i:=1 to p  do Begin
    GpF.SetBit(P16);
    GpF.ClearBit(P16);
  end;
  ido:= Time;
  v:= TimeStampToMSecs(DateTimeToTimeStamp(ido));
  LogMemo.Lines.Add('Stop: '+TimeToStr(ido)+' Frequency: '+
                                IntToStr(p div (v-k))+' kHz');
end;
 
procedure TForm1.Timer1Timer(Sender: TObject);
begin
  If PWM then Begin
    If (d > 0) and (i+d < 1024) then begin
          i:=i+d;
          GpF.PwmWrite(Ppwm,i);
    end ;
    If (d < 0) and (i+d > -1) then begin
          i:=i+d;
          GpF.PwmWrite(Ppwm,i);
    end;
  end;
end;
 
 
end.