Improved sysfs file access code
This commit is contained in:
		@@ -15,28 +15,16 @@ try {
 | 
			
		||||
$gpio->setMapper( new WiringPiMapper(2) );
 | 
			
		||||
 | 
			
		||||
// Access logical pin 0, since we got a mapper assigned. Otherwise this would
 | 
			
		||||
// be the actual GPIO0 pin.
 | 
			
		||||
// be the actual GPIO0 pin. 
 | 
			
		||||
$led = $gpio[0]
 | 
			
		||||
    ->export()
 | 
			
		||||
    ->setDirection("output")
 | 
			
		||||
    ->setValue(0)
 | 
			
		||||
    ->setLabel("red led")
 | 
			
		||||
    ->dumpStatus(true);
 | 
			
		||||
 | 
			
		||||
$btn1 = $gpio[1]
 | 
			
		||||
    ->setDirection("input")
 | 
			
		||||
    ->setValue(0)
 | 
			
		||||
    ->setEdge("rising")
 | 
			
		||||
    ->setHandler(function() { echo "INTERRUPT!\n"; })
 | 
			
		||||
    ->setLabel("button 1")
 | 
			
		||||
    ->dumpStatus(true);
 | 
			
		||||
 | 
			
		||||
$btn2 = $gpio[2]
 | 
			
		||||
    ->setDirection("input")
 | 
			
		||||
    ->setValue(0)
 | 
			
		||||
    ->setEdge("rising")
 | 
			
		||||
    ->setHandler(function() { echo "INTERRUPT!\n"; })
 | 
			
		||||
    ->setLabel("button 2")
 | 
			
		||||
    ->dumpStatus(true);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
$x = 0;
 | 
			
		||||
while(true) {
 | 
			
		||||
    $x = (int)(!$x);
 | 
			
		||||
    $led->setValue($x);
 | 
			
		||||
    usleep(500000);
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										42
									
								
								examples/buttons.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										42
									
								
								examples/buttons.php
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,42 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
require_once __DIR__."/../vendor/autoload.php";
 | 
			
		||||
 | 
			
		||||
use NoccyLabs\Gpio\Gpio;
 | 
			
		||||
use NoccyLabs\Gpio\GpioMapper\WiringPiMapper;
 | 
			
		||||
 | 
			
		||||
try {
 | 
			
		||||
    $gpio = new Gpio();
 | 
			
		||||
} catch (Gpio\Exception $e) {
 | 
			
		||||
    error_log("Error: {$e}");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// The mapper translates GPIO to logical pins and vice versa
 | 
			
		||||
$gpio->setMapper( new WiringPiMapper(2) );
 | 
			
		||||
 | 
			
		||||
// Access logical pin 0, since we got a mapper assigned. Otherwise this would
 | 
			
		||||
// be the actual GPIO0 pin.
 | 
			
		||||
$led = $gpio[0]
 | 
			
		||||
    ->export()
 | 
			
		||||
    ->setDirection("output")
 | 
			
		||||
    ->setValue(0)
 | 
			
		||||
    ->setLabel("red led")
 | 
			
		||||
    ->dumpStatus(true);
 | 
			
		||||
 | 
			
		||||
$btn1 = $gpio[1]
 | 
			
		||||
    ->setDirection("input")
 | 
			
		||||
    ->setValue(0)
 | 
			
		||||
    ->setEdge("rising")
 | 
			
		||||
    ->setHandler(function() { echo "INTERRUPT!\n"; })
 | 
			
		||||
    ->setLabel("button 1")
 | 
			
		||||
    ->dumpStatus(true);
 | 
			
		||||
 | 
			
		||||
$btn2 = $gpio[2]
 | 
			
		||||
    ->setDirection("input")
 | 
			
		||||
    ->setValue(0)
 | 
			
		||||
    ->setEdge("rising")
 | 
			
		||||
    ->setHandler(function() { echo "INTERRUPT!\n"; })
 | 
			
		||||
    ->setLabel("button 2")
 | 
			
		||||
    ->dumpStatus(true);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@@ -2,6 +2,21 @@
 | 
			
		||||
 | 
			
		||||
require_once __DIR__."/../vendor/autoload.php";
 | 
			
		||||
 | 
			
		||||
/* 
 | 
			
		||||
 * This example demonstrates using a 4-button wireless remote control with the
 | 
			
		||||
 * GPIO, in this case with the pins mapped against WiringPi for a Rev2 board.
 | 
			
		||||
 * If you are using this code with any other hardware, please update the mapper
 | 
			
		||||
 * below.
 | 
			
		||||
 *
 | 
			
		||||
 * It is assumed that Pin 0 is the interrupt pin (VT) to signal when a button
 | 
			
		||||
 * press has been received, and Pin 1-4 are connected to the pins for button
 | 
			
		||||
 * A to D on the remote control.
 | 
			
		||||
 *
 | 
			
		||||
 * Note that the Raspberry Pi GPIO is not 5V tolerant, so use an optoisolator
 | 
			
		||||
 * or transistors to ensure that you don't zap your preciouos hardware.
 | 
			
		||||
 *
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
use NoccyLabs\Gpio\Gpio;
 | 
			
		||||
use NoccyLabs\Gpio\GpioMapper\WiringPiMapper;
 | 
			
		||||
 | 
			
		||||
@@ -21,7 +36,12 @@ $led = $gpio[0]
 | 
			
		||||
    ->setDirection("input")
 | 
			
		||||
    ->setEdge("rising")
 | 
			
		||||
    ->setHandler(function($e) use($gpio) {
 | 
			
		||||
        
 | 
			
		||||
            if ($gpio[1]->getValue()) { echo "A"; }
 | 
			
		||||
        elseif ($gpio[2]->getValue()) { echo "B"; }
 | 
			
		||||
        elseif ($gpio[3]->getValue()) { echo "C"; }
 | 
			
		||||
        elseif ($gpio[4]->getValue()) { echo "D"; }
 | 
			
		||||
        else { echo "None"; }
 | 
			
		||||
        echo "\n";
 | 
			
		||||
    })
 | 
			
		||||
    ->setLabel("rfint")
 | 
			
		||||
    ->dumpStatus(true);
 | 
			
		||||
@@ -33,3 +53,7 @@ for($n = 1; $n < 5; $n++) {
 | 
			
		||||
        ->dumpStatus(true);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
while(true) {
 | 
			
		||||
    $gpio->refresh();
 | 
			
		||||
    usleep(10000);
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										36
									
								
								lib/Gpio.php
									
									
									
									
									
								
							
							
						
						
									
										36
									
								
								lib/Gpio.php
									
									
									
									
									
								
							@@ -23,6 +23,18 @@ use NoccyLabs\Gpio\Exception\HardwareException;
 | 
			
		||||
 | 
			
		||||
class Gpio implements \ArrayAccess
 | 
			
		||||
{
 | 
			
		||||
    // Direction
 | 
			
		||||
    const DIR_IN       = "in";
 | 
			
		||||
    const DIR_OUT      = "out";
 | 
			
		||||
    // Values
 | 
			
		||||
    const VAL_HIGH     = 1;
 | 
			
		||||
    const VAL_LOW      = 0;
 | 
			
		||||
    // Edges
 | 
			
		||||
    const EDGE_NONE    = "none";
 | 
			
		||||
    const EDGE_RISING  = "rising";
 | 
			
		||||
    const EDGE_FALLING = "faling";
 | 
			
		||||
    const EDGE_BOTH    = "both";
 | 
			
		||||
 | 
			
		||||
    protected $gpio = array();
 | 
			
		||||
    
 | 
			
		||||
    /** @var NoccyLabs\Gpio\GpioMapperInterface */
 | 
			
		||||
@@ -51,7 +63,29 @@ class Gpio implements \ArrayAccess
 | 
			
		||||
            $pin->doInterrupt();
 | 
			
		||||
        
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    public function getPinFromFd($fd)
 | 
			
		||||
    {
 | 
			
		||||
        foreach($this->fd_pins as $pinfd=>$pin) {
 | 
			
		||||
            if ($pinfd == $fd) { return $pin; }
 | 
			
		||||
        }
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    protected $fd_gpio = array();
 | 
			
		||||
    protected $fd_pins = array();
 | 
			
		||||
    
 | 
			
		||||
    public function enableInterrupt(GpioPin $pin, $fd)
 | 
			
		||||
    {
 | 
			
		||||
        $this->fd_gpio[] = $fd;
 | 
			
		||||
        
 | 
			
		||||
        $this->fd_pins[$fd] = $pin;
 | 
			
		||||
        
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    public function disableInterrupt(GpioPin $pin)
 | 
			
		||||
    {
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    public function setMapper(GpioMapperInterface $mapper=null)
 | 
			
		||||
@@ -64,7 +98,7 @@ class Gpio implements \ArrayAccess
 | 
			
		||||
    {
 | 
			
		||||
        if ($this->mapper) { $index = $this->mapper->mapLogicalToGpioPin($index); }
 | 
			
		||||
        if (empty($this->gpio[$index])) {
 | 
			
		||||
            $this->gpio[$index] = new GpioPin($index);
 | 
			
		||||
            $this->gpio[$index] = new GpioPin($index, $this);
 | 
			
		||||
        }
 | 
			
		||||
        return $this->gpio[$index];
 | 
			
		||||
    }
 | 
			
		||||
 
 | 
			
		||||
@@ -19,6 +19,8 @@
 | 
			
		||||
 | 
			
		||||
namespace NoccyLabs\Gpio;
 | 
			
		||||
 | 
			
		||||
use NoccyLabs\Gpio\Exception\HardwareException;
 | 
			
		||||
 | 
			
		||||
use NoccyLabs\Sansi\Charset as CS;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
@@ -41,10 +43,13 @@ class GpioPin
 | 
			
		||||
    protected $handler;
 | 
			
		||||
 | 
			
		||||
    protected $label;
 | 
			
		||||
    
 | 
			
		||||
    protected $gpio;
 | 
			
		||||
 | 
			
		||||
    public function __construct($pin)
 | 
			
		||||
    public function __construct($pin, Gpio $gpio)
 | 
			
		||||
    {
 | 
			
		||||
        $this->pin = (int)$pin;
 | 
			
		||||
        $this->gpio = $gpio;
 | 
			
		||||
        $this->export();
 | 
			
		||||
        $this->fd = fopen("/sys/class/gpio/gpio{$pin}/value", "rb");
 | 
			
		||||
    }
 | 
			
		||||
@@ -80,13 +85,24 @@ class GpioPin
 | 
			
		||||
    {
 | 
			
		||||
        return $this->value;
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Set a descriptive label for the pin, used for debugging and troubleshooting.
 | 
			
		||||
     *
 | 
			
		||||
     * @param string $label
 | 
			
		||||
     * @return NoccyLabs\Gpio\GpioPin 
 | 
			
		||||
     */    
 | 
			
		||||
    public function setLabel($label)
 | 
			
		||||
    {
 | 
			
		||||
        $this->label = (string)$label;
 | 
			
		||||
        return $this;
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    /**
 | 
			
		||||
     * Get the assigned label for this pin.
 | 
			
		||||
     *
 | 
			
		||||
     * @return string The label
 | 
			
		||||
     */    
 | 
			
		||||
    public function getLabel()
 | 
			
		||||
    {
 | 
			
		||||
        return $this->label;
 | 
			
		||||
@@ -94,9 +110,9 @@ class GpioPin
 | 
			
		||||
    
 | 
			
		||||
    public function export()
 | 
			
		||||
    {
 | 
			
		||||
        @file_put_contents("/sys/class/gpio/export", $this->pin);
 | 
			
		||||
        $this->sysfsWrite(null, "export", $this->pin);
 | 
			
		||||
        if (!file_exists("/sys/class/gpio/gpio{$this->pin}")) {
 | 
			
		||||
            throw new \Exception();
 | 
			
		||||
            throw new HardwareException("Unable to export pin {$this->pin}");
 | 
			
		||||
        }
 | 
			
		||||
        return $this;
 | 
			
		||||
    }
 | 
			
		||||
@@ -107,23 +123,54 @@ class GpioPin
 | 
			
		||||
        return $this;
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    public function sysfsWrite($pin, $file, $value)
 | 
			
		||||
    {
 | 
			
		||||
        if ($pin) {
 | 
			
		||||
            $path = "/sys/class/gpio/gpio{$pin}/{$file}";
 | 
			
		||||
        } else {
 | 
			
		||||
            $path = "/sys/class/gpio/{$file}";
 | 
			
		||||
        }
 | 
			
		||||
        if (!is_writable($path)) {
 | 
			
		||||
            throw new HardwareException("Sysfs file {$path} not writable");
 | 
			
		||||
        }
 | 
			
		||||
        $f = fopen($path,"w+");
 | 
			
		||||
        if (!is_resource($f)) {
 | 
			
		||||
            throw new HardwareException("Unable to write to sysfs file {$path}");
 | 
			
		||||
        }
 | 
			
		||||
        fwrite($f,$value);
 | 
			
		||||
        fclose($f);
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    public function sysfsRead($pin, $file)
 | 
			
		||||
    {
 | 
			
		||||
        $path = "/sys/class/gpio/gpio{$pin}/{$file}";
 | 
			
		||||
        $f = fopen($path,"r");
 | 
			
		||||
        if (!is_resource($f)) {
 | 
			
		||||
            throw new HardwareException("Unable to read from sysfs file {$path}");
 | 
			
		||||
        }
 | 
			
		||||
        $ret = fgets($f);
 | 
			
		||||
        fclose($f);
 | 
			
		||||
        return $ret;
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    public function setEdge($edge)
 | 
			
		||||
    {
 | 
			
		||||
        if (!in_array($edge, array("rising", "falling", "both", "none"))) {
 | 
			
		||||
            throw new \Exception;
 | 
			
		||||
        }
 | 
			
		||||
        $this->edge = $edge;
 | 
			
		||||
        @file_put_contents("/sys/class/gpio/gpio{$this->pin}/edge", $edge);
 | 
			
		||||
        $this->sysfsWrite($this->pin, "edge", $edge);
 | 
			
		||||
        return $this;
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    public function getEdge()
 | 
			
		||||
    {
 | 
			
		||||
        return $this->edge;
 | 
			
		||||
        return $this->sysfsRead($this->pin, "edge");
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    public function setHandler(callable $handler=null)
 | 
			
		||||
    {
 | 
			
		||||
        $this->gpio->setInterruptHandler($this->pin, $this->fd);
 | 
			
		||||
        return $this;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user