wiringpi 0.0.1-armv6l-linux

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,2 @@
1
+ require 'mkmf'
2
+ create_makefile('wiringpi/wiringpi')
@@ -0,0 +1,587 @@
1
+ /*
2
+ * wiringPi:
3
+ * Arduino compatable (ish) Wiring library for the Raspberry Pi
4
+ * Copyright (c) 2012 Gordon Henderson
5
+ *
6
+ * Thanks to code samples from Gert Jan van Loo and the
7
+ * BCM2835 ARM Peripherals manual, however it's missing
8
+ * the clock section /grr/mutter/
9
+ ***********************************************************************
10
+ * This file is part of wiringPi:
11
+ * https://projects.drogon.net/raspberry-pi/wiringpi/
12
+ *
13
+ * wiringPi is free software: you can redistribute it and/or modify
14
+ * it under the terms of the GNU General Public License as published by
15
+ * the Free Software Foundation, either version 3 of the License, or
16
+ * (at your option) any later version.
17
+ *
18
+ * wiringPi is distributed in the hope that it will be useful,
19
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
20
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21
+ * GNU General Public License for more details.
22
+ *
23
+ * You should have received a copy of the GNU General Public License
24
+ * along with wiringPi. If not, see <http://www.gnu.org/licenses/>.
25
+ ***********************************************************************
26
+ */
27
+
28
+ // Revisions:
29
+ // 11 Jun 2012:
30
+ // Fixed some typos.
31
+ // Added c++ support for the .h file
32
+ // Added a new function to allow for using my "pin" numbers, or native
33
+ // GPIO pin numbers.
34
+ // Removed my busy-loop delay and replaced it with a call to delayMicroseconds
35
+ //
36
+ // 02 May 2012:
37
+ // Added in the 2 UART pins
38
+ // Change maxPins to numPins to more accurately reflect purpose
39
+
40
+ // Pad drive current fiddling
41
+
42
+ #undef DEBUG_PADS
43
+
44
+ #include <stdio.h>
45
+ #include <stdint.h>
46
+ #include <errno.h>
47
+ #include <string.h>
48
+ #include <time.h>
49
+ #include <fcntl.h>
50
+ #include <sys/mman.h>
51
+
52
+ #include "wiringpi.h"
53
+
54
+ #ifndef TRUE
55
+ #define TRUE (1==1)
56
+ #define FALSE (1==2)
57
+ #endif
58
+
59
+ // Port function select bits
60
+
61
+ #define FSEL_INPT 0b000
62
+ #define FSEL_OUTP 0b001
63
+ #define FSEL_ALT0 0b100
64
+ #define FSEL_ALT0 0b100
65
+ #define FSEL_ALT1 0b101
66
+ #define FSEL_ALT2 0b110
67
+ #define FSEL_ALT3 0b111
68
+ #define FSEL_ALT4 0b011
69
+ #define FSEL_ALT5 0b010
70
+
71
+ // Access from ARM Running Linux
72
+ // Take from Gerts code. Some of this is not in the manual
73
+ // that I can find )-:
74
+
75
+ #define BCM2708_PERI_BASE 0x20000000
76
+ #define GPIO_PADS (BCM2708_PERI_BASE + 0x100000)
77
+ #define CLOCK_BASE (BCM2708_PERI_BASE + 0x101000)
78
+ #define GPIO_BASE (BCM2708_PERI_BASE + 0x200000)
79
+ #define GPIO_PWM (BCM2708_PERI_BASE + 0x20C000)
80
+
81
+ #define PAGE_SIZE (4*1024)
82
+ #define BLOCK_SIZE (4*1024)
83
+
84
+ // PWM
85
+
86
+ #define PWM_CONTROL 0
87
+ #define PWM_STATUS 1
88
+ #define PWM0_RANGE 4
89
+ #define PWM0_DATA 5
90
+ #define PWM1_RANGE 8
91
+ #define PWM1_DATA 9
92
+
93
+ #define PWMCLK_CNTL 40
94
+ #define PWMCLK_DIV 41
95
+
96
+ #define PWM1_MS_MODE 0x8000 // Run in MS mode
97
+ #define PWM1_USEFIFO 0x2000 // Data from FIFO
98
+ #define PWM1_REVPOLAR 0x1000 // Reverse polarity
99
+ #define PWM1_OFFSTATE 0x0800 // Ouput Off state
100
+ #define PWM1_REPEATFF 0x0400 // Repeat last value if FIFO empty
101
+ #define PWM1_SERIAL 0x0200 // Run in serial mode
102
+ #define PWM1_ENABLE 0x0100 // Channel Enable
103
+
104
+ #define PWM0_MS_MODE 0x0080 // Run in MS mode
105
+ #define PWM0_USEFIFO 0x0020 // Data from FIFO
106
+ #define PWM0_REVPOLAR 0x0010 // Reverse polarity
107
+ #define PWM0_OFFSTATE 0x0008 // Ouput Off state
108
+ #define PWM0_REPEATFF 0x0004 // Repeat last value if FIFO empty
109
+ #define PWM0_SERIAL 0x0002 // Run in serial mode
110
+ #define PWM0_ENABLE 0x0001 // Channel Enable
111
+
112
+
113
+ // Locals to hold pointers to the hardware
114
+
115
+ static volatile uint32_t *gpio ;
116
+ static volatile uint32_t *pwm ;
117
+ static volatile uint32_t *clk ;
118
+
119
+ // The BCM2835 has 54 GPIO pins.
120
+ // BCM2835 data sheet, Page 90 onwards.
121
+ // There are 6 control registers, each control the functions of a block
122
+ // of 10 pins.
123
+ // Each control register has 10 sets of 3 bits per GPIO pin:
124
+ //
125
+ // 000 = GPIO Pin X is an input
126
+ // 001 = GPIO Pin X is an output
127
+ // 100 = GPIO Pin X takes alternate function 0
128
+ // 101 = GPIO Pin X takes alternate function 1
129
+ // 110 = GPIO Pin X takes alternate function 2
130
+ // 111 = GPIO Pin X takes alternate function 3
131
+ // 011 = GPIO Pin X takes alternate function 4
132
+ // 010 = GPIO Pin X takes alternate function 5
133
+ //
134
+ // So the 3 bits for port X are:
135
+ // X / 10 + ((X % 10) * 3)
136
+
137
+ // mode
138
+
139
+ static int gpioPinMode ;
140
+
141
+ // Doing it the Arduino way with lookup tables...
142
+ // Yes, it's probably more innefficient than all the bit-twidling, but it
143
+ // does tend to make it all a bit clearer. At least to me!
144
+
145
+ // pinToGpio:
146
+ // Take a Wiring pin (0 through X) and re-map it to the BCM_GPIO pin
147
+
148
+ static int pinToGpio [] =
149
+ {
150
+ 17, 18, 21, 22, 23, 24, 25, 4, // From the Original Wiki - GPIO 0 through 7
151
+ 0, 1, // I2C - SDA0, SCL0
152
+ 8, 7, // SPI - CE1, CE0
153
+ 10, 9, 11, // SPI - MISO, MOSI, SCLK
154
+ 14, 15, // UART - Tx, Rx
155
+ } ;
156
+
157
+ // gpioToGPFSEL:
158
+ // Map a BCM_GPIO pin to it's control port. (GPFSEL 0-5)
159
+
160
+ static uint8_t gpioToGPFSEL [] =
161
+ {
162
+ 0,0,0,0,0,0,0,0,0,0,
163
+ 1,1,1,1,1,1,1,1,1,1,
164
+ 2,2,2,2,2,2,2,2,2,2,
165
+ 3,3,3,3,3,3,3,3,3,3,
166
+ 4,4,4,4,4,4,4,4,4,4,
167
+ 5,5,5,5,5,5,5,5,5,5,
168
+ } ;
169
+
170
+ // gpioToShift
171
+ // Define the shift up for the 3 bits per pin in each GPFSEL port
172
+
173
+ static uint8_t gpioToShift [] =
174
+ {
175
+ 0,3,6,9,12,15,18,21,24,27,
176
+ 0,3,6,9,12,15,18,21,24,27,
177
+ 0,3,6,9,12,15,18,21,24,27,
178
+ 0,3,6,9,12,15,18,21,24,27,
179
+ 0,3,6,9,12,15,18,21,24,27,
180
+ } ;
181
+
182
+ // gpioToGPSET:
183
+ // (Word) offset to the GPIO Set registers for each GPIO pin
184
+
185
+ static uint8_t gpioToGPSET [] =
186
+ {
187
+ 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
188
+ 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
189
+ } ;
190
+
191
+ // gpioToGPCLR:
192
+ // (Word) offset to the GPIO Clear registers for each GPIO pin
193
+
194
+ static uint8_t gpioToGPCLR [] =
195
+ {
196
+ 10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,
197
+ 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,
198
+ } ;
199
+
200
+ // gpioToGPLEV:
201
+ // (Word) offset to the GPIO Input level registers for each GPIO pin
202
+
203
+ static uint8_t gpioToGPLEV [] =
204
+ {
205
+ 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,
206
+ 14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,
207
+ } ;
208
+
209
+ // gpioToPUDCLK
210
+ // (Word) offset to the Pull Up Down Clock regsiter
211
+
212
+ static uint8_t gpioToPUDCLK [] =
213
+ {
214
+ 38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,
215
+ 39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,
216
+ } ;
217
+
218
+ // gpioToPwmALT
219
+ // the ALT value to put a GPIO pin into PWM mode
220
+
221
+ static uint8_t gpioToPwmALT [] =
222
+ {
223
+ 0, 0, 0, 0, 0, 0, 0, 0, // 0 -> 7
224
+ 0, 0, 0, 0, FSEL_ALT0, FSEL_ALT0, 0, 0, // 8 -> 15
225
+ 0, 0, FSEL_ALT5, FSEL_ALT5, 0, 0, 0, 0, // 16 -> 23
226
+ 0, 0, 0, 0, 0, 0, 0, 0, // 24 -> 31
227
+ 0, 0, 0, 0, 0, 0, 0, 0, // 32 -> 39
228
+ FSEL_ALT0, FSEL_ALT0, 0, 0, 0, FSEL_ALT0, 0, 0, // 40 -> 47
229
+ 0, 0, 0, 0, 0, 0, 0, 0, // 48 -> 55
230
+ 0, 0, 0, 0, 0, 0, 0, 0, // 56 -> 63
231
+ } ;
232
+
233
+ static uint8_t gpioToPwmPort [] =
234
+ {
235
+ 0, 0, 0, 0, 0, 0, 0, 0, // 0 -> 7
236
+ 0, 0, 0, 0, PWM0_DATA, PWM1_DATA, 0, 0, // 8 -> 15
237
+ 0, 0, PWM0_DATA, PWM1_DATA, 0, 0, 0, 0, // 16 -> 23
238
+ 0, 0, 0, 0, 0, 0, 0, 0, // 24 -> 31
239
+ 0, 0, 0, 0, 0, 0, 0, 0, // 32 -> 39
240
+ PWM0_DATA, PWM1_DATA, 0, 0, 0, PWM1_DATA, 0, 0, // 40 -> 47
241
+ 0, 0, 0, 0, 0, 0, 0, 0, // 48 -> 55
242
+ 0, 0, 0, 0, 0, 0, 0, 0, // 56 -> 63
243
+
244
+ } ;
245
+
246
+
247
+ //////////////////////////////////////////////////////////////////////////////////
248
+
249
+
250
+ /*
251
+ * wiringPiGpioMode:
252
+ * Set the mode - use Pin numbers (0-16) or GPIO number (seemingly random)
253
+ *********************************************************************************
254
+ */
255
+
256
+ void wiringPiGpioMode (int mode)
257
+ {
258
+ gpioPinMode = mode ;
259
+ }
260
+
261
+
262
+ /*
263
+ * wiringPiSetup:
264
+ * Must be called once at the start of your program execution.
265
+ *********************************************************************************
266
+ */
267
+
268
+ int wiringPiSetup (void)
269
+ {
270
+ int fd ;
271
+ uint8_t *gpioMem, *pwmMem, *clkMem ;
272
+
273
+ #ifdef DEBUG_PADS
274
+ uint8_t *gpioMem, *padsMem, *pwmMem, *clkMem ;
275
+ uint32_t *pads ;
276
+ #endif
277
+
278
+ // Set Pin mode by default
279
+
280
+ wiringPiGpioMode (WPI_MODE_PINS) ;
281
+
282
+ // Open the master /dev/memory device
283
+
284
+ if ((fd = open ("/dev/mem", O_RDWR | O_SYNC) ) < 0)
285
+ {
286
+ fprintf (stderr, "wiringPiSetup: Unable to open /dev/mem: %s\n", strerror (errno)) ;
287
+ return -1 ;
288
+ }
289
+
290
+ // GPIO:
291
+
292
+ // Allocate 2 pages - 1 ...
293
+
294
+ if ((gpioMem = malloc (BLOCK_SIZE + (PAGE_SIZE-1))) == NULL)
295
+ {
296
+ fprintf (stderr, "wiringPiSetup: malloc failed: %s\n", strerror (errno)) ;
297
+ return -1 ;
298
+ }
299
+
300
+ // ... presumably to make sure we can round it up to a whole page size
301
+
302
+ if (((uint32_t)gpioMem % PAGE_SIZE) != 0)
303
+ gpioMem += PAGE_SIZE - ((uint32_t)gpioMem % PAGE_SIZE) ;
304
+
305
+ gpio = (uint32_t *)mmap((caddr_t)gpioMem, BLOCK_SIZE, PROT_READ|PROT_WRITE, MAP_SHARED|MAP_FIXED, fd, GPIO_BASE) ;
306
+
307
+ if ((int32_t)gpio < 0)
308
+ {
309
+ fprintf (stderr, "wiringPiSetup: mmap failed: %s\n", strerror (errno)) ;
310
+ return -1 ;
311
+ }
312
+
313
+ // PWM
314
+
315
+ if ((pwmMem = malloc (BLOCK_SIZE + (PAGE_SIZE-1))) == NULL)
316
+ {
317
+ fprintf (stderr, "wiringPiSetup: pwmMem malloc failed: %s\n", strerror (errno)) ;
318
+ return -1 ;
319
+ }
320
+
321
+ if (((uint32_t)pwmMem % PAGE_SIZE) != 0)
322
+ pwmMem += PAGE_SIZE - ((uint32_t)pwmMem % PAGE_SIZE) ;
323
+
324
+ pwm = (uint32_t *)mmap(pwmMem, BLOCK_SIZE, PROT_READ|PROT_WRITE, MAP_SHARED|MAP_FIXED, fd, GPIO_PWM) ;
325
+
326
+ if ((int32_t)pwm < 0)
327
+ {
328
+ fprintf (stderr, "wiringPiSetup: mmap failed (pwm): %s\n", strerror (errno)) ;
329
+ return -1 ;
330
+ }
331
+
332
+ // Clock control (needed for PWM)
333
+
334
+ if ((clkMem = malloc (BLOCK_SIZE + (PAGE_SIZE-1))) == NULL)
335
+ {
336
+ fprintf (stderr, "wiringPiSetup: clkMem malloc failed: %s\n", strerror (errno)) ;
337
+ return -1 ;
338
+ }
339
+
340
+ if (((uint32_t)clkMem % PAGE_SIZE) != 0)
341
+ clkMem += PAGE_SIZE - ((uint32_t)clkMem % PAGE_SIZE) ;
342
+
343
+ clk = (uint32_t *)mmap(clkMem, BLOCK_SIZE, PROT_READ|PROT_WRITE, MAP_SHARED|MAP_FIXED, fd, CLOCK_BASE) ;
344
+
345
+ if ((int32_t)clk < 0)
346
+ {
347
+ fprintf (stderr, "wiringPiSetup: mmap failed (clk): %s\n", strerror (errno)) ;
348
+ return -1 ;
349
+ }
350
+
351
+ #ifdef DEBUG_PADS
352
+ if ((padsMem = malloc (BLOCK_SIZE + (PAGE_SIZE-1))) == NULL)
353
+ {
354
+ fprintf (stderr, "wiringPiSetup: padsMem malloc failed: %s\n", strerror (errno)) ;
355
+ return -1 ;
356
+ }
357
+
358
+ if (((uint32_t)padsMem % PAGE_SIZE) != 0)
359
+ padsMem += PAGE_SIZE - ((uint32_t)padsMem % PAGE_SIZE) ;
360
+
361
+ pads = (uint32_t *)mmap(padsMem, BLOCK_SIZE, PROT_READ|PROT_WRITE, MAP_SHARED|MAP_FIXED, fd, GPIO_PADS) ;
362
+
363
+ if ((int32_t)pads < 0)
364
+ {
365
+ fprintf (stderr, "wiringPiSetup: mmap failed (pads): %s\n", strerror (errno)) ;
366
+ return -1 ;
367
+ }
368
+
369
+ printf ("Checking pads @ 0x%08X\n", (unsigned int)pads) ;
370
+
371
+ printf ("%08X %08X %08X\n", *(pads + 11), *(pads + 12), *(pads + 13)) ;
372
+ // *(pads + 11) = 0x1F ;
373
+ printf ("%08X %08X %08X\n", *(pads + 11), *(pads + 12), *(pads + 13)) ;
374
+ #endif
375
+
376
+ return 0 ;
377
+ }
378
+
379
+
380
+ /*
381
+ * pinMode:
382
+ * Sets the mode of a pin to be input, output or PWM output
383
+ *********************************************************************************
384
+ */
385
+
386
+ void pinMode (int pin, int mode)
387
+ {
388
+ static int pwmRunning = FALSE ;
389
+
390
+ int gpioPin, fSel, shift ;
391
+ int alt ;
392
+
393
+
394
+ if (gpioPinMode == WPI_MODE_PINS)
395
+ {
396
+ if ((pin < 0) || (pin >= NUM_PINS))
397
+ return ;
398
+ gpioPin = pinToGpio [pin] ;
399
+ }
400
+ else
401
+ gpioPin = pin ;
402
+
403
+ fSel = gpioToGPFSEL [gpioPin] ;
404
+ shift = gpioToShift [gpioPin] ;
405
+
406
+
407
+ /**/ if (mode == INPUT)
408
+ *(gpio + fSel) = (*(gpio + fSel) & ~(7 << shift)) ; // Sets bits to zero = input
409
+ else if (mode == OUTPUT)
410
+ *(gpio + fSel) = (*(gpio + fSel) & ~(7 << shift)) | (1 << shift) ;
411
+ else if (mode == PWM_OUTPUT)
412
+ {
413
+ if ((alt = gpioToPwmALT [gpioPin]) == 0) // Not a PWM pin
414
+ return ;
415
+
416
+ // Set pin to PWM mode
417
+
418
+ *(gpio + fSel) = (*(gpio + fSel) & ~(7 << shift)) | (alt << shift) ;
419
+
420
+ // We didn't initialise the PWM hardware at setup time - because it's possible that
421
+ // something else is using the PWM - e.g. the Audio systems! So if we use PWM
422
+ // here, then we're assuming that nothing else is, otherwise things are going
423
+ // to sound a bit funny...
424
+
425
+ if (!pwmRunning)
426
+ {
427
+
428
+ // Gert/Doms Values
429
+ *(clk + PWMCLK_DIV) = 0x5A000000 | (32<<12) ; // set pwm div to 32 (19.2/3 = 600KHz)
430
+ *(clk + PWMCLK_CNTL) = 0x5A000011 ; // Source=osc and enable
431
+ digitalWrite (pin, LOW) ;
432
+ *(pwm + PWM_CONTROL) = 0 ; // Disable PWM
433
+ delayMicroseconds (10) ;
434
+ *(pwm + PWM0_RANGE) = 0x400 ;
435
+ delayMicroseconds (10) ;
436
+ *(pwm + PWM1_RANGE) = 0x400 ;
437
+ delayMicroseconds (10) ;
438
+
439
+ // Enable PWMs
440
+
441
+ *(pwm + PWM0_DATA) = 512 ;
442
+ *(pwm + PWM1_DATA) = 512 ;
443
+
444
+ *(pwm + PWM_CONTROL) = PWM0_ENABLE | PWM1_ENABLE ;
445
+ }
446
+
447
+ }
448
+
449
+ // When we change mode of any pin, we remove the pull up/downs
450
+
451
+ pullUpDnControl (pin, PUD_OFF) ;
452
+ }
453
+
454
+
455
+ /*
456
+ * digitalWrite:
457
+ * Set an output bit
458
+ *********************************************************************************
459
+ */
460
+
461
+ void digitalWrite (int pin, int value)
462
+ {
463
+ int gpioPin ;
464
+
465
+ if (gpioPinMode == WPI_MODE_PINS)
466
+ {
467
+ if ((pin < 0) || (pin >= NUM_PINS))
468
+ return ;
469
+ gpioPin = pinToGpio [pin] ;
470
+ }
471
+ else
472
+ gpioPin = pin ;
473
+
474
+ if (value == HIGH)
475
+ *(gpio + gpioToGPSET [gpioPin]) = 1 << gpioPin ;
476
+ else
477
+ *(gpio + gpioToGPCLR [gpioPin]) = 1 << gpioPin ;
478
+ }
479
+
480
+
481
+ /*
482
+ * pwnWrite:
483
+ * Set an output PWM value
484
+ *********************************************************************************
485
+ */
486
+
487
+ void pwmWrite (int pin, int value)
488
+ {
489
+ int port, gpioPin ;
490
+
491
+ if (gpioPinMode == WPI_MODE_PINS)
492
+ {
493
+ if ((pin < 0) || (pin >= NUM_PINS))
494
+ return ;
495
+ gpioPin = pinToGpio [pin] ;
496
+ }
497
+ else
498
+ gpioPin = pin ;
499
+
500
+ port = gpioToPwmPort [gpioPin] ;
501
+
502
+ *(pwm + port) = value & ~0x400 ;
503
+ }
504
+
505
+
506
+ /*
507
+ * digitalRead:
508
+ * Read the value of a given Pin, returning HIGH or LOW
509
+ *********************************************************************************
510
+ */
511
+
512
+ int digitalRead (int pin)
513
+ {
514
+ int gpioPin ;
515
+
516
+ if (gpioPinMode == WPI_MODE_PINS)
517
+ {
518
+ if ((pin < 0) || (pin >= NUM_PINS))
519
+ return 0 ;
520
+ gpioPin = pinToGpio [pin] ;
521
+ }
522
+ else
523
+ gpioPin = pin ;
524
+
525
+ if ((*(gpio + gpioToGPLEV [gpioPin]) & (1 << gpioPin)) != 0)
526
+ return HIGH ;
527
+ else
528
+ return LOW ;
529
+ }
530
+
531
+ /*
532
+ * pullUpDownCtrl:
533
+ * Control the internal pull-up/down resistors on a GPIO pin
534
+ * The Arduino only has pull-ups and these are enabled by writing 1
535
+ * to a port when in input mode - this paradigm doesn't quite apply
536
+ * here though.
537
+ *********************************************************************************
538
+ */
539
+
540
+ void pullUpDnControl (int pin, int pud)
541
+ {
542
+ int gpioPin ;
543
+
544
+ if (gpioPinMode == WPI_MODE_PINS)
545
+ {
546
+ if ((pin < 0) || (pin >= NUM_PINS))
547
+ return ;
548
+ gpioPin = pinToGpio [pin] ;
549
+ }
550
+ else
551
+ gpioPin = pin ;
552
+
553
+ *(gpio + 37) = pud ;
554
+ delayMicroseconds (10) ;
555
+ *(gpio + gpioToPUDCLK [gpioPin]) = 1 << gpioPin ;
556
+ delayMicroseconds (10) ;
557
+
558
+ *(gpio + 37) = 0 ;
559
+ *(gpio + gpioToPUDCLK [gpioPin]) = 0 ;
560
+ }
561
+
562
+
563
+ /*
564
+ * delay: delayMicroseconds
565
+ * Wait for some number of milli/micro seconds
566
+ *********************************************************************************
567
+ */
568
+
569
+ void delay (unsigned int howLong)
570
+ {
571
+ struct timespec sleeper, dummy ;
572
+
573
+ sleeper.tv_sec = (time_t)(howLong / 1000) ;
574
+ sleeper.tv_nsec = (long)(howLong % 1000) * 1000000 ;
575
+
576
+ nanosleep (&sleeper, &dummy) ;
577
+ }
578
+
579
+ void delayMicroseconds (unsigned int howLong)
580
+ {
581
+ struct timespec sleeper, dummy ;
582
+
583
+ sleeper.tv_sec = 0 ;
584
+ sleeper.tv_nsec = (long)(howLong * 1000) ;
585
+
586
+ nanosleep (&sleeper, &dummy) ;
587
+ }