wiringpi 1.0.1

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,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
+ }