Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1160)

Side by Side Diff: pkg/raspberry_pi/lib/raspberry_pi.dart

Issue 1389573002: Refactor Raspberry Pi GPIO and add GPIO mock (Closed) Base URL: git@github.com:dart-lang/fletch.git@master
Patch Set: Remove unused constant Created 5 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « pkg/gpio/lib/gpio_mock.dart ('k') | samples/raspberry_pi/basic/blinky.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2015, the Fletch project authors. Please see the AUTHORS file 1 // Copyright (c) 2015, the Fletch project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE.md file. 3 // BSD-style license that can be found in the LICENSE.md file.
4 4
5 /// Library for the basic Raspberry Pi features. 5 /// Library for the basic Raspberry Pi features.
6 library raspberry_pi; 6 library raspberry_pi;
7 7
8 import 'dart:fletch.ffi';
8 import 'dart:typed_data'; 9 import 'dart:typed_data';
9 10
10 import 'package:file/file.dart'; 11 import 'package:file/file.dart';
12 import 'package:gpio/gpio.dart' as gpio;
13
14 // Foreign functions used.
15 final ForeignFunction _open = ForeignLibrary.main.lookup('open');
16 final ForeignFunction _mmap = ForeignLibrary.main.lookup('mmap');
11 17
12 /// Possible modes of the on-board LEDs 18 /// Possible modes of the on-board LEDs
13 enum OnboardLEDMode { 19 enum OnboardLEDMode {
14 /// The on-board LED is controlled by the system. 20 /// The on-board LED is controlled by the system.
15 system, 21 system,
16 /// The on-board LED is controlled by the user through GPIO. 22 /// The on-board LED is controlled by the user through GPIO.
17 gpio, 23 gpio,
18 /// The on-board LED is pulsing heart-beat. 24 /// The on-board LED is pulsing heart-beat.
19 heartbeat, 25 heartbeat,
20 /// The on-board LED is in timer state. 26 /// The on-board LED is in timer state.
21 timer, 27 timer,
22 } 28 }
23 29
24 /// Class for accessing Raspberry Pi features. 30 /// Class for accessing Raspberry Pi features.
25 /// 31 ///
32 /// Use GPIO through the memory mapped interface:
33 ///
34 /// ```
35 /// import 'package:raspberry_pi/raspberry_pi.dart';
36 /// import 'package:gpio/gpio.dart';
37 ///
38 /// main() {
39 /// RaspberryPi pi = new RaspberryPi();
40 /// GPIO gpio = pi.memoryMappedGPIO; // Selecting memory mapped GPIO.
41 /// gpio.setMode(4, Mode.output);
42 /// gpio.setPin(4, true);
43 /// }
44 /// ```
45 ///
46 /// Use GPIO through the sysfs interface:
47 ///
48 /// ```
49 /// import 'package:raspberry_pi/raspberry_pi.dart';
50 /// import 'package:gpio/gpio.dart';
51 ///
52 /// main() {
53 /// RaspberryPi pi = new RaspberryPi();
54 /// GPIO gpio = pi.sysfsGPIO; // Selecting sysfs GPIO.
55 /// gpio.setMode(4, Mode.output);
56 /// gpio.setPin(4, true);
57 /// }
58 /// ```
59 ///
26 /// Change the activity LED to heartbeat mode: 60 /// Change the activity LED to heartbeat mode:
27 /// 61 ///
28 /// ``` 62 /// ```
29 /// import 'package:raspberry_pi/raspberry_pi.dart'; 63 /// import 'package:raspberry_pi/raspberry_pi.dart';
30 /// 64 ///
31 /// main() { 65 /// main() {
32 /// RaspberryPi pi = new RaspberryPi(); 66 /// RaspberryPi pi = new RaspberryPi();
33 /// pi.leds.activityLED.setMode(OnboardLEDMode.heartbeat); 67 /// pi.leds.activityLED.setMode(OnboardLEDMode.heartbeat);
34 /// } 68 /// }
35 /// ``` 69 /// ```
36 /// 70 ///
37 /// Change the activity LED to gpio mode to allow it to be used as a 71 /// Change the activity LED to gpio mode to allow it to be used as a
38 /// normal GPIO pin. 72 /// normal GPIO pin.
39 /// 73 ///
40 /// ``` 74 /// ```
41 /// import 'package:raspberry_pi/raspberry_pi.dart'; 75 /// import 'package:raspberry_pi/raspberry_pi.dart';
42 /// import 'package:gpio/gpio.dart'; 76 /// import 'package:gpio/gpio.dart';
43 /// 77 ///
44 /// main() { 78 /// main() {
45 /// RaspberryPi pi = new RaspberryPi(); 79 /// RaspberryPi pi = new RaspberryPi();
46 /// GPIO gpio = new PiMemoryMappedGPIO(); 80 /// GPIO gpio = new PiMemoryMappedGPIO();
47 /// pi.leds.activityLED.setMode(OnboardLEDMode.gpio); 81 /// pi.leds.activityLED.setMode(OnboardLEDMode.gpio);
48 /// gpio.setPin(pi.leds.activityLED.pin, true); 82 /// gpio.setPin(pi.leds.activityLED.pin, true);
49 /// } 83 /// }
50 /// ``` 84 /// ```
51 class RaspberryPi { 85 class RaspberryPi {
86 /// The number of GPIO pins on the Raspberry Pi 2.
87 static const int gpioPins = 54;
88 var _memoryMappedGPIO;
89 var _sysfsGPIO;
90
52 /// Provide access to the on-board LEDs. 91 /// Provide access to the on-board LEDs.
53 final OnBoardLEDs leds = new OnBoardLEDs._(); 92 final OnBoardLEDs leds = new OnBoardLEDs._();
54 93
55 RaspberryPi(); 94 RaspberryPi();
95
96 get memoryMappedGPIO {
97 if (_memoryMappedGPIO == null) {
98 _memoryMappedGPIO = new PiMemoryMappedGPIO();
99 }
100 return _memoryMappedGPIO;
101 }
102
103 get sysfsGPIO {
104 if (_sysfsGPIO == null) {
105 _sysfsGPIO = new gpio.SysfsGPIO(gpioPins);
106 }
107 return _sysfsGPIO;
108
109 }
110 }
111
112 /// Pull-up/down resistor state.
113 enum PullUpDown {
114 floating,
115 pullDown,
116 pullUp,
117 }
118
119 /// Provide GPIO access on Raspberry Pi using direct memory access.
120 ///
121 /// The following code shows how to turn on GPIO pin 4:
122 ///
123 /// ```
124 /// PiMemoryMappedGPIO gpio = new PiMemoryMappedGPIO();
125 /// gpio.setMode(4, Mode.output);
126 /// gpio.setPin(4, true));
127 /// ```
128 ///
129 /// The following code shows how to read GPIO pin 17:
130 ///
131 /// ```
132 /// PiMemoryMappedGPIO gpio = new PiMemoryMappedGPIO();
133 /// gpio.setMode(17, Mode.input);
134 /// print(gpio.getPin(17));
135 /// ```
136 class PiMemoryMappedGPIO extends gpio.GPIOBase {
137 // See datasheet:
138 // https://www.raspberrypi.org/wp-content/uploads/2012/02/BCM2835-ARM-Peripher als.pdf
139
140 // Raspberry Pi model 1 (A/A+/B)
141 // BCM2708 / BCM 2835
142
143 // Raspberry Pi model 2
144 // BCM2709 / BCM 2836
145
146 // Peripherals base address.
147 static const int _baseAddressModel1 = 0x20000000;
148 static const int _baseAddressModel2 = 0x3F000000;
149 static const int _baseAddressGPIOOffset = 0x00200000;
150
151 // Size of the peripherals area.
152 static const int _blockSize = 4096;
153
154 // Offsets (in bytes) to various areas.
155 static const int _gpioFunctionSelectBase = 0 << 2;
156 static const int _gpioOutputSetBase = 7 << 2;
157 static const int _gpioOutputClearBase = 10 << 2;
158 static const int _gpioPinLevelBase = 13 << 2;
159 static const int _gpioPullUpPullDown = 37 << 2;
160 static const int _gpioPullUpPullDownClockBase = 38 << 2;
161
162 // All alternative functions are mapped to `Mode.other` for now.
163 static const _functionToMode =
164 [gpio.Mode.input, gpio.Mode.output,
165 gpio.Mode.other, gpio.Mode.other,
166 gpio.Mode.other, gpio.Mode.other, gpio.Mode.other];
167
168 int _fd; // File descriptor for /dev/mem.
169 ForeignPointer _addr;
170 ForeignMemory _mem;
171
172 PiMemoryMappedGPIO(): super(RaspberryPi.gpioPins) {
173 // From /usr/include/x86_64-linux-gnu/bits/fcntl-linux.h.
174 const int oRDWR = 02; // O_RDWR
175 // Found from C code 'printf("%x\n", O_SYNC);'.
176 const int oSync = 0x101000; // O_SYNC
177
178 // Open /dev/mem to get to the physical memory.
179 var devMem = new ForeignMemory.fromStringAsUTF8('/dev/mem');
180 _fd = _open.icall$2Retry(devMem, oRDWR | oSync);
181 if (_fd < 0) {
182 throw new gpio.GPIOException("Failed to open '/dev/mem'", Foreign.errno);
183 }
184 devMem.free();
185
186 // From /usr/include/x86_64-linux-gnu/bits/mman-linux.h.
187 const int protRead = 0x1; // PROT_READ.
188 const int protWrite = 0x2; // PROT_WRITE.
189 const int mapShared = 0x01; // MAP_SHARED.
190
191 _addr = _mmap.pcall$6(0, _blockSize, protRead | protWrite, mapShared,
192 _fd, _baseAddressModel2 + _baseAddressGPIOOffset);
193 _mem = new ForeignMemory.fromAddress(_addr.address, _blockSize);
194 }
195
196 void setMode(int pin, gpio.Mode mode) {
197 checkPinRange(pin);
198 // GPIO function select registers each have 3 bits for 10 pins.
199 var fsel = (pin ~/ 10);
200 var shift = (pin % 10) * 3;
201 var function = mode == gpio.Mode.input ? 0 : 1;
202 var offset = _gpioFunctionSelectBase + (fsel << 2);
203 var value = _mem.getUint32(offset);
204 value = (value & ~(0x07 << shift)) | function << shift;
205 _mem.setUint32(offset, value);
206 }
207
208 gpio.Mode getMode(int pin) {
209 checkPinRange(pin);
210 // GPIO function select registers each have 3 bits for 10 pins.
211 var fsel = (pin ~/ 10);
212 var shift = (pin % 10) * 3;
213 var offset = _gpioFunctionSelectBase + (fsel << 2);
214 var function = (_mem.getUint32(offset) >> shift) & 0x07;
215 return _functionToMode[function];
216 }
217
218 void setPin(int pin, bool value) {
219 checkPinRange(pin);
220 // GPIO output set and output clear registers each have 1 bits for 32 pins.
221 int register = pin ~/ 32;
222 int shift = pin % 32;
223 if (value) {
224 _mem.setUint32(_gpioOutputSetBase + (register << 2), 1 << shift);
225 } else {
226 _mem.setUint32(_gpioOutputClearBase + (register << 2), 1 << shift);
227 }
228 }
229
230 bool getPin(int pin) {
231 checkPinRange(pin);
232 // GPIO pin level registers each have 1 bits for 32 pins.
233 int register = pin ~/ 32;
234 int shift = pin % 32;
235 return
236 (_mem.getUint32(_gpioPinLevelBase + (register << 2)) & 1 << shift) != 0;
237 }
238
239 /// Set the floating/pull-up/pull-down state of [pin].
240 ///
241 /// Use `0` for floating, `1` for pull down and `2` for pull-up.
242 void setPullUpDown(int pin, PullUpDown pullUpDown) {
243 checkPinRange(pin);
244 int register = pin ~/ 32;
245 int shift = pin % 32;
246 // First set the value in the update register.
247 _mem.setUint32(_gpioPullUpPullDown, pullUpDown.index);
248 sleep(1); // Datasheet says: "Wait for 150 cycles".
249 // Then set the clock bit.
250 _mem.setUint32(_gpioPullUpPullDownClockBase + (register << 2), 1 << shift);
251 sleep(1); // Datasheet says: "Wait for 150 cycles".
252 // Clear value and clock bit.
253 _mem.setUint32(_gpioPullUpPullDown, 0);
254 _mem.setUint32(_gpioPullUpPullDownClockBase + (register << 2), 0);
255 }
56 } 256 }
57 257
58 // The on-board LEDs. 258 // The on-board LEDs.
59 enum _OnboardLED { 259 enum _OnboardLED {
60 power, 260 power,
61 activity, 261 activity,
62 } 262 }
63 263
64 /// Access to the on-board LEDs. 264 /// Access to the on-board LEDs.
65 class OnBoardLEDs { 265 class OnBoardLEDs {
(...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after
172 void setMode(OnboardLEDMode mode) { 372 void setMode(OnboardLEDMode mode) {
173 _leds._setMode(_led, mode); 373 _leds._setMode(_led, mode);
174 } 374 }
175 375
176 /// Turn on the LED. 376 /// Turn on the LED.
177 void on() => _leds._setBrightness(_led, true); 377 void on() => _leds._setBrightness(_led, true);
178 378
179 /// Turn off the LED. 379 /// Turn off the LED.
180 void off() => _leds._setBrightness(_led, false); 380 void off() => _leds._setBrightness(_led, false);
181 } 381 }
OLDNEW
« no previous file with comments | « pkg/gpio/lib/gpio_mock.dart ('k') | samples/raspberry_pi/basic/blinky.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698