Chromium Code Reviews| 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); |