wiringpi 1.0.1

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