| 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) {
|
| // 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);
|
|
|