Você não pode selecionar mais de 25 tópicos Os tópicos devem começar com uma letra ou um número, podem incluir traços ('-') e podem ter até 35 caracteres.

wiringPi.c 27 KiB

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