Index: pkg/gpio/lib/gpio.dart |
diff --git a/pkg/gpio/lib/gpio.dart b/pkg/gpio/lib/gpio.dart |
index fda5c109e5e924a9636e0fa5e229014a3b0a416f..a429e4e2bc00c52d241a6707e1958835cabf7ed2 100644 |
--- a/pkg/gpio/lib/gpio.dart |
+++ b/pkg/gpio/lib/gpio.dart |
@@ -27,9 +27,7 @@ import 'dart:typed_data'; |
import 'package:file/file.dart'; |
// Foreign functions used. |
-final ForeignFunction _open = ForeignLibrary.main.lookup('open'); |
final ForeignFunction _lseek = ForeignLibrary.main.lookup('lseek'); |
-final ForeignFunction _mmap = ForeignLibrary.main.lookup('mmap'); |
final ForeignFunction _poll = ForeignLibrary.main.lookup('poll'); |
/// GPIO modes. |
@@ -46,6 +44,12 @@ enum Mode { |
/// Base GPIO interface supported by all GPIO implementations. |
abstract class GPIO { |
+ /// The default number of pins for GPIO is 50. |
+ static const int defaultPins = 50; |
+ |
+ /// Number of pins exposed by this GPIO. |
+ int get pins; |
+ |
/// Set the mode of [pin] to [mode]. |
void setMode(int pin, Mode mode); |
@@ -63,162 +67,19 @@ abstract class GPIO { |
bool getPin(int pin); |
} |
-/// Pull-up/down resistor state. |
-enum PullUpDown { |
- floating, |
- pullDown, |
- pullUp, |
-} |
- |
// Internal base class. |
-class _GPIOBase { |
+abstract class GPIOBase implements GPIO { |
// Number of GPIO pins. |
- final int _maxPins; |
+ final int _pins; |
- _GPIOBase(this._maxPins); |
+ GPIOBase(this._pins); |
- void _checkPinRange(int pin) { |
- if (pin < 0 || _maxPins <= pin) { |
- throw new RangeError.index(pin, this, 'pin', null, _maxPins); |
- } |
- } |
-} |
+ get pins => _pins; |
-/// Provide GPIO access on Raspberry Pi using direct memory access. |
-/// |
-/// The following code shows how to turn on GPIO pin 4: |
-/// |
-/// ``` |
-/// PiMemoryMappedGPIO gpio = new PiMemoryMappedGPIO(); |
-/// gpio.setMode(4, Mode.output); |
-/// gpio.setPin(4, true)); |
-/// ``` |
-/// |
-/// The following code shows how to read GPIO pin 17: |
-/// |
-/// ``` |
-/// PiMemoryMappedGPIO gpio = new PiMemoryMappedGPIO(); |
-/// gpio.setMode(17, Mode.input); |
-/// print(gpio.getPin(17)); |
-/// ``` |
-class PiMemoryMappedGPIO extends _GPIOBase implements GPIO { |
- // See datasheet: |
- // https://www.raspberrypi.org/wp-content/uploads/2012/02/BCM2835-ARM-Peripherals.pdf |
- |
- // Raspberry Pi model 1 (A/A+/B) |
- // BCM2708 / BCM 2835 |
- |
- // Raspberry Pi model 2 |
- // BCM2709 / BCM 2836 |
- |
- // Peripherals base address. |
- static const int _baseAddressModel1 = 0x20000000; |
- static const int _baseAddressModel2 = 0x3F000000; |
- static const int _baseAddressGPIOOffset = 0x00200000; |
- |
- // Size of the peripherals area. |
- static const int _blockSize = 4096; |
- |
- // Offsets (in bytes) to various areas. |
- static const int _gpioFunctionSelectBase = 0 << 2; |
- static const int _gpioOutputSetBase = 7 << 2; |
- static const int _gpioOutputClearBase = 10 << 2; |
- static const int _gpioPinLevelBase = 13 << 2; |
- static const int _gpioPullUpPullDown = 37 << 2; |
- static const int _gpioPullUpPullDownClockBase = 38 << 2; |
- |
- // All alternative functions are mapped to `Mode.other` for now. |
- static const _functionToMode = |
- [Mode.input, Mode.output, |
- Mode.other, Mode.other, Mode.other, Mode.other, Mode.other]; |
- |
- int _fd; // File descriptor for /dev/mem. |
- ForeignPointer _addr; |
- ForeignMemory _mem; |
- |
- PiMemoryMappedGPIO(): super(54) { |
- // From /usr/include/x86_64-linux-gnu/bits/fcntl-linux.h. |
- const int oRDWR = 02; // O_RDWR |
- // Found from C code 'printf("%x\n", O_SYNC);'. |
- const int oSync = 0x101000; // O_SYNC |
- |
- // Open /dev/mem to get to the physical memory. |
- var devMem = new ForeignMemory.fromStringAsUTF8('/dev/mem'); |
- _fd = _open.icall$2Retry(devMem, oRDWR | oSync); |
- if (_fd < 0) { |
- throw new GPIOException("Failed to open '/dev/mem'", Foreign.errno); |
+ void checkPinRange(int pin) { |
+ if (pin < 0 || _pins <= pin) { |
+ throw new RangeError.index(pin, this, 'pin', null, _pins); |
} |
- devMem.free(); |
- |
- // From /usr/include/x86_64-linux-gnu/bits/mman-linux.h. |
- const int protRead = 0x1; // PROT_READ. |
- const int protWrite = 0x2; // PROT_WRITE. |
- const int mapShared = 0x01; // MAP_SHARED. |
- |
- _addr = _mmap.pcall$6(0, _blockSize, protRead | protWrite, mapShared, |
- _fd, _baseAddressModel2 + _baseAddressGPIOOffset); |
- _mem = new ForeignMemory.fromAddress(_addr.address, _blockSize); |
- } |
- |
- void setMode(int pin, Mode mode) { |
- _checkPinRange(pin); |
- // GPIO function select registers each have 3 bits for 10 pins. |
- var fsel = (pin ~/ 10); |
- var shift = (pin % 10) * 3; |
- var function = mode == Mode.input ? 0 : 1; |
- var offset = _gpioFunctionSelectBase + (fsel << 2); |
- var value = _mem.getUint32(offset); |
- value = (value & ~(0x07 << shift)) | function << shift; |
- _mem.setUint32(offset, value); |
- } |
- |
- Mode getMode(int pin) { |
- _checkPinRange(pin); |
- // GPIO function select registers each have 3 bits for 10 pins. |
- var fsel = (pin ~/ 10); |
- var shift = (pin % 10) * 3; |
- var offset = _gpioFunctionSelectBase + (fsel << 2); |
- var function = (_mem.getUint32(offset) >> shift) & 0x07; |
- return _functionToMode[function]; |
- } |
- |
- void setPin(int pin, bool value) { |
- _checkPinRange(pin); |
- // GPIO output set and output clear registers each have 1 bits for 32 pins. |
- int register = pin ~/ 32; |
- int shift = pin % 32; |
- if (value) { |
- _mem.setUint32(_gpioOutputSetBase + (register << 2), 1 << shift); |
- } else { |
- _mem.setUint32(_gpioOutputClearBase + (register << 2), 1 << shift); |
- } |
- } |
- |
- bool getPin(int pin) { |
- _checkPinRange(pin); |
- // GPIO pin level registers each have 1 bits for 32 pins. |
- int register = pin ~/ 32; |
- int shift = pin % 32; |
- return |
- (_mem.getUint32(_gpioPinLevelBase + (register << 2)) & 1 << shift) != 0; |
- } |
- |
- /// Set the floating/pull-up/pull-down state of [pin]. |
- /// |
- /// Use `0` for floating, `1` for pull down and `2` for pull-up. |
- void setPullUpDown(int pin, PullUpDown pullUpDown) { |
- _checkPinRange(pin); |
- int register = pin ~/ 32; |
- int shift = pin % 32; |
- // First set the value in the update register. |
- _mem.setUint32(_gpioPullUpPullDown, pullUpDown.index); |
- sleep(1); // Datasheet says: "Wait for 150 cycles". |
- // Then set the clock bit. |
- _mem.setUint32(_gpioPullUpPullDownClockBase + (register << 2), 1 << shift); |
- sleep(1); // Datasheet says: "Wait for 150 cycles". |
- // Clear value and clock bit. |
- _mem.setUint32(_gpioPullUpPullDown, 0); |
- _mem.setUint32(_gpioPullUpPullDownClockBase + (register << 2), 0); |
} |
} |
@@ -267,7 +128,7 @@ enum Trigger { |
/// gpio.setPin(4, value); |
/// } |
/// ``` |
-class SysfsGPIO extends _GPIOBase implements GPIO { |
+class SysfsGPIO extends GPIOBase { |
// For documentation on the GPIO Sysfs Interface for Userspace see |
// https://www.kernel.org/doc/Documentation/gpio/sysfs.txt. |
static const String _basePath = '/sys/class/gpio/'; |
@@ -286,7 +147,7 @@ class SysfsGPIO extends _GPIOBase implements GPIO { |
List<File> _tracked; |
/// Create a GPIO controller using the GPIO Sysfs Interface. |
- SysfsGPIO([int maxPins = 54]): super(maxPins) { |
+ SysfsGPIO([int pins = GPIO.defaultPins]): super(pins) { |
sigurdm
2015/10/05 07:22:18
How come this changed from 54 to 50? Was the other
Søren Gjesse
2015/10/05 07:43:39
The value 50 is a pretty arbitrary default. 54 is
|
// Byte buffers for string constants. |
var data; |
data = new Uint8List(1); |
@@ -316,8 +177,8 @@ class SysfsGPIO extends _GPIOBase implements GPIO { |
// Find the exported pins by just running through all trying to open |
// the value file. |
- _tracked = new List<File>(_maxPins); |
- for (int pin = 0; pin < _maxPins; pin++) { |
+ _tracked = new List<File>(pins); |
+ for (int pin = 0; pin < pins; pin++) { |
_track(pin); |
} |
} |
@@ -343,14 +204,14 @@ class SysfsGPIO extends _GPIOBase implements GPIO { |
} |
void _checkTracked(int pin) { |
- _checkPinRange(pin); |
+ checkPinRange(pin); |
if (!isTracked(pin)) throw 'Pin $pin is not tracked'; |
} |
/// Returns a list with the pins currently tracked. |
List tracked() { |
var result = []; |
- for (int pin = 0; pin < _maxPins; pin++) { |
+ for (int pin = 0; pin < pins; pin++) { |
if (_tracked[pin] != null) result.add(pin); |
} |
return result; |
@@ -478,7 +339,7 @@ class SysfsGPIO extends _GPIOBase implements GPIO { |
} |
void exportPin(int pin) { |
- _checkPinRange(pin); |
+ checkPinRange(pin); |
// If already exported do nothing. |
if (isTracked(pin)) return; |
_exportUnexport(true, pin); |
@@ -486,7 +347,7 @@ class SysfsGPIO extends _GPIOBase implements GPIO { |
} |
void unexportPin(int pin) { |
- _checkPinRange(pin); |
+ checkPinRange(pin); |
// If not exported do nothing. |
if (!isTracked(pin)) return; |
_exportUnexport(false, pin); |