Gordons Projects

--> Projects Top-Level GIT

Updated wiringPi.c to work with some pullUpDown stuff
[wiringPi] / wiringPi / wiringPi.c
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 Lesser General Public License as
15  *    published by the Free Software Foundation, either version 3 of the
16  *    License, or (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 Lesser General Public License for more details.
22  *
23  *    You should have received a copy of the GNU Lesser General Public
24  *    License along with wiringPi.
25  *    If not, see <http://www.gnu.org/licenses/>.
26  ***********************************************************************
27  */
28
29 // Revisions:
30 //      19 Jul 2012:
31 //              Moved to the LGPL
32 //              Added an abstraction layer to the main routines to save a tiny
33 //              bit of run-time and make the clode a little cleaner (if a little
34 //              larger)
35 //              Added waitForInterrupt code
36 //              Added piHiPri code
37 //
38 //       9 Jul 2012:
39 //              Added in support to use the /sys/class/gpio interface.
40 //       2 Jul 2012:
41 //              Fixed a few more bugs to do with range-checking when in GPIO mode.
42 //      11 Jun 2012:
43 //              Fixed some typos.
44 //              Added c++ support for the .h file
45 //              Added a new function to allow for using my "pin" numbers, or native
46 //                      GPIO pin numbers.
47 //              Removed my busy-loop delay and replaced it with a call to delayMicroseconds
48 //
49 //      02 May 2012:
50 //              Added in the 2 UART pins
51 //              Change maxPins to numPins to more accurately reflect purpose
52
53 // Pad drive current fiddling
54
55 #undef  DEBUG_PADS
56
57 #include <stdio.h>
58 #include <stdint.h>
59 #include <poll.h>
60 #include <unistd.h>
61 #include <errno.h>
62 #include <string.h>
63 #include <time.h>
64 #include <fcntl.h>
65 #include <sys/time.h>
66 #include <sys/mman.h>
67 #include <sys/types.h>
68 #include <sys/stat.h>
69
70 #include "wiringPi.h"
71
72 // Function stubs
73
74 void (*pinMode)           (int pin, int mode) ;
75 void (*pullUpDnControl)   (int pin, int pud) ;
76 void (*digitalWrite)      (int pin, int value) ;
77 void (*pwmWrite)          (int pin, int value) ;
78 void (*setPadDrive)       (int group, int value) ;
79 int  (*digitalRead)       (int pin) ;
80 int  (*waitForInterrupt)  (int pin, int mS) ;
81 void (*delayMicroseconds) (unsigned int howLong) ;
82
83
84 #ifndef TRUE
85 #define TRUE    (1==1)
86 #define FALSE   (1==2)
87 #endif
88
89 // BCM Magic
90
91 #define BCM_PASSWORD            0x5A000000
92
93
94 // Port function select bits
95
96 #define FSEL_INPT               0b000
97 #define FSEL_OUTP               0b001
98 #define FSEL_ALT0               0b100
99 #define FSEL_ALT0               0b100
100 #define FSEL_ALT1               0b101
101 #define FSEL_ALT2               0b110
102 #define FSEL_ALT3               0b111
103 #define FSEL_ALT4               0b011
104 #define FSEL_ALT5               0b010
105
106 // Access from ARM Running Linux
107 //      Take from Gert/Doms code. Some of this is not in the manual
108 //      that I can find )-:
109
110 #define BCM2708_PERI_BASE                          0x20000000
111 #define GPIO_PADS               (BCM2708_PERI_BASE + 0x100000)
112 #define CLOCK_BASE              (BCM2708_PERI_BASE + 0x101000)
113 #define GPIO_BASE               (BCM2708_PERI_BASE + 0x200000)
114 #define GPIO_TIMER              (BCM2708_PERI_BASE + 0x00B000)
115 #define GPIO_PWM                (BCM2708_PERI_BASE + 0x20C000)
116
117 #define PAGE_SIZE               (4*1024)
118 #define BLOCK_SIZE              (4*1024)
119
120 // PWM
121
122 #define PWM_CONTROL 0
123 #define PWM_STATUS  1
124 #define PWM0_RANGE  4
125 #define PWM0_DATA   5
126 #define PWM1_RANGE  8
127 #define PWM1_DATA   9
128
129 #define PWMCLK_CNTL     40
130 #define PWMCLK_DIV      41
131
132 #define PWM1_MS_MODE    0x8000  // Run in MS mode
133 #define PWM1_USEFIFO    0x2000  // Data from FIFO
134 #define PWM1_REVPOLAR   0x1000  // Reverse polarity
135 #define PWM1_OFFSTATE   0x0800  // Ouput Off state
136 #define PWM1_REPEATFF   0x0400  // Repeat last value if FIFO empty
137 #define PWM1_SERIAL     0x0200  // Run in serial mode
138 #define PWM1_ENABLE     0x0100  // Channel Enable
139
140 #define PWM0_MS_MODE    0x0080  // Run in MS mode
141 #define PWM0_USEFIFO    0x0020  // Data from FIFO
142 #define PWM0_REVPOLAR   0x0010  // Reverse polarity
143 #define PWM0_OFFSTATE   0x0008  // Ouput Off state
144 #define PWM0_REPEATFF   0x0004  // Repeat last value if FIFO empty
145 #define PWM0_SERIAL     0x0002  // Run in serial mode
146 #define PWM0_ENABLE     0x0001  // Channel Enable
147
148 // Timer
149
150 #define TIMER_LOAD      (0x400 >> 2)
151 #define TIMER_VALUE     (0x404 >> 2)
152 #define TIMER_CONTROL   (0x408 >> 2)
153 #define TIMER_IRQ_CLR   (0x40C >> 2)
154 #define TIMER_IRQ_RAW   (0x410 >> 2)
155 #define TIMER_IRQ_MASK  (0x414 >> 2)
156 #define TIMER_RELOAD    (0x418 >> 2)
157 #define TIMER_PRE_DIV   (0x41C >> 2)
158 #define TIMER_COUNTER   (0x420 >> 2)
159
160 // Locals to hold pointers to the hardware
161
162 static volatile uint32_t *gpio ;
163 static volatile uint32_t *pwm ;
164 static volatile uint32_t *clk ;
165 static volatile uint32_t *pads ;
166 static volatile uint32_t *timer ;
167
168 static volatile uint32_t *timerIrqRaw ;
169
170 // The BCM2835 has 54 GPIO pins.
171 //      BCM2835 data sheet, Page 90 onwards.
172 //      There are 6 control registers, each control the functions of a block
173 //      of 10 pins.
174 //      Each control register has 10 sets of 3 bits per GPIO pin:
175 //
176 //      000 = GPIO Pin X is an input
177 //      001 = GPIO Pin X is an output
178 //      100 = GPIO Pin X takes alternate function 0
179 //      101 = GPIO Pin X takes alternate function 1
180 //      110 = GPIO Pin X takes alternate function 2
181 //      111 = GPIO Pin X takes alternate function 3
182 //      011 = GPIO Pin X takes alternate function 4
183 //      010 = GPIO Pin X takes alternate function 5
184 //
185 // So the 3 bits for port X are:
186 //      X / 10 + ((X % 10) * 3)
187
188 // sysFds:
189 //      Map a file descriptor from the /sys/class/gpio/gpioX/value
190
191 static int sysFds [64] ;
192
193 // Doing it the Arduino way with lookup tables...
194 //      Yes, it's probably more innefficient than all the bit-twidling, but it
195 //      does tend to make it all a bit clearer. At least to me!
196
197 // pinToGpio:
198 //      Take a Wiring pin (0 through X) and re-map it to the BCM_GPIO pin
199
200 static int pinToGpio [64] =
201 {
202   17, 18, 21, 22, 23, 24, 25, 4,        // From the Original Wiki - GPIO 0 through 7
203    0,  1,                               // I2C  - SDA0, SCL0
204    8,  7,                               // SPI  - CE1, CE0
205   10,  9, 11,                           // SPI  - MOSI, MISO, SCLK
206   14, 15,                               // UART - Tx, Rx
207
208 // Padding:
209
210           -1, -1, -1,-1,-1,-1,-1, -1, -1, -1, -1, -1, -1, -1, -1,       // ... 31
211   -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,       // ... 47
212   -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,       // ... 63
213 } ;
214
215 // gpioToGPFSEL:
216 //      Map a BCM_GPIO pin to it's control port. (GPFSEL 0-5)
217
218 static uint8_t gpioToGPFSEL [] =
219 {
220   0,0,0,0,0,0,0,0,0,0,
221   1,1,1,1,1,1,1,1,1,1,
222   2,2,2,2,2,2,2,2,2,2,
223   3,3,3,3,3,3,3,3,3,3,
224   4,4,4,4,4,4,4,4,4,4,
225   5,5,5,5,5,5,5,5,5,5,
226 } ;
227
228 // gpioToShift
229 //      Define the shift up for the 3 bits per pin in each GPFSEL port
230
231 static uint8_t gpioToShift [] =
232 {
233   0,3,6,9,12,15,18,21,24,27,
234   0,3,6,9,12,15,18,21,24,27,
235   0,3,6,9,12,15,18,21,24,27,
236   0,3,6,9,12,15,18,21,24,27,
237   0,3,6,9,12,15,18,21,24,27,
238 } ;
239
240 // gpioToGPSET:
241 //      (Word) offset to the GPIO Set registers for each GPIO pin
242
243 static uint8_t gpioToGPSET [] =
244 {
245    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,
246    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,
247 } ;
248
249 // gpioToGPCLR:
250 //      (Word) offset to the GPIO Clear registers for each GPIO pin
251
252 static uint8_t gpioToGPCLR [] =
253 {
254   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,
255   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,
256 } ;
257
258 // gpioToGPLEV:
259 //      (Word) offset to the GPIO Input level registers for each GPIO pin
260
261 static uint8_t gpioToGPLEV [] =
262 {
263   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,
264   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,
265 } ;
266
267 #ifdef notYetReady
268 // gpioToEDS
269 //      (Word) offset to the Event Detect Status
270
271 static uint8_t gpioToEDS [] =
272 {
273   16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,
274   17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,
275 } ;
276
277 // gpioToREN
278 //      (Word) offset to the Rising edgde ENable register
279
280 static uint8_t gpioToREN [] =
281 {
282   19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,
283   20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,
284 } ;
285
286 // gpioToFEN
287 //      (Word) offset to the Falling edgde ENable register
288
289 static uint8_t gpioToFEN [] =
290 {
291   22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,
292   23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,
293 } ;
294 #endif
295
296 // gpioToPUDCLK
297 //      (Word) offset to the Pull Up Down Clock regsiter
298
299 #define GPPUD   37
300
301 static uint8_t gpioToPUDCLK [] =
302 {
303   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,
304   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,
305 } ;
306
307 // gpioToPwmALT
308 //      the ALT value to put a GPIO pin into PWM mode
309
310 static uint8_t gpioToPwmALT [] =
311 {
312           0,         0,         0,         0,         0,         0,         0,         0,       //  0 ->  7
313           0,         0,         0,         0, FSEL_ALT0, FSEL_ALT0,         0,         0,       //  8 -> 15
314           0,         0, FSEL_ALT5, FSEL_ALT5,         0,         0,         0,         0,       // 16 -> 23
315           0,         0,         0,         0,         0,         0,         0,         0,       // 24 -> 31
316           0,         0,         0,         0,         0,         0,         0,         0,       // 32 -> 39
317   FSEL_ALT0, FSEL_ALT0,         0,         0,         0, FSEL_ALT0,         0,         0,       // 40 -> 47
318           0,         0,         0,         0,         0,         0,         0,         0,       // 48 -> 55
319           0,         0,         0,         0,         0,         0,         0,         0,       // 56 -> 63
320 } ;
321
322 static uint8_t gpioToPwmPort [] =
323 {
324           0,         0,         0,         0,         0,         0,         0,         0,       //  0 ->  7
325           0,         0,         0,         0, PWM0_DATA, PWM1_DATA,         0,         0,       //  8 -> 15
326           0,         0, PWM0_DATA, PWM1_DATA,         0,         0,         0,         0,       // 16 -> 23
327           0,         0,         0,         0,         0,         0,         0,         0,       // 24 -> 31
328           0,         0,         0,         0,         0,         0,         0,         0,       // 32 -> 39
329   PWM0_DATA, PWM1_DATA,         0,         0,         0, PWM1_DATA,         0,         0,       // 40 -> 47
330           0,         0,         0,         0,         0,         0,         0,         0,       // 48 -> 55
331           0,         0,         0,         0,         0,         0,         0,         0,       // 56 -> 63
332
333 } ;
334
335
336 // Time for easy calculations
337
338 static unsigned long long epoch ;
339
340 //////////////////////////////////////////////////////////////////////////////////
341
342
343 /*
344  * pinMode:
345  *      Sets the mode of a pin to be input, output or PWM output
346  *********************************************************************************
347  */
348
349 void pinModeGpio (int pin, int mode)
350 {
351   static int pwmRunning  = FALSE ;
352   int fSel, shift, alt ;
353
354   pin &= 63 ;
355
356   fSel    = gpioToGPFSEL [pin] ;
357   shift   = gpioToShift  [pin] ;
358
359   /**/ if (mode == INPUT)
360     *(gpio + fSel) = (*(gpio + fSel) & ~(7 << shift)) ; // Sets bits to zero = input
361   else if (mode == OUTPUT)
362     *(gpio + fSel) = (*(gpio + fSel) & ~(7 << shift)) | (1 << shift) ;
363   else if (mode == PWM_OUTPUT)
364   {
365     if ((alt = gpioToPwmALT [pin]) == 0)        // Not a PWM pin
366       return ;
367
368 // Set pin to PWM mode
369
370     *(gpio + fSel) = (*(gpio + fSel) & ~(7 << shift)) | (alt << shift) ;
371
372 // We didn't initialise the PWM hardware at setup time - because it's possible that
373 //      something else is using the PWM - e.g. the Audio systems! So if we use PWM
374 //      here, then we're assuming that nothing else is, otherwise things are going
375 //      to sound a bit funny...
376
377     if (!pwmRunning)
378     {
379
380 //      Gert/Doms Values
381       *(clk + PWMCLK_DIV)  = BCM_PASSWORD | (32<<12) ;  // set pwm div to 32 (19.2/3 = 600KHz)
382       *(clk + PWMCLK_CNTL) = BCM_PASSWORD | 0x11 ;      // Source=osc and enable
383       digitalWrite (pin, LOW) ;
384       *(pwm + PWM_CONTROL) = 0 ;                        // Disable PWM
385       delayMicroseconds (10) ;
386       *(pwm + PWM0_RANGE) = 0x400 ;
387       delayMicroseconds (10) ;
388       *(pwm + PWM1_RANGE) = 0x400 ;
389       delayMicroseconds (10) ;
390
391 // Enable PWMs
392
393       *(pwm + PWM0_DATA) = 512 ;
394       *(pwm + PWM1_DATA) = 512 ;
395
396       *(pwm + PWM_CONTROL) = PWM0_ENABLE | PWM1_ENABLE ;
397
398       pwmRunning = TRUE ;
399     }
400
401   }
402
403 // When we change mode of any pin, we remove the pull up/downs
404
405 //  delayMicroseconds (300) ;
406 //  pullUpDnControl (pin, PUD_OFF) ;
407 }
408
409 void pinModeWPi (int pin, int mode)
410 {
411   pinModeGpio (pinToGpio [pin & 63], mode) ;
412 }
413
414 void pinModeSys (int pin, int mode)
415 {
416   return ;
417 }
418
419
420 #ifdef notYetReady
421 /*
422  * pinED01:
423  * pinED10:
424  *      Enables edge-detect mode on a pin - from a 0 to a 1 or 1 to 0
425  *      Pin must already be in input mode with appropriate pull up/downs set.
426  *********************************************************************************
427  */
428
429 void pinEnableED01Pi (int pin)
430 {
431   pin = pinToGpio [pin & 63] ;
432 }
433 #endif
434
435
436
437 /*
438  * digitalWrite:
439  *      Set an output bit
440  *********************************************************************************
441  */
442
443 void digitalWriteWPi (int pin, int value)
444 {
445   pin = pinToGpio [pin & 63] ;
446
447   if (value == LOW)
448     *(gpio + gpioToGPCLR [pin]) = 1 << (pin & 31) ;
449   else
450     *(gpio + gpioToGPSET [pin]) = 1 << (pin & 31) ;
451 }
452
453 void digitalWriteGpio (int pin, int value)
454 {
455   pin &= 63 ;
456
457   if (value == LOW)
458     *(gpio + gpioToGPCLR [pin]) = 1 << (pin & 31) ;
459   else
460     *(gpio + gpioToGPSET [pin]) = 1 << (pin & 31) ;
461 }
462
463 void digitalWriteSys (int pin, int value)
464 {
465   pin &= 63 ;
466
467   if (sysFds [pin] != -1)
468   {
469     if (value == LOW)
470       write (sysFds [pin], "0\n", 2) ;
471     else
472       write (sysFds [pin], "1\n", 2) ;
473   }
474 }
475
476
477 /*
478  * pwnWrite:
479  *      Set an output PWM value
480  *********************************************************************************
481  */
482
483 void pwmWriteGpio (int pin, int value)
484 {
485   int port ;
486
487   pin  = pin & 63 ;
488   port = gpioToPwmPort [pin] ;
489
490   *(pwm + port) = value & 0x3FF ;
491 }
492
493 void pwmWriteWPi (int pin, int value)
494 {
495   pwmWriteGpio (pinToGpio [pin & 63], value) ;
496 }
497
498 void pwmWriteSys (int pin, int value)
499 {
500   return ;
501 }
502
503
504 /*
505  * setPadDrive:
506  *      Set the PAD driver value
507  *********************************************************************************
508  */
509
510 void setPadDriveWPi (int group, int value)
511 {
512   uint32_t wrVal ;
513
514   if ((group < 0) || (group > 2))
515     return ;
516
517   wrVal = BCM_PASSWORD | 0x18 | (value & 7) ;
518   *(pads + group + 11) = wrVal ;
519
520 #ifdef  DEBUG_PADS
521   printf ("setPadDrive: Group: %d, value: %d (%08X)\n", group, value, wrVal) ;
522   printf ("Read : %08X\n", *(pads + group + 11)) ;
523 #endif
524 }
525
526 void setPadDriveGpio (int group, int value)
527 {
528   setPadDriveWPi (group, value) ;
529 }
530
531 void setPadDriveSys (int group, int value)
532 {
533   return ;
534 }
535
536
537 /*
538  * digitalRead:
539  *      Read the value of a given Pin, returning HIGH or LOW
540  *********************************************************************************
541  */
542
543 int digitalReadWPi (int pin)
544 {
545   pin = pinToGpio [pin & 63] ;
546
547   if ((*(gpio + gpioToGPLEV [pin]) & (1 << (pin & 31))) != 0)
548     return HIGH ;
549   else
550     return LOW ;
551 }
552
553 int digitalReadGpio (int pin)
554 {
555   pin &= 63 ;
556
557   if ((*(gpio + gpioToGPLEV [pin]) & (1 << (pin & 31))) != 0)
558     return HIGH ;
559   else
560     return LOW ;
561 }
562
563 int digitalReadSys (int pin)
564 {
565   char c ;
566
567   pin &= 63 ;
568
569   if (sysFds [pin] == -1)
570     return 0 ;
571
572   lseek (sysFds [pin], 0L, SEEK_SET) ;
573   read  (sysFds [pin], &c, 1) ;
574   return (c == '0') ? 0 : 1 ;
575 }
576
577
578 /*
579  * pullUpDownCtrl:
580  *      Control the internal pull-up/down resistors on a GPIO pin
581  *      The Arduino only has pull-ups and these are enabled by writing 1
582  *      to a port when in input mode - this paradigm doesn't quite apply
583  *      here though.
584  *********************************************************************************
585  */
586
587 void pullUpDnControlGpio (int pin, int pud)
588 {
589   pin &= 63 ;
590   pud &=  3 ;
591
592   *(gpio + GPPUD)              = pud ;                  delayMicroseconds (5) ;
593   *(gpio + gpioToPUDCLK [pin]) = 1 << (pin & 31) ;      delayMicroseconds (5) ;
594   
595   *(gpio + GPPUD)              = 0 ;                    delayMicroseconds (5) ;
596   *(gpio + gpioToPUDCLK [pin]) = 0 ;                    delayMicroseconds (5) ;
597 }
598
599 void pullUpDnControlWPi (int pin, int pud)
600 {
601   pullUpDnControlGpio (pinToGpio [pin & 63], pud) ;
602 }
603
604 void pullUpDnControlSys (int pin, int pud)
605 {
606   return ;
607 }
608
609
610 /*
611  * waitForInterrupt:
612  *      Wait for Interrupt on a GPIO pin.
613  *      This is actually done via the /sys/class/gpio interface regardless of
614  *      the wiringPi access mode in-use. Maybe sometime it might get a better
615  *      way for a bit more efficiency.
616  *********************************************************************************
617  */
618
619 int waitForInterruptSys (int pin, int mS)
620 {
621   int fd, x ;
622   char buf [8] ;
623   struct pollfd polls ;
624
625   if ((fd = sysFds [pin & 63]) == -1)
626     return -2 ;
627
628 // Do a dummy read
629
630   x = read (fd, buf, 6) ;
631   if (x < 0)
632     return x ;
633
634 // And seek
635
636   lseek (fd, 0, SEEK_SET) ;
637
638 // Setup poll structure
639
640   polls.fd     = fd ;
641   polls.events = POLLPRI ;      // Urgent data!
642
643 // Wait for it ...
644
645   return poll (&polls, 1, mS) ;
646 }
647
648 int waitForInterruptWPi (int pin, int mS)
649 {
650   return waitForInterruptSys (pinToGpio [pin & 63], mS) ;
651 }
652
653 int waitForInterruptGpio (int pin, int mS)
654 {
655   return waitForInterruptSys (pin, mS) ;
656 }
657
658
659
660
661 /*
662  * delay:
663  *      Wait for some number of milli seconds
664  *********************************************************************************
665  */
666
667 void delay (unsigned int howLong)
668 {
669   struct timespec sleeper, dummy ;
670
671   sleeper.tv_sec  = (time_t)(howLong / 1000) ;
672   sleeper.tv_nsec = (long)(howLong % 1000) * 1000000 ;
673
674   nanosleep (&sleeper, &dummy) ;
675 }
676
677
678 /*
679  * delayMicroseconds:
680  *      This is somewhat intersting. It seems that on the Pi, a single call
681  *      to nanosleep takes some 80 to 130 microseconds anyway, so while
682  *      obeying the standards (may take longer), it's not always what we
683  *      want!
684  *
685  *      So what I'll do now is if the delay is less than 100uS we'll do it
686  *      in a hard loop, watching a built-in counter on the ARM chip. This is
687  *      somewhat sub-optimal in that it uses 100% CPU, something not an issue
688  *      in a microcontroller, but under a multi-tasking, multi-user OS, it's
689  *      wastefull, however we've no real choice )-:
690  *********************************************************************************
691  */
692
693 void delayMicrosecondsSys (unsigned int howLong)
694 {
695   struct timespec sleeper, dummy ;
696
697   sleeper.tv_sec  = 0 ;
698   sleeper.tv_nsec = (long)(howLong * 1000) ;
699
700   nanosleep (&sleeper, &dummy) ;
701 }
702
703 void delayMicrosecondsHard (unsigned int howLong)
704 {
705   *(timer + TIMER_LOAD)    = howLong ;
706   *(timer + TIMER_IRQ_CLR) = 0 ;
707
708   while (*timerIrqRaw == 0)
709     ;
710 }
711
712 void delayMicrosecondsWPi (unsigned int howLong)
713 {
714   struct timespec sleeper, dummy ;
715
716   /**/ if (howLong ==   0)
717     return ;
718   else if (howLong  < 100)
719     delayMicrosecondsHard (howLong) ;
720   else
721   {
722     sleeper.tv_sec  = 0 ;
723     sleeper.tv_nsec = (long)(howLong * 1000) ;
724     nanosleep (&sleeper, &dummy) ;
725   }
726 }
727
728
729 /*
730  * millis:
731  *      Return a number of milliseconds as an unsigned int.
732  *********************************************************************************
733  */
734
735 unsigned int millis (void)
736 {
737   struct timeval tv ;
738   unsigned long long t1 ;
739
740   gettimeofday (&tv, NULL) ;
741
742   t1 = (tv.tv_sec * 1000000 + tv.tv_usec) / 1000 ;
743
744   return (uint32_t)(t1 - epoch) ;
745 }
746
747
748 /*
749  * wiringPiSetup:
750  *      Must be called once at the start of your program execution.
751  *
752  * Default setup: Initialises the system into wiringPi Pin mode and uses the
753  *      memory mapped hardware directly.
754  *********************************************************************************
755  */
756
757 int wiringPiSetup (void)
758 {
759   int      fd ;
760   uint8_t *gpioMem, *pwmMem, *clkMem, *padsMem, *timerMem ;
761   struct timeval tv ;
762
763             pinMode =           pinModeWPi ;
764     pullUpDnControl =   pullUpDnControlWPi ;
765        digitalWrite =      digitalWriteWPi ;
766            pwmWrite =          pwmWriteWPi ;
767         setPadDrive =       setPadDriveWPi ;
768         digitalRead =       digitalReadWPi ;
769    waitForInterrupt =  waitForInterruptWPi ;
770   delayMicroseconds = delayMicrosecondsWPi ;
771   
772 // Open the master /dev/memory device
773
774   if ((fd = open ("/dev/mem", O_RDWR | O_SYNC) ) < 0)
775   {
776     fprintf (stderr, "wiringPiSetup: Unable to open /dev/mem: %s\n", strerror (errno)) ;
777     return -1 ;
778   }
779
780 // GPIO:
781
782 // Allocate 2 pages - 1 ...
783
784   if ((gpioMem = malloc (BLOCK_SIZE + (PAGE_SIZE-1))) == NULL)
785   {
786     fprintf (stderr, "wiringPiSetup: malloc failed: %s\n", strerror (errno)) ;
787     return -1 ;
788   }
789
790 // ... presumably to make sure we can round it up to a whole page size
791
792   if (((uint32_t)gpioMem % PAGE_SIZE) != 0)
793     gpioMem += PAGE_SIZE - ((uint32_t)gpioMem % PAGE_SIZE) ;
794
795   gpio = (uint32_t *)mmap((caddr_t)gpioMem, BLOCK_SIZE, PROT_READ|PROT_WRITE, MAP_SHARED|MAP_FIXED, fd, GPIO_BASE) ;
796
797   if ((int32_t)gpio < 0)
798   {
799     fprintf (stderr, "wiringPiSetup: mmap failed: %s\n", strerror (errno)) ;
800     return -1 ;
801   }
802
803 // PWM
804
805   if ((pwmMem = malloc (BLOCK_SIZE + (PAGE_SIZE-1))) == NULL)
806   {
807     fprintf (stderr, "wiringPiSetup: pwmMem malloc failed: %s\n", strerror (errno)) ;
808     return -1 ;
809   }
810
811   if (((uint32_t)pwmMem % PAGE_SIZE) != 0)
812     pwmMem += PAGE_SIZE - ((uint32_t)pwmMem % PAGE_SIZE) ;
813
814   pwm = (uint32_t *)mmap(pwmMem, BLOCK_SIZE, PROT_READ|PROT_WRITE, MAP_SHARED|MAP_FIXED, fd, GPIO_PWM) ;
815
816   if ((int32_t)pwm < 0)
817   {
818     fprintf (stderr, "wiringPiSetup: mmap failed (pwm): %s\n", strerror (errno)) ;
819     return -1 ;
820   }
821  
822 // Clock control (needed for PWM)
823
824   if ((clkMem = malloc (BLOCK_SIZE + (PAGE_SIZE-1))) == NULL)
825   {
826     fprintf (stderr, "wiringPiSetup: clkMem malloc failed: %s\n", strerror (errno)) ;
827     return -1 ;
828   }
829
830   if (((uint32_t)clkMem % PAGE_SIZE) != 0)
831     clkMem += PAGE_SIZE - ((uint32_t)clkMem % PAGE_SIZE) ;
832
833   clk = (uint32_t *)mmap(clkMem, BLOCK_SIZE, PROT_READ|PROT_WRITE, MAP_SHARED|MAP_FIXED, fd, CLOCK_BASE) ;
834
835   if ((int32_t)clk < 0)
836   {
837     fprintf (stderr, "wiringPiSetup: mmap failed (clk): %s\n", strerror (errno)) ;
838     return -1 ;
839   }
840  
841 // The drive pads
842
843   if ((padsMem = malloc (BLOCK_SIZE + (PAGE_SIZE-1))) == NULL)
844   {
845     fprintf (stderr, "wiringPiSetup: padsMem malloc failed: %s\n", strerror (errno)) ;
846     return -1 ;
847   }
848
849   if (((uint32_t)padsMem % PAGE_SIZE) != 0)
850     padsMem += PAGE_SIZE - ((uint32_t)padsMem % PAGE_SIZE) ;
851
852   pads = (uint32_t *)mmap(padsMem, BLOCK_SIZE, PROT_READ|PROT_WRITE, MAP_SHARED|MAP_FIXED, fd, GPIO_PADS) ;
853
854   if ((int32_t)pads < 0)
855   {
856     fprintf (stderr, "wiringPiSetup: mmap failed (pads): %s\n", strerror (errno)) ;
857     return -1 ;
858   }
859
860 #ifdef  DEBUG_PADS
861   printf ("Checking pads @ 0x%08X\n", (unsigned int)pads) ;
862   printf (" -> %08X %08X %08X\n", *(pads + 11), *(pads + 12), *(pads + 13)) ;
863 #endif
864
865 // The system timer
866
867   if ((timerMem = malloc (BLOCK_SIZE + (PAGE_SIZE-1))) == NULL)
868   {
869     fprintf (stderr, "wiringPiSetup: timerMem malloc failed: %s\n", strerror (errno)) ;
870     return -1 ;
871   }
872
873   if (((uint32_t)timerMem % PAGE_SIZE) != 0)
874     timerMem += PAGE_SIZE - ((uint32_t)timerMem % PAGE_SIZE) ;
875
876   timer = (uint32_t *)mmap(timerMem, BLOCK_SIZE, PROT_READ|PROT_WRITE, MAP_SHARED|MAP_FIXED, fd, GPIO_TIMER) ;
877
878   if ((int32_t)timer < 0)
879   {
880     fprintf (stderr, "wiringPiSetup: mmap failed (timer): %s\n", strerror (errno)) ;
881     return -1 ;
882   }
883
884 // Set the timer to free-running, 1MHz.
885 //      0xF9 is 249, the timer divide is base clock / (divide+1)
886 //      so base clock is 250MHz / 250 = 1MHz.
887
888   *(timer + TIMER_CONTROL) = 0x0000280 ;
889   *(timer + TIMER_PRE_DIV) = 0x00000F9 ;
890   timerIrqRaw = timer + TIMER_IRQ_RAW ;
891
892 // Initialise our epoch for millis()
893
894   gettimeofday (&tv, NULL) ;
895   epoch = (tv.tv_sec * 1000000 + tv.tv_usec) / 1000 ;
896
897   return 0 ;
898 }
899
900
901 /*
902  * wiringPiSetupGpio:
903  *      Must be called once at the start of your program execution.
904  *
905  * GPIO setup: Initialises the system into GPIO Pin mode and uses the
906  *      memory mapped hardware directly.
907  *********************************************************************************
908  */
909
910 int wiringPiSetupGpio (void)
911 {
912   int x = wiringPiSetup () ;
913
914   if (x != 0)
915     return x ;
916
917             pinMode =           pinModeGpio ;
918     pullUpDnControl =   pullUpDnControlGpio ;
919        digitalWrite =      digitalWriteGpio ;
920            pwmWrite =          pwmWriteGpio ;
921         setPadDrive =       setPadDriveGpio ;
922         digitalRead =       digitalReadGpio ;
923    waitForInterrupt =  waitForInterruptGpio ;
924   delayMicroseconds = delayMicrosecondsWPi ;    // Same
925
926   return 0 ;
927 }
928
929
930 /*
931  * wiringPiSetupSys:
932  *      Must be called once at the start of your program execution.
933  *
934  * Initialisation (again), however this time we are using the /sys/class/gpio
935  *      interface to the GPIO systems - slightly slower, but always usable as
936  *      a non-root user, assuming the devices are already exported and setup correctly.
937  */
938
939 int wiringPiSetupSys (void)
940 {
941   int pin ;
942   struct timeval tv ;
943   char fName [128] ;
944
945             pinMode =           pinModeSys ;
946     pullUpDnControl =   pullUpDnControlSys ;
947        digitalWrite =      digitalWriteSys ;
948            pwmWrite =          pwmWriteSys ;
949         setPadDrive =       setPadDriveSys ;
950         digitalRead =       digitalReadSys ;
951    waitForInterrupt =  waitForInterruptSys ;
952   delayMicroseconds = delayMicrosecondsSys ;
953
954 // Open and scan the directory, looking for exported GPIOs, and pre-open
955 //      the 'value' interface to speed things up for later
956   
957   for (pin = 0 ; pin < 64 ; ++pin)
958   {
959     sprintf (fName, "/sys/class/gpio/gpio%d/value", pin) ;
960     sysFds [pin] = open (fName, O_RDWR) ;
961   }
962
963 // Initialise the epoch for mills() ...
964
965   gettimeofday (&tv, NULL) ;
966   epoch = (tv.tv_sec * 1000000 + tv.tv_usec) / 1000 ;
967
968   return 0 ;
969 }