wiringpi2 2.0.0
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.
- data/ext/wiringpi/WiringPi/examples/blink.c +50 -0
- data/ext/wiringpi/WiringPi/examples/delayTest.c +107 -0
- data/ext/wiringpi/WiringPi/examples/ds1302.c +238 -0
- data/ext/wiringpi/WiringPi/examples/gertboard.c +94 -0
- data/ext/wiringpi/WiringPi/examples/header.h +23 -0
- data/ext/wiringpi/WiringPi/examples/isr-osc.c +118 -0
- data/ext/wiringpi/WiringPi/examples/isr.c +99 -0
- data/ext/wiringpi/WiringPi/examples/lcd.c +129 -0
- data/ext/wiringpi/WiringPi/examples/nes.c +67 -0
- data/ext/wiringpi/WiringPi/examples/okLed.c +83 -0
- data/ext/wiringpi/WiringPi/examples/piface.c +74 -0
- data/ext/wiringpi/WiringPi/examples/pwm.c +93 -0
- data/ext/wiringpi/WiringPi/examples/serialRead.c +48 -0
- data/ext/wiringpi/WiringPi/examples/serialTest.c +75 -0
- data/ext/wiringpi/WiringPi/examples/servo.c +57 -0
- data/ext/wiringpi/WiringPi/examples/speed.c +123 -0
- data/ext/wiringpi/WiringPi/examples/test1.c +111 -0
- data/ext/wiringpi/WiringPi/examples/test2.c +58 -0
- data/ext/wiringpi/WiringPi/examples/tone.c +59 -0
- data/ext/wiringpi/WiringPi/examples/wfi.c +161 -0
- data/ext/wiringpi/WiringPi/gpio/gpio.c +1371 -0
- data/ext/wiringpi/WiringPi/wiringPi/ds1302.c +239 -0
- data/ext/wiringpi/WiringPi/wiringPi/ds1302.h +44 -0
- data/ext/wiringpi/WiringPi/wiringPi/gertboard.c +166 -0
- data/ext/wiringpi/WiringPi/wiringPi/gertboard.h +40 -0
- data/ext/wiringpi/WiringPi/wiringPi/lcd.c +380 -0
- data/ext/wiringpi/WiringPi/wiringPi/lcd.h +46 -0
- data/ext/wiringpi/WiringPi/wiringPi/mcp23008.c +155 -0
- data/ext/wiringpi/WiringPi/wiringPi/mcp23008.h +33 -0
- data/ext/wiringpi/WiringPi/wiringPi/mcp23017.c +195 -0
- data/ext/wiringpi/WiringPi/wiringPi/mcp23017.h +33 -0
- data/ext/wiringpi/WiringPi/wiringPi/mcp23s08.c +195 -0
- data/ext/wiringpi/WiringPi/wiringPi/mcp23s08.h +33 -0
- data/ext/wiringpi/WiringPi/wiringPi/mcp23s17.c +236 -0
- data/ext/wiringpi/WiringPi/wiringPi/mcp23s17.h +33 -0
- data/ext/wiringpi/WiringPi/wiringPi/mcp23x08.h +73 -0
- data/ext/wiringpi/WiringPi/wiringPi/mcp23x0817.h +87 -0
- data/ext/wiringpi/WiringPi/wiringPi/piFace.c +179 -0
- data/ext/wiringpi/WiringPi/wiringPi/piFace.h +32 -0
- data/ext/wiringpi/WiringPi/wiringPi/piHiPri.c +50 -0
- data/ext/wiringpi/WiringPi/wiringPi/piNes.c +113 -0
- data/ext/wiringpi/WiringPi/wiringPi/piNes.h +45 -0
- data/ext/wiringpi/WiringPi/wiringPi/piThread.c +63 -0
- data/ext/wiringpi/WiringPi/wiringPi/softPwm.c +130 -0
- data/ext/wiringpi/WiringPi/wiringPi/softPwm.h +34 -0
- data/ext/wiringpi/WiringPi/wiringPi/softServo.c +211 -0
- data/ext/wiringpi/WiringPi/wiringPi/softServo.h +35 -0
- data/ext/wiringpi/WiringPi/wiringPi/softTone.c +121 -0
- data/ext/wiringpi/WiringPi/wiringPi/softTone.h +38 -0
- data/ext/wiringpi/WiringPi/wiringPi/sr595.c +108 -0
- data/ext/wiringpi/WiringPi/wiringPi/sr595.h +33 -0
- data/ext/wiringpi/WiringPi/wiringPi/wiringPi.c +1664 -0
- data/ext/wiringpi/WiringPi/wiringPi/wiringPi.h +168 -0
- data/ext/wiringpi/WiringPi/wiringPi/wiringPiI2C.c +227 -0
- data/ext/wiringpi/WiringPi/wiringPi/wiringPiI2C.h +42 -0
- data/ext/wiringpi/WiringPi/wiringPi/wiringPiSPI.c +119 -0
- data/ext/wiringpi/WiringPi/wiringPi/wiringPiSPI.h +35 -0
- data/ext/wiringpi/WiringPi/wiringPi/wiringSerial.c +213 -0
- data/ext/wiringpi/WiringPi/wiringPi/wiringSerial.h +38 -0
- data/ext/wiringpi/WiringPi/wiringPi/wiringShift.c +83 -0
- data/ext/wiringpi/WiringPi/wiringPi/wiringShift.h +41 -0
- data/ext/wiringpi/extconf.rb +8 -0
- data/ext/wiringpi/wiringpi_wrap.c +4378 -0
- data/lib/wiringpi/event.rb +21 -0
- data/lib/wiringpi/gpio.rb +131 -0
- data/lib/wiringpi/i2c.rb +26 -0
- data/lib/wiringpi/mcp23x17.rb +31 -0
- data/lib/wiringpi/serial.rb +49 -0
- data/lib/wiringpi/spi.rb +15 -0
- data/lib/wiringpi2.rb +42 -0
- metadata +122 -0
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* softTone.c:
|
|
3
|
+
* For that authentic retro sound...
|
|
4
|
+
* Er... A little experiment to produce tones out of a Pi using
|
|
5
|
+
* one (or 2) GPIO pins and a piezeo "speaker" element.
|
|
6
|
+
* (Or a high impedance speaker, but don'y blame me if you blow-up
|
|
7
|
+
* the GPIO pins!)
|
|
8
|
+
* Copyright (c) 2012 Gordon Henderson
|
|
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
|
+
#ifdef __cplusplus
|
|
30
|
+
extern "C" {
|
|
31
|
+
#endif
|
|
32
|
+
|
|
33
|
+
extern int softToneCreate (int pin) ;
|
|
34
|
+
extern void softToneWrite (int pin, int freq) ;
|
|
35
|
+
|
|
36
|
+
#ifdef __cplusplus
|
|
37
|
+
}
|
|
38
|
+
#endif
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* sr595.c:
|
|
3
|
+
* Extend wiringPi with the 74x595 shift register as a GPIO
|
|
4
|
+
* expander chip.
|
|
5
|
+
* Note that the code can cope with a number of 595's
|
|
6
|
+
* daisy-chained together - up to 4 for now as we're storing
|
|
7
|
+
* the output "register" in a single unsigned int.
|
|
8
|
+
*
|
|
9
|
+
* Copyright (c) 2013 Gordon Henderson
|
|
10
|
+
***********************************************************************
|
|
11
|
+
* This file is part of wiringPi:
|
|
12
|
+
* https://projects.drogon.net/raspberry-pi/wiringpi/
|
|
13
|
+
*
|
|
14
|
+
* wiringPi is free software: you can redistribute it and/or modify
|
|
15
|
+
* it under the terms of the GNU Lesser General Public License as
|
|
16
|
+
* published by the Free Software Foundation, either version 3 of the
|
|
17
|
+
* License, or (at your option) any later version.
|
|
18
|
+
*
|
|
19
|
+
* wiringPi is distributed in the hope that it will be useful,
|
|
20
|
+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
21
|
+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
22
|
+
* GNU Lesser General Public License for more details.
|
|
23
|
+
*
|
|
24
|
+
* You should have received a copy of the GNU Lesser General Public
|
|
25
|
+
* License along with wiringPi.
|
|
26
|
+
* If not, see <http://www.gnu.org/licenses/>.
|
|
27
|
+
***********************************************************************
|
|
28
|
+
*/
|
|
29
|
+
|
|
30
|
+
#include <stdio.h>
|
|
31
|
+
#include <stdint.h>
|
|
32
|
+
|
|
33
|
+
#include "wiringPi.h"
|
|
34
|
+
|
|
35
|
+
#include "sr595.h"
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
/*
|
|
39
|
+
* myDigitalWrite:
|
|
40
|
+
*********************************************************************************
|
|
41
|
+
*/
|
|
42
|
+
|
|
43
|
+
static void myDigitalWrite (struct wiringPiNodeStruct *node, int pin, int value)
|
|
44
|
+
{
|
|
45
|
+
unsigned int mask ;
|
|
46
|
+
int dataPin, clockPin, latchPin ;
|
|
47
|
+
int bit, bits, output ;
|
|
48
|
+
|
|
49
|
+
pin -= node->pinBase ; // Normalise pin number
|
|
50
|
+
bits = node->pinMax - node->pinBase + 1 ; // ie. number of clock pulses
|
|
51
|
+
dataPin = node->data0 ;
|
|
52
|
+
clockPin = node->data1 ;
|
|
53
|
+
latchPin = node->data2 ;
|
|
54
|
+
output = node->data3 ;
|
|
55
|
+
|
|
56
|
+
mask = 1 << pin ;
|
|
57
|
+
|
|
58
|
+
if (value == LOW)
|
|
59
|
+
output &= (~mask) ;
|
|
60
|
+
else
|
|
61
|
+
output |= mask ;
|
|
62
|
+
|
|
63
|
+
node->data3 = output ;
|
|
64
|
+
|
|
65
|
+
// A low -> high latch transition copies the latch to the output pins
|
|
66
|
+
|
|
67
|
+
digitalWrite (latchPin, LOW) ; delayMicroseconds (1) ;
|
|
68
|
+
for (bit = bits - 1 ; bit >= 0 ; --bit)
|
|
69
|
+
{
|
|
70
|
+
digitalWrite (dataPin, output & (1 << bit)) ;
|
|
71
|
+
|
|
72
|
+
digitalWrite (clockPin, HIGH) ; delayMicroseconds (1) ;
|
|
73
|
+
digitalWrite (clockPin, LOW) ; delayMicroseconds (1) ;
|
|
74
|
+
}
|
|
75
|
+
digitalWrite (latchPin, HIGH) ; delayMicroseconds (1) ;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
/*
|
|
80
|
+
* sr595Setup:
|
|
81
|
+
* Create a new instance of a 74x595 shift register GPIO expander.
|
|
82
|
+
*********************************************************************************
|
|
83
|
+
*/
|
|
84
|
+
|
|
85
|
+
int sr595Setup (int pinBase, int numPins, int dataPin, int clockPin, int latchPin)
|
|
86
|
+
{
|
|
87
|
+
struct wiringPiNodeStruct *node ;
|
|
88
|
+
|
|
89
|
+
node = wiringPiNewNode (pinBase, numPins) ;
|
|
90
|
+
|
|
91
|
+
node->data0 = dataPin ;
|
|
92
|
+
node->data1 = clockPin ;
|
|
93
|
+
node->data2 = latchPin ;
|
|
94
|
+
node->data3 = 0 ; // Output register
|
|
95
|
+
node->digitalWrite = myDigitalWrite ;
|
|
96
|
+
|
|
97
|
+
// Initialise the underlying hardware
|
|
98
|
+
|
|
99
|
+
digitalWrite (dataPin, LOW) ;
|
|
100
|
+
digitalWrite (clockPin, LOW) ;
|
|
101
|
+
digitalWrite (latchPin, HIGH) ;
|
|
102
|
+
|
|
103
|
+
pinMode (dataPin, OUTPUT) ;
|
|
104
|
+
pinMode (clockPin, OUTPUT) ;
|
|
105
|
+
pinMode (latchPin, OUTPUT) ;
|
|
106
|
+
|
|
107
|
+
return 0 ;
|
|
108
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* sr595.h:
|
|
3
|
+
* Extend wiringPi with the 74x595 shift registers.
|
|
4
|
+
* Copyright (c) 2013 Gordon Henderson
|
|
5
|
+
***********************************************************************
|
|
6
|
+
* This file is part of wiringPi:
|
|
7
|
+
* https://projects.drogon.net/raspberry-pi/wiringpi/
|
|
8
|
+
*
|
|
9
|
+
* wiringPi is free software: you can redistribute it and/or modify
|
|
10
|
+
* it under the terms of the GNU Lesser General Public License as
|
|
11
|
+
* published by the Free Software Foundation, either version 3 of the
|
|
12
|
+
* License, or (at your option) any later version.
|
|
13
|
+
*
|
|
14
|
+
* wiringPi is distributed in the hope that it will be useful,
|
|
15
|
+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
16
|
+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
17
|
+
* GNU Lesser General Public License for more details.
|
|
18
|
+
*
|
|
19
|
+
* You should have received a copy of the GNU Lesser General Public
|
|
20
|
+
* License along with wiringPi.
|
|
21
|
+
* If not, see <http://www.gnu.org/licenses/>.
|
|
22
|
+
***********************************************************************
|
|
23
|
+
*/
|
|
24
|
+
|
|
25
|
+
#ifdef __cplusplus
|
|
26
|
+
extern "C" {
|
|
27
|
+
#endif
|
|
28
|
+
|
|
29
|
+
extern int sr595Setup (int pinBase, int numPins, int dataPin, int clockPin, int latchPin) ;
|
|
30
|
+
|
|
31
|
+
#ifdef __cplusplus
|
|
32
|
+
}
|
|
33
|
+
#endif
|
|
@@ -0,0 +1,1664 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* wiringPi:
|
|
3
|
+
* Arduino compatable (ish) Wiring library for the Raspberry Pi
|
|
4
|
+
* Copyright (c) 2012 Gordon Henderson
|
|
5
|
+
* Additional code for pwmSetClock by Chris Hall <chris@kchall.plus.com>
|
|
6
|
+
*
|
|
7
|
+
* Thanks to code samples from Gert Jan van Loo and the
|
|
8
|
+
* BCM2835 ARM Peripherals manual, however it's missing
|
|
9
|
+
* the clock section /grr/mutter/
|
|
10
|
+
***********************************************************************
|
|
11
|
+
* This file is part of wiringPi:
|
|
12
|
+
* https://projects.drogon.net/raspberry-pi/wiringpi/
|
|
13
|
+
*
|
|
14
|
+
* wiringPi is free software: you can redistribute it and/or modify
|
|
15
|
+
* it under the terms of the GNU Lesser General Public License as
|
|
16
|
+
* published by the Free Software Foundation, either version 3 of the
|
|
17
|
+
* License, or (at your option) any later version.
|
|
18
|
+
*
|
|
19
|
+
* wiringPi is distributed in the hope that it will be useful,
|
|
20
|
+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
21
|
+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
22
|
+
* GNU Lesser General Public License for more details.
|
|
23
|
+
*
|
|
24
|
+
* You should have received a copy of the GNU Lesser General Public
|
|
25
|
+
* License along with wiringPi.
|
|
26
|
+
* If not, see <http://www.gnu.org/licenses/>.
|
|
27
|
+
***********************************************************************
|
|
28
|
+
*/
|
|
29
|
+
|
|
30
|
+
// Revisions:
|
|
31
|
+
// 19 Jul 2012:
|
|
32
|
+
// Moved to the LGPL
|
|
33
|
+
// Added an abstraction layer to the main routines to save a tiny
|
|
34
|
+
// bit of run-time and make the clode a little cleaner (if a little
|
|
35
|
+
// larger)
|
|
36
|
+
// Added waitForInterrupt code
|
|
37
|
+
// Added piHiPri code
|
|
38
|
+
//
|
|
39
|
+
// 9 Jul 2012:
|
|
40
|
+
// Added in support to use the /sys/class/gpio interface.
|
|
41
|
+
// 2 Jul 2012:
|
|
42
|
+
// Fixed a few more bugs to do with range-checking when in GPIO mode.
|
|
43
|
+
// 11 Jun 2012:
|
|
44
|
+
// Fixed some typos.
|
|
45
|
+
// Added c++ support for the .h file
|
|
46
|
+
// Added a new function to allow for using my "pin" numbers, or native
|
|
47
|
+
// GPIO pin numbers.
|
|
48
|
+
// Removed my busy-loop delay and replaced it with a call to delayMicroseconds
|
|
49
|
+
//
|
|
50
|
+
// 02 May 2012:
|
|
51
|
+
// Added in the 2 UART pins
|
|
52
|
+
// Change maxPins to numPins to more accurately reflect purpose
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
#include <stdio.h>
|
|
56
|
+
#include <stdarg.h>
|
|
57
|
+
#include <stdint.h>
|
|
58
|
+
#include <stdlib.h>
|
|
59
|
+
#include <ctype.h>
|
|
60
|
+
#include <poll.h>
|
|
61
|
+
#include <unistd.h>
|
|
62
|
+
#include <errno.h>
|
|
63
|
+
#include <string.h>
|
|
64
|
+
#include <time.h>
|
|
65
|
+
#include <fcntl.h>
|
|
66
|
+
#include <pthread.h>
|
|
67
|
+
#include <sys/time.h>
|
|
68
|
+
#include <sys/mman.h>
|
|
69
|
+
#include <sys/stat.h>
|
|
70
|
+
#include <sys/wait.h>
|
|
71
|
+
#include <sys/ioctl.h>
|
|
72
|
+
|
|
73
|
+
#include "wiringPi.h"
|
|
74
|
+
|
|
75
|
+
#ifndef TRUE
|
|
76
|
+
#define TRUE (1==1)
|
|
77
|
+
#define FALSE (1==2)
|
|
78
|
+
#endif
|
|
79
|
+
|
|
80
|
+
// Environment Variables
|
|
81
|
+
|
|
82
|
+
#define ENV_DEBUG "WIRINGPI_DEBUG"
|
|
83
|
+
#define ENV_CODES "WIRINGPI_CODES"
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
// Mask for the bottom 64 pins which belong to the Raspberry Pi
|
|
87
|
+
// The others are available for the other devices
|
|
88
|
+
|
|
89
|
+
#define PI_GPIO_MASK (0xFFFFFFC0)
|
|
90
|
+
|
|
91
|
+
static struct wiringPiNodeStruct *wiringPiNodes = NULL ;
|
|
92
|
+
|
|
93
|
+
// BCM Magic
|
|
94
|
+
|
|
95
|
+
#define BCM_PASSWORD 0x5A000000
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
// The BCM2835 has 54 GPIO pins.
|
|
99
|
+
// BCM2835 data sheet, Page 90 onwards.
|
|
100
|
+
// There are 6 control registers, each control the functions of a block
|
|
101
|
+
// of 10 pins.
|
|
102
|
+
// Each control register has 10 sets of 3 bits per GPIO pin - the ALT values
|
|
103
|
+
//
|
|
104
|
+
// 000 = GPIO Pin X is an input
|
|
105
|
+
// 001 = GPIO Pin X is an output
|
|
106
|
+
// 100 = GPIO Pin X takes alternate function 0
|
|
107
|
+
// 101 = GPIO Pin X takes alternate function 1
|
|
108
|
+
// 110 = GPIO Pin X takes alternate function 2
|
|
109
|
+
// 111 = GPIO Pin X takes alternate function 3
|
|
110
|
+
// 011 = GPIO Pin X takes alternate function 4
|
|
111
|
+
// 010 = GPIO Pin X takes alternate function 5
|
|
112
|
+
//
|
|
113
|
+
// So the 3 bits for port X are:
|
|
114
|
+
// X / 10 + ((X % 10) * 3)
|
|
115
|
+
|
|
116
|
+
// Port function select bits
|
|
117
|
+
|
|
118
|
+
#define FSEL_INPT 0b000
|
|
119
|
+
#define FSEL_OUTP 0b001
|
|
120
|
+
#define FSEL_ALT0 0b100
|
|
121
|
+
#define FSEL_ALT0 0b100
|
|
122
|
+
#define FSEL_ALT1 0b101
|
|
123
|
+
#define FSEL_ALT2 0b110
|
|
124
|
+
#define FSEL_ALT3 0b111
|
|
125
|
+
#define FSEL_ALT4 0b011
|
|
126
|
+
#define FSEL_ALT5 0b010
|
|
127
|
+
|
|
128
|
+
// Access from ARM Running Linux
|
|
129
|
+
// Taken from Gert/Doms code. Some of this is not in the manual
|
|
130
|
+
// that I can find )-:
|
|
131
|
+
|
|
132
|
+
#define BCM2708_PERI_BASE 0x20000000
|
|
133
|
+
#define GPIO_PADS (BCM2708_PERI_BASE + 0x00100000)
|
|
134
|
+
#define CLOCK_BASE (BCM2708_PERI_BASE + 0x00101000)
|
|
135
|
+
#define GPIO_BASE (BCM2708_PERI_BASE + 0x00200000)
|
|
136
|
+
#define GPIO_TIMER (BCM2708_PERI_BASE + 0x0000B000)
|
|
137
|
+
#define GPIO_PWM (BCM2708_PERI_BASE + 0x0020C000)
|
|
138
|
+
|
|
139
|
+
#define PAGE_SIZE (4*1024)
|
|
140
|
+
#define BLOCK_SIZE (4*1024)
|
|
141
|
+
|
|
142
|
+
// PWM
|
|
143
|
+
// Word offsets into the PWM control region
|
|
144
|
+
|
|
145
|
+
#define PWM_CONTROL 0
|
|
146
|
+
#define PWM_STATUS 1
|
|
147
|
+
#define PWM0_RANGE 4
|
|
148
|
+
#define PWM0_DATA 5
|
|
149
|
+
#define PWM1_RANGE 8
|
|
150
|
+
#define PWM1_DATA 9
|
|
151
|
+
|
|
152
|
+
// Clock regsiter offsets
|
|
153
|
+
|
|
154
|
+
#define PWMCLK_CNTL 40
|
|
155
|
+
#define PWMCLK_DIV 41
|
|
156
|
+
|
|
157
|
+
#define PWM0_MS_MODE 0x0080 // Run in MS mode
|
|
158
|
+
#define PWM0_USEFIFO 0x0020 // Data from FIFO
|
|
159
|
+
#define PWM0_REVPOLAR 0x0010 // Reverse polarity
|
|
160
|
+
#define PWM0_OFFSTATE 0x0008 // Ouput Off state
|
|
161
|
+
#define PWM0_REPEATFF 0x0004 // Repeat last value if FIFO empty
|
|
162
|
+
#define PWM0_SERIAL 0x0002 // Run in serial mode
|
|
163
|
+
#define PWM0_ENABLE 0x0001 // Channel Enable
|
|
164
|
+
|
|
165
|
+
#define PWM1_MS_MODE 0x8000 // Run in MS mode
|
|
166
|
+
#define PWM1_USEFIFO 0x2000 // Data from FIFO
|
|
167
|
+
#define PWM1_REVPOLAR 0x1000 // Reverse polarity
|
|
168
|
+
#define PWM1_OFFSTATE 0x0800 // Ouput Off state
|
|
169
|
+
#define PWM1_REPEATFF 0x0400 // Repeat last value if FIFO empty
|
|
170
|
+
#define PWM1_SERIAL 0x0200 // Run in serial mode
|
|
171
|
+
#define PWM1_ENABLE 0x0100 // Channel Enable
|
|
172
|
+
|
|
173
|
+
// Timer
|
|
174
|
+
// Word offsets
|
|
175
|
+
|
|
176
|
+
#define TIMER_LOAD (0x400 >> 2)
|
|
177
|
+
#define TIMER_VALUE (0x404 >> 2)
|
|
178
|
+
#define TIMER_CONTROL (0x408 >> 2)
|
|
179
|
+
#define TIMER_IRQ_CLR (0x40C >> 2)
|
|
180
|
+
#define TIMER_IRQ_RAW (0x410 >> 2)
|
|
181
|
+
#define TIMER_IRQ_MASK (0x414 >> 2)
|
|
182
|
+
#define TIMER_RELOAD (0x418 >> 2)
|
|
183
|
+
#define TIMER_PRE_DIV (0x41C >> 2)
|
|
184
|
+
#define TIMER_COUNTER (0x420 >> 2)
|
|
185
|
+
|
|
186
|
+
// Locals to hold pointers to the hardware
|
|
187
|
+
|
|
188
|
+
static volatile uint32_t *gpio ;
|
|
189
|
+
static volatile uint32_t *pwm ;
|
|
190
|
+
static volatile uint32_t *clk ;
|
|
191
|
+
static volatile uint32_t *pads ;
|
|
192
|
+
|
|
193
|
+
#ifdef USE_TIMER
|
|
194
|
+
static volatile uint32_t *timer ;
|
|
195
|
+
static volatile uint32_t *timerIrqRaw ;
|
|
196
|
+
#endif
|
|
197
|
+
|
|
198
|
+
// Time for easy calculations
|
|
199
|
+
|
|
200
|
+
static uint64_t epochMilli, epochMicro ;
|
|
201
|
+
|
|
202
|
+
// Misc
|
|
203
|
+
|
|
204
|
+
static int wiringPiMode = WPI_MODE_UNINITIALISED ;
|
|
205
|
+
|
|
206
|
+
// Debugging & Return codes
|
|
207
|
+
|
|
208
|
+
int wiringPiDebug = FALSE ;
|
|
209
|
+
int wiringPiCodes = FALSE ;
|
|
210
|
+
|
|
211
|
+
// sysFds:
|
|
212
|
+
// Map a file descriptor from the /sys/class/gpio/gpioX/value
|
|
213
|
+
|
|
214
|
+
static int sysFds [64] ;
|
|
215
|
+
|
|
216
|
+
// ISR Data
|
|
217
|
+
|
|
218
|
+
static void (*isrFunctions [64])(void) ;
|
|
219
|
+
|
|
220
|
+
|
|
221
|
+
// Doing it the Arduino way with lookup tables...
|
|
222
|
+
// Yes, it's probably more innefficient than all the bit-twidling, but it
|
|
223
|
+
// does tend to make it all a bit clearer. At least to me!
|
|
224
|
+
|
|
225
|
+
// pinToGpio:
|
|
226
|
+
// Take a Wiring pin (0 through X) and re-map it to the BCM_GPIO pin
|
|
227
|
+
// Cope for 2 different board revisions here.
|
|
228
|
+
|
|
229
|
+
static int *pinToGpio ;
|
|
230
|
+
|
|
231
|
+
static int pinToGpioR1 [64] =
|
|
232
|
+
{
|
|
233
|
+
17, 18, 21, 22, 23, 24, 25, 4, // From the Original Wiki - GPIO 0 through 7: wpi 0 - 7
|
|
234
|
+
0, 1, // I2C - SDA0, SCL0 wpi 8 - 9
|
|
235
|
+
8, 7, // SPI - CE1, CE0 wpi 10 - 11
|
|
236
|
+
10, 9, 11, // SPI - MOSI, MISO, SCLK wpi 12 - 14
|
|
237
|
+
14, 15, // UART - Tx, Rx wpi 15 - 16
|
|
238
|
+
|
|
239
|
+
// Padding:
|
|
240
|
+
|
|
241
|
+
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // ... 31
|
|
242
|
+
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // ... 47
|
|
243
|
+
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // ... 63
|
|
244
|
+
} ;
|
|
245
|
+
|
|
246
|
+
static int pinToGpioR2 [64] =
|
|
247
|
+
{
|
|
248
|
+
17, 18, 27, 22, 23, 24, 25, 4, // From the Original Wiki - GPIO 0 through 7: wpi 0 - 7
|
|
249
|
+
2, 3, // I2C - SDA0, SCL0 wpi 8 - 9
|
|
250
|
+
8, 7, // SPI - CE1, CE0 wpi 10 - 11
|
|
251
|
+
10, 9, 11, // SPI - MOSI, MISO, SCLK wpi 12 - 14
|
|
252
|
+
14, 15, // UART - Tx, Rx wpi 15 - 16
|
|
253
|
+
28, 29, 30, 31, // New GPIOs 8 though 11 wpi 17 - 20
|
|
254
|
+
|
|
255
|
+
// Padding:
|
|
256
|
+
|
|
257
|
+
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // ... 31
|
|
258
|
+
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // ... 47
|
|
259
|
+
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // ... 63
|
|
260
|
+
} ;
|
|
261
|
+
|
|
262
|
+
|
|
263
|
+
// physToGpio:
|
|
264
|
+
// Take a physical pin (1 through 26) and re-map it to the BCM_GPIO pin
|
|
265
|
+
// Cope for 2 different board revisions here.
|
|
266
|
+
|
|
267
|
+
static int *physToGpio ;
|
|
268
|
+
|
|
269
|
+
static int physToGpioR1 [64] =
|
|
270
|
+
{
|
|
271
|
+
-1, // 0
|
|
272
|
+
-1, -1, // 1, 2
|
|
273
|
+
0, -1,
|
|
274
|
+
1, -1,
|
|
275
|
+
4, 14,
|
|
276
|
+
-1, 15,
|
|
277
|
+
17, 18,
|
|
278
|
+
21, -1,
|
|
279
|
+
22, 23,
|
|
280
|
+
-1, 24,
|
|
281
|
+
10, -1,
|
|
282
|
+
9, 25,
|
|
283
|
+
11, 8,
|
|
284
|
+
-1, 7, // 25, 26
|
|
285
|
+
|
|
286
|
+
// Padding:
|
|
287
|
+
|
|
288
|
+
-1, -1, -1, -1, -1, // ... 31
|
|
289
|
+
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // ... 47
|
|
290
|
+
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // ... 63
|
|
291
|
+
} ;
|
|
292
|
+
|
|
293
|
+
static int physToGpioR2 [64] =
|
|
294
|
+
{
|
|
295
|
+
-1, // 0
|
|
296
|
+
-1, -1, // 1, 2
|
|
297
|
+
2, -1,
|
|
298
|
+
3, -1,
|
|
299
|
+
4, 14,
|
|
300
|
+
-1, 15,
|
|
301
|
+
17, 18,
|
|
302
|
+
27, -1,
|
|
303
|
+
22, 23,
|
|
304
|
+
-1, 24,
|
|
305
|
+
10, -1,
|
|
306
|
+
9, 25,
|
|
307
|
+
11, 8,
|
|
308
|
+
-1, 7, // 25, 26
|
|
309
|
+
|
|
310
|
+
// Padding:
|
|
311
|
+
|
|
312
|
+
-1, -1, -1, -1, -1, // ... 31
|
|
313
|
+
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // ... 47
|
|
314
|
+
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // ... 63
|
|
315
|
+
} ;
|
|
316
|
+
|
|
317
|
+
|
|
318
|
+
// gpioToGPFSEL:
|
|
319
|
+
// Map a BCM_GPIO pin to it's Function Selection
|
|
320
|
+
// control port. (GPFSEL 0-5)
|
|
321
|
+
// Groups of 10 - 3 bits per Function - 30 bits per port
|
|
322
|
+
|
|
323
|
+
static uint8_t gpioToGPFSEL [] =
|
|
324
|
+
{
|
|
325
|
+
0,0,0,0,0,0,0,0,0,0,
|
|
326
|
+
1,1,1,1,1,1,1,1,1,1,
|
|
327
|
+
2,2,2,2,2,2,2,2,2,2,
|
|
328
|
+
3,3,3,3,3,3,3,3,3,3,
|
|
329
|
+
4,4,4,4,4,4,4,4,4,4,
|
|
330
|
+
5,5,5,5,5,5,5,5,5,5,
|
|
331
|
+
} ;
|
|
332
|
+
|
|
333
|
+
|
|
334
|
+
// gpioToShift
|
|
335
|
+
// Define the shift up for the 3 bits per pin in each GPFSEL port
|
|
336
|
+
|
|
337
|
+
static uint8_t gpioToShift [] =
|
|
338
|
+
{
|
|
339
|
+
0,3,6,9,12,15,18,21,24,27,
|
|
340
|
+
0,3,6,9,12,15,18,21,24,27,
|
|
341
|
+
0,3,6,9,12,15,18,21,24,27,
|
|
342
|
+
0,3,6,9,12,15,18,21,24,27,
|
|
343
|
+
0,3,6,9,12,15,18,21,24,27,
|
|
344
|
+
} ;
|
|
345
|
+
|
|
346
|
+
|
|
347
|
+
// gpioToGPSET:
|
|
348
|
+
// (Word) offset to the GPIO Set registers for each GPIO pin
|
|
349
|
+
|
|
350
|
+
static uint8_t gpioToGPSET [] =
|
|
351
|
+
{
|
|
352
|
+
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,
|
|
353
|
+
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,
|
|
354
|
+
} ;
|
|
355
|
+
|
|
356
|
+
// gpioToGPCLR:
|
|
357
|
+
// (Word) offset to the GPIO Clear registers for each GPIO pin
|
|
358
|
+
|
|
359
|
+
static uint8_t gpioToGPCLR [] =
|
|
360
|
+
{
|
|
361
|
+
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,
|
|
362
|
+
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,
|
|
363
|
+
} ;
|
|
364
|
+
|
|
365
|
+
|
|
366
|
+
// gpioToGPLEV:
|
|
367
|
+
// (Word) offset to the GPIO Input level registers for each GPIO pin
|
|
368
|
+
|
|
369
|
+
static uint8_t gpioToGPLEV [] =
|
|
370
|
+
{
|
|
371
|
+
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,
|
|
372
|
+
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,
|
|
373
|
+
} ;
|
|
374
|
+
|
|
375
|
+
|
|
376
|
+
#ifdef notYetReady
|
|
377
|
+
// gpioToEDS
|
|
378
|
+
// (Word) offset to the Event Detect Status
|
|
379
|
+
|
|
380
|
+
static uint8_t gpioToEDS [] =
|
|
381
|
+
{
|
|
382
|
+
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,
|
|
383
|
+
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,
|
|
384
|
+
} ;
|
|
385
|
+
|
|
386
|
+
// gpioToREN
|
|
387
|
+
// (Word) offset to the Rising edgde ENable register
|
|
388
|
+
|
|
389
|
+
static uint8_t gpioToREN [] =
|
|
390
|
+
{
|
|
391
|
+
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,
|
|
392
|
+
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,
|
|
393
|
+
} ;
|
|
394
|
+
|
|
395
|
+
// gpioToFEN
|
|
396
|
+
// (Word) offset to the Falling edgde ENable register
|
|
397
|
+
|
|
398
|
+
static uint8_t gpioToFEN [] =
|
|
399
|
+
{
|
|
400
|
+
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,
|
|
401
|
+
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,
|
|
402
|
+
} ;
|
|
403
|
+
#endif
|
|
404
|
+
|
|
405
|
+
|
|
406
|
+
// GPPUD:
|
|
407
|
+
// GPIO Pin pull up/down register
|
|
408
|
+
|
|
409
|
+
#define GPPUD 37
|
|
410
|
+
|
|
411
|
+
// gpioToPUDCLK
|
|
412
|
+
// (Word) offset to the Pull Up Down Clock regsiter
|
|
413
|
+
|
|
414
|
+
static uint8_t gpioToPUDCLK [] =
|
|
415
|
+
{
|
|
416
|
+
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,
|
|
417
|
+
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,
|
|
418
|
+
} ;
|
|
419
|
+
|
|
420
|
+
|
|
421
|
+
// gpioToPwmALT
|
|
422
|
+
// the ALT value to put a GPIO pin into PWM mode
|
|
423
|
+
|
|
424
|
+
static uint8_t gpioToPwmALT [] =
|
|
425
|
+
{
|
|
426
|
+
0, 0, 0, 0, 0, 0, 0, 0, // 0 -> 7
|
|
427
|
+
0, 0, 0, 0, FSEL_ALT0, FSEL_ALT0, 0, 0, // 8 -> 15
|
|
428
|
+
0, 0, FSEL_ALT5, FSEL_ALT5, 0, 0, 0, 0, // 16 -> 23
|
|
429
|
+
0, 0, 0, 0, 0, 0, 0, 0, // 24 -> 31
|
|
430
|
+
0, 0, 0, 0, 0, 0, 0, 0, // 32 -> 39
|
|
431
|
+
FSEL_ALT0, FSEL_ALT0, 0, 0, 0, FSEL_ALT0, 0, 0, // 40 -> 47
|
|
432
|
+
0, 0, 0, 0, 0, 0, 0, 0, // 48 -> 55
|
|
433
|
+
0, 0, 0, 0, 0, 0, 0, 0, // 56 -> 63
|
|
434
|
+
} ;
|
|
435
|
+
|
|
436
|
+
|
|
437
|
+
// gpioToPwmPort
|
|
438
|
+
// The port value to put a GPIO pin into PWM mode
|
|
439
|
+
|
|
440
|
+
static uint8_t gpioToPwmPort [] =
|
|
441
|
+
{
|
|
442
|
+
0, 0, 0, 0, 0, 0, 0, 0, // 0 -> 7
|
|
443
|
+
0, 0, 0, 0, PWM0_DATA, PWM1_DATA, 0, 0, // 8 -> 15
|
|
444
|
+
0, 0, PWM0_DATA, PWM1_DATA, 0, 0, 0, 0, // 16 -> 23
|
|
445
|
+
0, 0, 0, 0, 0, 0, 0, 0, // 24 -> 31
|
|
446
|
+
0, 0, 0, 0, 0, 0, 0, 0, // 32 -> 39
|
|
447
|
+
PWM0_DATA, PWM1_DATA, 0, 0, 0, PWM1_DATA, 0, 0, // 40 -> 47
|
|
448
|
+
0, 0, 0, 0, 0, 0, 0, 0, // 48 -> 55
|
|
449
|
+
0, 0, 0, 0, 0, 0, 0, 0, // 56 -> 63
|
|
450
|
+
|
|
451
|
+
} ;
|
|
452
|
+
|
|
453
|
+
// gpioToGpClkALT:
|
|
454
|
+
// ALT value to put a GPIO pin into GP Clock mode.
|
|
455
|
+
// On the Pi we can really only use BCM_GPIO_4 and BCM_GPIO_21
|
|
456
|
+
// for clocks 0 and 1 respectively, however I'll include the full
|
|
457
|
+
// list for completeness - maybe one day...
|
|
458
|
+
|
|
459
|
+
#define GPIO_CLOCK_SOURCE 1
|
|
460
|
+
|
|
461
|
+
// gpioToGpClkALT0:
|
|
462
|
+
|
|
463
|
+
static uint8_t gpioToGpClkALT0 [] =
|
|
464
|
+
{
|
|
465
|
+
0, 0, 0, 0, FSEL_ALT0, FSEL_ALT0, FSEL_ALT0, 0, // 0 -> 7
|
|
466
|
+
0, 0, 0, 0, 0, 0, 0, 0, // 8 -> 15
|
|
467
|
+
0, 0, 0, 0, FSEL_ALT5, FSEL_ALT5, 0, 0, // 16 -> 23
|
|
468
|
+
0, 0, 0, 0, 0, 0, 0, 0, // 24 -> 31
|
|
469
|
+
FSEL_ALT0, 0, FSEL_ALT0, 0, 0, 0, 0, 0, // 32 -> 39
|
|
470
|
+
0, 0, FSEL_ALT0, FSEL_ALT0, FSEL_ALT0, 0, 0, 0, // 40 -> 47
|
|
471
|
+
0, 0, 0, 0, 0, 0, 0, 0, // 48 -> 55
|
|
472
|
+
0, 0, 0, 0, 0, 0, 0, 0, // 56 -> 63
|
|
473
|
+
} ;
|
|
474
|
+
|
|
475
|
+
// gpioToClk:
|
|
476
|
+
// (word) Offsets to the clock Control and Divisor register
|
|
477
|
+
|
|
478
|
+
static uint8_t gpioToClkCon [] =
|
|
479
|
+
{
|
|
480
|
+
-1, -1, -1, -1, 28, 30, 32, -1, // 0 -> 7
|
|
481
|
+
-1, -1, -1, -1, -1, -1, -1, -1, // 8 -> 15
|
|
482
|
+
-1, -1, -1, -1, 28, 30, -1, -1, // 16 -> 23
|
|
483
|
+
-1, -1, -1, -1, -1, -1, -1, -1, // 24 -> 31
|
|
484
|
+
28, -1, 28, -1, -1, -1, -1, -1, // 32 -> 39
|
|
485
|
+
-1, -1, 28, 30, 28, -1, -1, -1, // 40 -> 47
|
|
486
|
+
-1, -1, -1, -1, -1, -1, -1, -1, // 48 -> 55
|
|
487
|
+
-1, -1, -1, -1, -1, -1, -1, -1, // 56 -> 63
|
|
488
|
+
} ;
|
|
489
|
+
|
|
490
|
+
static uint8_t gpioToClkDiv [] =
|
|
491
|
+
{
|
|
492
|
+
-1, -1, -1, -1, 29, 31, 33, -1, // 0 -> 7
|
|
493
|
+
-1, -1, -1, -1, -1, -1, -1, -1, // 8 -> 15
|
|
494
|
+
-1, -1, -1, -1, 29, 31, -1, -1, // 16 -> 23
|
|
495
|
+
-1, -1, -1, -1, -1, -1, -1, -1, // 24 -> 31
|
|
496
|
+
29, -1, 29, -1, -1, -1, -1, -1, // 32 -> 39
|
|
497
|
+
-1, -1, 29, 31, 29, -1, -1, -1, // 40 -> 47
|
|
498
|
+
-1, -1, -1, -1, -1, -1, -1, -1, // 48 -> 55
|
|
499
|
+
-1, -1, -1, -1, -1, -1, -1, -1, // 56 -> 63
|
|
500
|
+
} ;
|
|
501
|
+
|
|
502
|
+
|
|
503
|
+
/*
|
|
504
|
+
* Functions
|
|
505
|
+
*********************************************************************************
|
|
506
|
+
*/
|
|
507
|
+
|
|
508
|
+
|
|
509
|
+
/*
|
|
510
|
+
* wiringPiFailure:
|
|
511
|
+
* Fail. Or not.
|
|
512
|
+
*********************************************************************************
|
|
513
|
+
*/
|
|
514
|
+
|
|
515
|
+
int wiringPiFailure (char *message, ...)
|
|
516
|
+
{
|
|
517
|
+
va_list argp ;
|
|
518
|
+
char buffer [1024] ;
|
|
519
|
+
|
|
520
|
+
va_start (argp, message) ;
|
|
521
|
+
vsnprintf (buffer, 1023, message, argp) ;
|
|
522
|
+
va_end (argp) ;
|
|
523
|
+
|
|
524
|
+
fprintf(stderr,"%s",buffer) ;
|
|
525
|
+
exit (EXIT_FAILURE) ;
|
|
526
|
+
|
|
527
|
+
return 0 ;
|
|
528
|
+
}
|
|
529
|
+
|
|
530
|
+
|
|
531
|
+
/*
|
|
532
|
+
* piBoardRev:
|
|
533
|
+
* Return a number representing the hardware revision of the board.
|
|
534
|
+
* Revision is currently 1 or 2. -1 is returned on error.
|
|
535
|
+
*
|
|
536
|
+
* Much confusion here )-:
|
|
537
|
+
* Seems there are some boards with 0000 in them (mistake in manufacture)
|
|
538
|
+
* and some board with 0005 in them (another mistake in manufacture?)
|
|
539
|
+
* So the distinction between boards that I can see is:
|
|
540
|
+
* 0000 - Error
|
|
541
|
+
* 0001 - Not used
|
|
542
|
+
* 0002 - Rev 1
|
|
543
|
+
* 0003 - Rev 1
|
|
544
|
+
* 0004 - Rev 2 (Early reports?
|
|
545
|
+
* 0005 - Rev 2 (but error?)
|
|
546
|
+
* 0006 - Rev 2
|
|
547
|
+
* 0008 - Rev 2 - Model A
|
|
548
|
+
* 000e - Rev 2 + 512MB
|
|
549
|
+
* 000f - Rev 2 + 512MB
|
|
550
|
+
*
|
|
551
|
+
* A small thorn is the olde style overvolting - that will add in
|
|
552
|
+
* 1000000
|
|
553
|
+
*
|
|
554
|
+
*********************************************************************************
|
|
555
|
+
*/
|
|
556
|
+
|
|
557
|
+
static void piBoardRevOops (char *why)
|
|
558
|
+
{
|
|
559
|
+
fprintf (stderr, "piBoardRev: Unable to determine board revision from /proc/cpuinfo\n") ;
|
|
560
|
+
fprintf (stderr, " -> %s\n", why) ;
|
|
561
|
+
fprintf (stderr, " -> You may want to check:\n") ;
|
|
562
|
+
fprintf (stderr, " -> http://www.raspberrypi.org/phpBB3/viewtopic.php?p=184410#p184410\n") ;
|
|
563
|
+
exit (EXIT_FAILURE) ;
|
|
564
|
+
}
|
|
565
|
+
|
|
566
|
+
int piBoardRev (void)
|
|
567
|
+
{
|
|
568
|
+
FILE *cpuFd ;
|
|
569
|
+
char line [120] ;
|
|
570
|
+
char *c, lastChar ;
|
|
571
|
+
static int boardRev = -1 ;
|
|
572
|
+
|
|
573
|
+
if (boardRev != -1) // No point checking twice
|
|
574
|
+
return boardRev ;
|
|
575
|
+
|
|
576
|
+
if ((cpuFd = fopen ("/proc/cpuinfo", "r")) == NULL)
|
|
577
|
+
piBoardRevOops ("Unable to open /proc/cpuinfo") ;
|
|
578
|
+
|
|
579
|
+
while (fgets (line, 120, cpuFd) != NULL)
|
|
580
|
+
if (strncmp (line, "Revision", 8) == 0)
|
|
581
|
+
break ;
|
|
582
|
+
|
|
583
|
+
fclose (cpuFd) ;
|
|
584
|
+
|
|
585
|
+
if (strncmp (line, "Revision", 8) != 0)
|
|
586
|
+
piBoardRevOops ("No \"Revision\" line") ;
|
|
587
|
+
|
|
588
|
+
for (c = &line [strlen (line) - 1] ; (*c == '\n') || (*c == '\r') ; --c)
|
|
589
|
+
*c = 0 ;
|
|
590
|
+
|
|
591
|
+
if (wiringPiDebug)
|
|
592
|
+
printf ("piboardRev: Revision string: %s\n", line) ;
|
|
593
|
+
|
|
594
|
+
for (c = line ; *c ; ++c)
|
|
595
|
+
if (isdigit (*c))
|
|
596
|
+
break ;
|
|
597
|
+
|
|
598
|
+
if (!isdigit (*c))
|
|
599
|
+
piBoardRevOops ("No numeric revision string") ;
|
|
600
|
+
|
|
601
|
+
// If you have overvolted the Pi, then it appears that the revision
|
|
602
|
+
// has 100000 added to it!
|
|
603
|
+
|
|
604
|
+
if (wiringPiDebug)
|
|
605
|
+
if (strlen (c) != 4)
|
|
606
|
+
printf ("piboardRev: This Pi has/is overvolted!\n") ;
|
|
607
|
+
|
|
608
|
+
lastChar = line [strlen (line) - 1] ;
|
|
609
|
+
|
|
610
|
+
if (wiringPiDebug)
|
|
611
|
+
printf ("piboardRev: lastChar is: '%c' (%d, 0x%02X)\n", lastChar, lastChar, lastChar) ;
|
|
612
|
+
|
|
613
|
+
/**/ if ((lastChar == '2') || (lastChar == '3'))
|
|
614
|
+
boardRev = 1 ;
|
|
615
|
+
else
|
|
616
|
+
boardRev = 2 ;
|
|
617
|
+
|
|
618
|
+
if (wiringPiDebug)
|
|
619
|
+
printf ("piBoardRev: Returning revision: %d\n", boardRev) ;
|
|
620
|
+
|
|
621
|
+
return boardRev ;
|
|
622
|
+
}
|
|
623
|
+
|
|
624
|
+
|
|
625
|
+
/*
|
|
626
|
+
* wpiPinToGpio:
|
|
627
|
+
* Translate a wiringPi Pin number to native GPIO pin number.
|
|
628
|
+
* Provided for external support.
|
|
629
|
+
*********************************************************************************
|
|
630
|
+
*/
|
|
631
|
+
|
|
632
|
+
int wpiPinToGpio (int wpiPin)
|
|
633
|
+
{
|
|
634
|
+
return pinToGpio [wpiPin & 63] ;
|
|
635
|
+
}
|
|
636
|
+
|
|
637
|
+
|
|
638
|
+
/*
|
|
639
|
+
* physPinToGpio:
|
|
640
|
+
* Translate a physical Pin number to native GPIO pin number.
|
|
641
|
+
* Provided for external support.
|
|
642
|
+
*********************************************************************************
|
|
643
|
+
*/
|
|
644
|
+
|
|
645
|
+
int physPinToGpio (int physPin)
|
|
646
|
+
{
|
|
647
|
+
return physToGpio [physPin & 63] ;
|
|
648
|
+
}
|
|
649
|
+
|
|
650
|
+
|
|
651
|
+
/*
|
|
652
|
+
* setPadDrive:
|
|
653
|
+
* Set the PAD driver value
|
|
654
|
+
*********************************************************************************
|
|
655
|
+
*/
|
|
656
|
+
|
|
657
|
+
void setPadDrive (int group, int value)
|
|
658
|
+
{
|
|
659
|
+
uint32_t wrVal ;
|
|
660
|
+
|
|
661
|
+
if ((wiringPiMode == WPI_MODE_PINS) || (wiringPiMode == WPI_MODE_GPIO))
|
|
662
|
+
{
|
|
663
|
+
if ((group < 0) || (group > 2))
|
|
664
|
+
return ;
|
|
665
|
+
|
|
666
|
+
wrVal = BCM_PASSWORD | 0x18 | (value & 7) ;
|
|
667
|
+
*(pads + group + 11) = wrVal ;
|
|
668
|
+
|
|
669
|
+
if (wiringPiDebug)
|
|
670
|
+
{
|
|
671
|
+
printf ("setPadDrive: Group: %d, value: %d (%08X)\n", group, value, wrVal) ;
|
|
672
|
+
printf ("Read : %08X\n", *(pads + group + 11)) ;
|
|
673
|
+
}
|
|
674
|
+
}
|
|
675
|
+
}
|
|
676
|
+
|
|
677
|
+
|
|
678
|
+
/*
|
|
679
|
+
* getAlt:
|
|
680
|
+
* Returns the ALT bits for a given port. Only really of-use
|
|
681
|
+
* for the gpio readall command (I think)
|
|
682
|
+
*********************************************************************************
|
|
683
|
+
*/
|
|
684
|
+
|
|
685
|
+
int getAlt (int pin)
|
|
686
|
+
{
|
|
687
|
+
int fSel, shift, alt ;
|
|
688
|
+
|
|
689
|
+
pin &= 63 ;
|
|
690
|
+
|
|
691
|
+
/**/ if (wiringPiMode == WPI_MODE_PINS)
|
|
692
|
+
pin = pinToGpio [pin] ;
|
|
693
|
+
else if (wiringPiMode == WPI_MODE_PHYS)
|
|
694
|
+
pin = physToGpio [pin] ;
|
|
695
|
+
else if (wiringPiMode != WPI_MODE_GPIO)
|
|
696
|
+
return 0 ;
|
|
697
|
+
|
|
698
|
+
fSel = gpioToGPFSEL [pin] ;
|
|
699
|
+
shift = gpioToShift [pin] ;
|
|
700
|
+
|
|
701
|
+
alt = (*(gpio + fSel) >> shift) & 7 ;
|
|
702
|
+
|
|
703
|
+
return alt ;
|
|
704
|
+
}
|
|
705
|
+
|
|
706
|
+
|
|
707
|
+
/*
|
|
708
|
+
* pwmSetMode:
|
|
709
|
+
* Select the native "balanced" mode, or standard mark:space mode
|
|
710
|
+
*********************************************************************************
|
|
711
|
+
*/
|
|
712
|
+
|
|
713
|
+
void pwmSetMode (int mode)
|
|
714
|
+
{
|
|
715
|
+
if ((wiringPiMode == WPI_MODE_PINS) || (wiringPiMode == WPI_MODE_GPIO) || (wiringPiMode == WPI_MODE_PHYS))
|
|
716
|
+
{
|
|
717
|
+
if (mode == PWM_MODE_MS)
|
|
718
|
+
*(pwm + PWM_CONTROL) = PWM0_ENABLE | PWM1_ENABLE | PWM0_MS_MODE | PWM1_MS_MODE ;
|
|
719
|
+
else
|
|
720
|
+
*(pwm + PWM_CONTROL) = PWM0_ENABLE | PWM1_ENABLE ;
|
|
721
|
+
}
|
|
722
|
+
}
|
|
723
|
+
|
|
724
|
+
|
|
725
|
+
/*
|
|
726
|
+
* pwmSetRange:
|
|
727
|
+
* Set the PWM range register. We set both range registers to the same
|
|
728
|
+
* value. If you want different in your own code, then write your own.
|
|
729
|
+
*********************************************************************************
|
|
730
|
+
*/
|
|
731
|
+
|
|
732
|
+
void pwmSetRange (unsigned int range)
|
|
733
|
+
{
|
|
734
|
+
if ((wiringPiMode == WPI_MODE_PINS) || (wiringPiMode == WPI_MODE_GPIO) || (wiringPiMode == WPI_MODE_PHYS))
|
|
735
|
+
{
|
|
736
|
+
*(pwm + PWM0_RANGE) = range ; delayMicroseconds (10) ;
|
|
737
|
+
*(pwm + PWM1_RANGE) = range ; delayMicroseconds (10) ;
|
|
738
|
+
}
|
|
739
|
+
}
|
|
740
|
+
|
|
741
|
+
|
|
742
|
+
/*
|
|
743
|
+
* pwmSetClock:
|
|
744
|
+
* Set/Change the PWM clock. Originally my code, but changed
|
|
745
|
+
* (for the better!) by Chris Hall, <chris@kchall.plus.com>
|
|
746
|
+
* after further study of the manual and testing with a 'scope
|
|
747
|
+
*********************************************************************************
|
|
748
|
+
*/
|
|
749
|
+
|
|
750
|
+
void pwmSetClock (int divisor)
|
|
751
|
+
{
|
|
752
|
+
uint32_t pwm_control ;
|
|
753
|
+
divisor &= 4095 ;
|
|
754
|
+
|
|
755
|
+
if ((wiringPiMode == WPI_MODE_PINS) || (wiringPiMode == WPI_MODE_GPIO) || (wiringPiMode == WPI_MODE_PHYS))
|
|
756
|
+
{
|
|
757
|
+
if (wiringPiDebug)
|
|
758
|
+
printf ("Setting to: %d. Current: 0x%08X\n", divisor, *(clk + PWMCLK_DIV)) ;
|
|
759
|
+
|
|
760
|
+
pwm_control = *(pwm + PWM_CONTROL) ; // preserve PWM_CONTROL
|
|
761
|
+
|
|
762
|
+
// We need to stop PWM prior to stopping PWM clock in MS mode otherwise BUSY
|
|
763
|
+
// stays high.
|
|
764
|
+
|
|
765
|
+
*(pwm + PWM_CONTROL) = 0 ; // Stop PWM
|
|
766
|
+
|
|
767
|
+
// Stop PWM clock before changing divisor. The delay after this does need to
|
|
768
|
+
// this big (95uS occasionally fails, 100uS OK), it's almost as though the BUSY
|
|
769
|
+
// flag is not working properly in balanced mode. Without the delay when DIV is
|
|
770
|
+
// adjusted the clock sometimes switches to very slow, once slow further DIV
|
|
771
|
+
// adjustments do nothing and it's difficult to get out of this mode.
|
|
772
|
+
|
|
773
|
+
*(clk + PWMCLK_CNTL) = BCM_PASSWORD | 0x01 ; // Stop PWM Clock
|
|
774
|
+
delayMicroseconds (110) ; // prevents clock going sloooow
|
|
775
|
+
|
|
776
|
+
while ((*(clk + PWMCLK_CNTL) & 0x80) != 0) // Wait for clock to be !BUSY
|
|
777
|
+
delayMicroseconds (1) ;
|
|
778
|
+
|
|
779
|
+
*(clk + PWMCLK_DIV) = BCM_PASSWORD | (divisor << 12) ;
|
|
780
|
+
|
|
781
|
+
*(clk + PWMCLK_CNTL) = BCM_PASSWORD | 0x11 ; // Start PWM clock
|
|
782
|
+
*(pwm + PWM_CONTROL) = pwm_control ; // restore PWM_CONTROL
|
|
783
|
+
|
|
784
|
+
if (wiringPiDebug)
|
|
785
|
+
printf ("Set to: %d. Now : 0x%08X\n", divisor, *(clk + PWMCLK_DIV)) ;
|
|
786
|
+
}
|
|
787
|
+
}
|
|
788
|
+
|
|
789
|
+
|
|
790
|
+
/*
|
|
791
|
+
* gpioClockSet:
|
|
792
|
+
* Set the freuency on a GPIO clock pin
|
|
793
|
+
*********************************************************************************
|
|
794
|
+
*/
|
|
795
|
+
|
|
796
|
+
void gpioClockSet (int pin, int freq)
|
|
797
|
+
{
|
|
798
|
+
int divi, divr, divf ;
|
|
799
|
+
|
|
800
|
+
pin &= 63 ;
|
|
801
|
+
|
|
802
|
+
/**/ if (wiringPiMode == WPI_MODE_PINS)
|
|
803
|
+
pin = pinToGpio [pin] ;
|
|
804
|
+
else if (wiringPiMode == WPI_MODE_PHYS)
|
|
805
|
+
pin = physToGpio [pin] ;
|
|
806
|
+
else if (wiringPiMode != WPI_MODE_GPIO)
|
|
807
|
+
return ;
|
|
808
|
+
|
|
809
|
+
divi = 19200000 / freq ;
|
|
810
|
+
divr = 19200000 % freq ;
|
|
811
|
+
divf = (int)((double)divr * 4096.0 / 19200000.0) ;
|
|
812
|
+
|
|
813
|
+
if (divi > 4095)
|
|
814
|
+
divi = 4095 ;
|
|
815
|
+
|
|
816
|
+
*(clk + gpioToClkCon [pin]) = BCM_PASSWORD | GPIO_CLOCK_SOURCE ; // Stop GPIO Clock
|
|
817
|
+
while ((*(clk + gpioToClkCon [pin]) & 0x80) != 0) // ... and wait
|
|
818
|
+
;
|
|
819
|
+
|
|
820
|
+
*(clk + gpioToClkDiv [pin]) = BCM_PASSWORD | (divi << 12) | divf ; // Set dividers
|
|
821
|
+
*(clk + gpioToClkCon [pin]) = BCM_PASSWORD | 0x10 | GPIO_CLOCK_SOURCE ; // Start Clock
|
|
822
|
+
}
|
|
823
|
+
|
|
824
|
+
|
|
825
|
+
/*
|
|
826
|
+
* wiringPiFindNode:
|
|
827
|
+
* Locate our device node
|
|
828
|
+
*********************************************************************************
|
|
829
|
+
*/
|
|
830
|
+
|
|
831
|
+
static struct wiringPiNodeStruct *wiringPiFindNode (int pin)
|
|
832
|
+
{
|
|
833
|
+
struct wiringPiNodeStruct *node = wiringPiNodes ;
|
|
834
|
+
|
|
835
|
+
while (node != NULL)
|
|
836
|
+
if ((pin >= node->pinBase) && (pin <= node->pinMax))
|
|
837
|
+
return node ;
|
|
838
|
+
else
|
|
839
|
+
node = node->next ;
|
|
840
|
+
|
|
841
|
+
return NULL ;
|
|
842
|
+
}
|
|
843
|
+
|
|
844
|
+
|
|
845
|
+
/*
|
|
846
|
+
* wiringPiNewNode:
|
|
847
|
+
* Create a new GPIO node into the wiringPi handling system
|
|
848
|
+
*********************************************************************************
|
|
849
|
+
*/
|
|
850
|
+
|
|
851
|
+
static void pinModeDummy (struct wiringPiNodeStruct *node, int pin, int mode) { return ; }
|
|
852
|
+
static void pullUpDnControlDummy (struct wiringPiNodeStruct *node, int pin, int pud) { return ; }
|
|
853
|
+
static int digitalReadDummy (struct wiringPiNodeStruct *node, int pin) { return LOW ; }
|
|
854
|
+
static void digitalWriteDummy (struct wiringPiNodeStruct *node, int pin, int value) { return ; }
|
|
855
|
+
static void pwmWriteDummy (struct wiringPiNodeStruct *node, int pin, int value) { return ; }
|
|
856
|
+
static int analogReadDummy (struct wiringPiNodeStruct *node, int pin) { return 0 ; }
|
|
857
|
+
static void analogWriteDummy (struct wiringPiNodeStruct *node, int pin, int value) { return ; }
|
|
858
|
+
|
|
859
|
+
struct wiringPiNodeStruct *wiringPiNewNode (int pinBase, int numPins)
|
|
860
|
+
{
|
|
861
|
+
int pin ;
|
|
862
|
+
struct wiringPiNodeStruct *node ;
|
|
863
|
+
|
|
864
|
+
// Minimum pin base is 64
|
|
865
|
+
|
|
866
|
+
if (pinBase < 64)
|
|
867
|
+
(void)wiringPiFailure ("wiringPiNewNode: pinBase of %d is < 64\n", pinBase) ;
|
|
868
|
+
|
|
869
|
+
// Check all pins in-case there is overlap:
|
|
870
|
+
|
|
871
|
+
for (pin = pinBase ; pin < (pinBase + numPins) ; ++pin)
|
|
872
|
+
if (wiringPiFindNode (pin) != NULL)
|
|
873
|
+
(void)wiringPiFailure ("wiringPiNewNode: Pin %d overlaps with existing definition\n", pin) ;
|
|
874
|
+
|
|
875
|
+
node = calloc (sizeof (struct wiringPiNodeStruct), 1) ; // calloc zeros
|
|
876
|
+
if (node == NULL)
|
|
877
|
+
(void)wiringPiFailure ("wiringPiNewNode: Unable to allocate memory: %s\n", strerror (errno)) ;
|
|
878
|
+
|
|
879
|
+
node->pinBase = pinBase ;
|
|
880
|
+
node->pinMax = pinBase + numPins - 1 ;
|
|
881
|
+
node->pinMode = pinModeDummy ;
|
|
882
|
+
node->pullUpDnControl = pullUpDnControlDummy ;
|
|
883
|
+
node->digitalRead = digitalReadDummy ;
|
|
884
|
+
node->digitalWrite = digitalWriteDummy ;
|
|
885
|
+
node->pwmWrite = pwmWriteDummy ;
|
|
886
|
+
node->analogRead = analogReadDummy ;
|
|
887
|
+
node->analogWrite = analogWriteDummy ;
|
|
888
|
+
node->next = wiringPiNodes ;
|
|
889
|
+
wiringPiNodes = node ;
|
|
890
|
+
|
|
891
|
+
return node ;
|
|
892
|
+
}
|
|
893
|
+
|
|
894
|
+
|
|
895
|
+
#ifdef notYetReady
|
|
896
|
+
/*
|
|
897
|
+
* pinED01:
|
|
898
|
+
* pinED10:
|
|
899
|
+
* Enables edge-detect mode on a pin - from a 0 to a 1 or 1 to 0
|
|
900
|
+
* Pin must already be in input mode with appropriate pull up/downs set.
|
|
901
|
+
*********************************************************************************
|
|
902
|
+
*/
|
|
903
|
+
|
|
904
|
+
void pinEnableED01Pi (int pin)
|
|
905
|
+
{
|
|
906
|
+
pin = pinToGpio [pin & 63] ;
|
|
907
|
+
}
|
|
908
|
+
#endif
|
|
909
|
+
|
|
910
|
+
|
|
911
|
+
/*
|
|
912
|
+
*********************************************************************************
|
|
913
|
+
* Core Functions
|
|
914
|
+
*********************************************************************************
|
|
915
|
+
*/
|
|
916
|
+
|
|
917
|
+
|
|
918
|
+
/*
|
|
919
|
+
* pinMode:
|
|
920
|
+
* Sets the mode of a pin to be input, output or PWM output
|
|
921
|
+
*********************************************************************************
|
|
922
|
+
*/
|
|
923
|
+
|
|
924
|
+
void pinMode (int pin, int mode)
|
|
925
|
+
{
|
|
926
|
+
int fSel, shift, alt ;
|
|
927
|
+
struct wiringPiNodeStruct *node = wiringPiNodes ;
|
|
928
|
+
|
|
929
|
+
if ((pin & PI_GPIO_MASK) == 0) // On-board pin
|
|
930
|
+
{
|
|
931
|
+
/**/ if (wiringPiMode == WPI_MODE_PINS)
|
|
932
|
+
pin = pinToGpio [pin] ;
|
|
933
|
+
else if (wiringPiMode == WPI_MODE_PHYS)
|
|
934
|
+
pin = physToGpio [pin] ;
|
|
935
|
+
else if (wiringPiMode != WPI_MODE_GPIO)
|
|
936
|
+
return ;
|
|
937
|
+
|
|
938
|
+
fSel = gpioToGPFSEL [pin] ;
|
|
939
|
+
shift = gpioToShift [pin] ;
|
|
940
|
+
|
|
941
|
+
/**/ if (mode == INPUT)
|
|
942
|
+
*(gpio + fSel) = (*(gpio + fSel) & ~(7 << shift)) ; // Sets bits to zero = input
|
|
943
|
+
else if (mode == OUTPUT)
|
|
944
|
+
*(gpio + fSel) = (*(gpio + fSel) & ~(7 << shift)) | (1 << shift) ;
|
|
945
|
+
else if (mode == PWM_OUTPUT)
|
|
946
|
+
{
|
|
947
|
+
if ((alt = gpioToPwmALT [pin]) == 0) // Not a PWM pin
|
|
948
|
+
return ;
|
|
949
|
+
|
|
950
|
+
// Set pin to PWM mode
|
|
951
|
+
|
|
952
|
+
*(gpio + fSel) = (*(gpio + fSel) & ~(7 << shift)) | (alt << shift) ;
|
|
953
|
+
delayMicroseconds (110) ; // See comments in pwmSetClockWPi
|
|
954
|
+
|
|
955
|
+
pwmSetMode (PWM_MODE_BAL) ; // Pi default mode
|
|
956
|
+
pwmSetRange (1024) ; // Default range of 1024
|
|
957
|
+
pwmSetClock (32) ; // 19.2 / 32 = 600KHz - Also starts the PWM
|
|
958
|
+
}
|
|
959
|
+
else if (mode == GPIO_CLOCK)
|
|
960
|
+
{
|
|
961
|
+
if ((alt = gpioToGpClkALT0 [pin]) == 0) // Not a GPIO_CLOCK pin
|
|
962
|
+
return ;
|
|
963
|
+
|
|
964
|
+
// Set pin to GPIO_CLOCK mode and set the clock frequency to 100KHz
|
|
965
|
+
|
|
966
|
+
*(gpio + fSel) = (*(gpio + fSel) & ~(7 << shift)) | (alt << shift) ;
|
|
967
|
+
delayMicroseconds (110) ;
|
|
968
|
+
gpioClockSet (pin, 100000) ;
|
|
969
|
+
}
|
|
970
|
+
}
|
|
971
|
+
else
|
|
972
|
+
{
|
|
973
|
+
if ((node = wiringPiFindNode (pin)) != NULL)
|
|
974
|
+
node->pinMode (node, pin, mode) ;
|
|
975
|
+
return ;
|
|
976
|
+
}
|
|
977
|
+
}
|
|
978
|
+
|
|
979
|
+
|
|
980
|
+
/*
|
|
981
|
+
* pullUpDownCtrl:
|
|
982
|
+
* Control the internal pull-up/down resistors on a GPIO pin
|
|
983
|
+
* The Arduino only has pull-ups and these are enabled by writing 1
|
|
984
|
+
* to a port when in input mode - this paradigm doesn't quite apply
|
|
985
|
+
* here though.
|
|
986
|
+
*********************************************************************************
|
|
987
|
+
*/
|
|
988
|
+
|
|
989
|
+
void pullUpDnControl (int pin, int pud)
|
|
990
|
+
{
|
|
991
|
+
struct wiringPiNodeStruct *node = wiringPiNodes ;
|
|
992
|
+
|
|
993
|
+
if ((pin & PI_GPIO_MASK) == 0) // On-Board Pin
|
|
994
|
+
{
|
|
995
|
+
/**/ if (wiringPiMode == WPI_MODE_PINS)
|
|
996
|
+
pin = pinToGpio [pin] ;
|
|
997
|
+
else if (wiringPiMode == WPI_MODE_PHYS)
|
|
998
|
+
pin = physToGpio [pin] ;
|
|
999
|
+
else if (wiringPiMode != WPI_MODE_GPIO)
|
|
1000
|
+
return ;
|
|
1001
|
+
|
|
1002
|
+
pud &= 3 ;
|
|
1003
|
+
|
|
1004
|
+
*(gpio + GPPUD) = pud ; delayMicroseconds (5) ;
|
|
1005
|
+
*(gpio + gpioToPUDCLK [pin]) = 1 << (pin & 31) ; delayMicroseconds (5) ;
|
|
1006
|
+
|
|
1007
|
+
*(gpio + GPPUD) = 0 ; delayMicroseconds (5) ;
|
|
1008
|
+
*(gpio + gpioToPUDCLK [pin]) = 0 ; delayMicroseconds (5) ;
|
|
1009
|
+
}
|
|
1010
|
+
else
|
|
1011
|
+
{
|
|
1012
|
+
if ((node = wiringPiFindNode (pin)) != NULL)
|
|
1013
|
+
node->pullUpDnControl (node, pin, pud) ;
|
|
1014
|
+
return ;
|
|
1015
|
+
}
|
|
1016
|
+
}
|
|
1017
|
+
|
|
1018
|
+
|
|
1019
|
+
/*
|
|
1020
|
+
* digitalRead:
|
|
1021
|
+
* Read the value of a given Pin, returning HIGH or LOW
|
|
1022
|
+
*********************************************************************************
|
|
1023
|
+
*/
|
|
1024
|
+
|
|
1025
|
+
int digitalRead (int pin)
|
|
1026
|
+
{
|
|
1027
|
+
char c ;
|
|
1028
|
+
struct wiringPiNodeStruct *node = wiringPiNodes ;
|
|
1029
|
+
|
|
1030
|
+
if ((pin & PI_GPIO_MASK) == 0) // On-Board Pin
|
|
1031
|
+
{
|
|
1032
|
+
/**/ if (wiringPiMode == WPI_MODE_GPIO_SYS) // Sys mode
|
|
1033
|
+
{
|
|
1034
|
+
if (sysFds [pin] == -1)
|
|
1035
|
+
return LOW ;
|
|
1036
|
+
|
|
1037
|
+
lseek (sysFds [pin], 0L, SEEK_SET) ;
|
|
1038
|
+
read (sysFds [pin], &c, 1) ;
|
|
1039
|
+
return (c == '0') ? LOW : HIGH ;
|
|
1040
|
+
}
|
|
1041
|
+
else if (wiringPiMode == WPI_MODE_PINS)
|
|
1042
|
+
pin = pinToGpio [pin] ;
|
|
1043
|
+
else if (wiringPiMode == WPI_MODE_PHYS)
|
|
1044
|
+
pin = physToGpio [pin] ;
|
|
1045
|
+
else if (wiringPiMode != WPI_MODE_GPIO)
|
|
1046
|
+
return LOW ;
|
|
1047
|
+
|
|
1048
|
+
if ((*(gpio + gpioToGPLEV [pin]) & (1 << (pin & 31))) != 0)
|
|
1049
|
+
return HIGH ;
|
|
1050
|
+
else
|
|
1051
|
+
return LOW ;
|
|
1052
|
+
}
|
|
1053
|
+
else
|
|
1054
|
+
{
|
|
1055
|
+
if ((node = wiringPiFindNode (pin)) == NULL)
|
|
1056
|
+
return LOW ;
|
|
1057
|
+
return node->digitalRead (node, pin) ;
|
|
1058
|
+
}
|
|
1059
|
+
}
|
|
1060
|
+
|
|
1061
|
+
|
|
1062
|
+
/*
|
|
1063
|
+
* digitalWrite:
|
|
1064
|
+
* Set an output bit
|
|
1065
|
+
*********************************************************************************
|
|
1066
|
+
*/
|
|
1067
|
+
|
|
1068
|
+
void digitalWrite (int pin, int value)
|
|
1069
|
+
{
|
|
1070
|
+
struct wiringPiNodeStruct *node = wiringPiNodes ;
|
|
1071
|
+
|
|
1072
|
+
if ((pin & PI_GPIO_MASK) == 0) // On-Board Pin
|
|
1073
|
+
{
|
|
1074
|
+
/**/ if (wiringPiMode == WPI_MODE_GPIO_SYS) // Sys mode
|
|
1075
|
+
{
|
|
1076
|
+
if (sysFds [pin] != -1)
|
|
1077
|
+
{
|
|
1078
|
+
if (value == LOW)
|
|
1079
|
+
write (sysFds [pin], "0\n", 2) ;
|
|
1080
|
+
else
|
|
1081
|
+
write (sysFds [pin], "1\n", 2) ;
|
|
1082
|
+
}
|
|
1083
|
+
}
|
|
1084
|
+
else if (wiringPiMode == WPI_MODE_PINS)
|
|
1085
|
+
pin = pinToGpio [pin] ;
|
|
1086
|
+
else if (wiringPiMode == WPI_MODE_GPIO)
|
|
1087
|
+
pin = physToGpio [pin] ;
|
|
1088
|
+
else if (wiringPiMode != WPI_MODE_GPIO)
|
|
1089
|
+
return ;
|
|
1090
|
+
|
|
1091
|
+
if (value == LOW)
|
|
1092
|
+
*(gpio + gpioToGPCLR [pin]) = 1 << (pin & 31) ;
|
|
1093
|
+
else
|
|
1094
|
+
*(gpio + gpioToGPSET [pin]) = 1 << (pin & 31) ;
|
|
1095
|
+
}
|
|
1096
|
+
else
|
|
1097
|
+
{
|
|
1098
|
+
if ((node = wiringPiFindNode (pin)) != NULL)
|
|
1099
|
+
node->digitalWrite (node, pin, value) ;
|
|
1100
|
+
}
|
|
1101
|
+
}
|
|
1102
|
+
|
|
1103
|
+
|
|
1104
|
+
/*
|
|
1105
|
+
* pwmWrite:
|
|
1106
|
+
* Set an output PWM value
|
|
1107
|
+
*********************************************************************************
|
|
1108
|
+
*/
|
|
1109
|
+
|
|
1110
|
+
void pwmWrite (int pin, int value)
|
|
1111
|
+
{
|
|
1112
|
+
struct wiringPiNodeStruct *node = wiringPiNodes ;
|
|
1113
|
+
|
|
1114
|
+
if ((pin & PI_GPIO_MASK) == 0) // On-Board Pin
|
|
1115
|
+
{
|
|
1116
|
+
/**/ if (wiringPiMode == WPI_MODE_PINS)
|
|
1117
|
+
pin = pinToGpio [pin] ;
|
|
1118
|
+
else if (wiringPiMode == WPI_MODE_PHYS)
|
|
1119
|
+
pin = physToGpio [pin] ;
|
|
1120
|
+
else if (wiringPiMode != WPI_MODE_GPIO)
|
|
1121
|
+
return ;
|
|
1122
|
+
|
|
1123
|
+
*(pwm + gpioToPwmPort [pin]) = value ;
|
|
1124
|
+
}
|
|
1125
|
+
else
|
|
1126
|
+
{
|
|
1127
|
+
if ((node = wiringPiFindNode (pin)) != NULL)
|
|
1128
|
+
node->pwmWrite (node, pin, value) ;
|
|
1129
|
+
}
|
|
1130
|
+
}
|
|
1131
|
+
|
|
1132
|
+
|
|
1133
|
+
/*
|
|
1134
|
+
* analogRead:
|
|
1135
|
+
* Read the analog value of a given Pin.
|
|
1136
|
+
* There is no on-board Pi analog hardware,
|
|
1137
|
+
* so this needs to go to a new node.
|
|
1138
|
+
*********************************************************************************
|
|
1139
|
+
*/
|
|
1140
|
+
|
|
1141
|
+
int analogRead (int pin)
|
|
1142
|
+
{
|
|
1143
|
+
struct wiringPiNodeStruct *node = wiringPiNodes ;
|
|
1144
|
+
|
|
1145
|
+
if ((node = wiringPiFindNode (pin)) == NULL)
|
|
1146
|
+
return 0 ;
|
|
1147
|
+
else
|
|
1148
|
+
return node->analogRead (node, pin) ;
|
|
1149
|
+
}
|
|
1150
|
+
|
|
1151
|
+
|
|
1152
|
+
/*
|
|
1153
|
+
* analogWrite:
|
|
1154
|
+
* Write the analog value to the given Pin.
|
|
1155
|
+
* There is no on-board Pi analog hardware,
|
|
1156
|
+
* so this needs to go to a new node.
|
|
1157
|
+
*********************************************************************************
|
|
1158
|
+
*/
|
|
1159
|
+
|
|
1160
|
+
void analogWrite (int pin, int value)
|
|
1161
|
+
{
|
|
1162
|
+
struct wiringPiNodeStruct *node = wiringPiNodes ;
|
|
1163
|
+
|
|
1164
|
+
if ((node = wiringPiFindNode (pin)) == NULL)
|
|
1165
|
+
return ;
|
|
1166
|
+
|
|
1167
|
+
node->analogWrite (node, pin, value) ;
|
|
1168
|
+
}
|
|
1169
|
+
|
|
1170
|
+
|
|
1171
|
+
|
|
1172
|
+
/*
|
|
1173
|
+
* digitalWriteByte:
|
|
1174
|
+
* Pi Specific
|
|
1175
|
+
* Write an 8-bit byte to the first 8 GPIO pins - try to do it as
|
|
1176
|
+
* fast as possible.
|
|
1177
|
+
* However it still needs 2 operations to set the bits, so any external
|
|
1178
|
+
* hardware must not rely on seeing a change as there will be a change
|
|
1179
|
+
* to set the outputs bits to zero, then another change to set the 1's
|
|
1180
|
+
*********************************************************************************
|
|
1181
|
+
*/
|
|
1182
|
+
|
|
1183
|
+
void digitalWriteByte (int value)
|
|
1184
|
+
{
|
|
1185
|
+
uint32_t pinSet = 0 ;
|
|
1186
|
+
uint32_t pinClr = 0 ;
|
|
1187
|
+
int mask = 1 ;
|
|
1188
|
+
int pin ;
|
|
1189
|
+
|
|
1190
|
+
/**/ if (wiringPiMode == WPI_MODE_GPIO_SYS)
|
|
1191
|
+
{
|
|
1192
|
+
for (pin = 0 ; pin < 8 ; ++pin)
|
|
1193
|
+
{
|
|
1194
|
+
digitalWrite (pin, value & mask) ;
|
|
1195
|
+
mask <<= 1 ;
|
|
1196
|
+
}
|
|
1197
|
+
}
|
|
1198
|
+
else
|
|
1199
|
+
{
|
|
1200
|
+
for (pin = 0 ; pin < 8 ; ++pin)
|
|
1201
|
+
{
|
|
1202
|
+
if ((value & mask) == 0)
|
|
1203
|
+
pinClr |= (1 << pinToGpio [pin]) ;
|
|
1204
|
+
else
|
|
1205
|
+
pinSet |= (1 << pinToGpio [pin]) ;
|
|
1206
|
+
|
|
1207
|
+
mask <<= 1 ;
|
|
1208
|
+
}
|
|
1209
|
+
|
|
1210
|
+
*(gpio + gpioToGPCLR [0]) = pinClr ;
|
|
1211
|
+
*(gpio + gpioToGPSET [0]) = pinSet ;
|
|
1212
|
+
}
|
|
1213
|
+
}
|
|
1214
|
+
|
|
1215
|
+
|
|
1216
|
+
/*
|
|
1217
|
+
* waitForInterrupt:
|
|
1218
|
+
* Pi Specific.
|
|
1219
|
+
* Wait for Interrupt on a GPIO pin.
|
|
1220
|
+
* This is actually done via the /sys/class/gpio interface regardless of
|
|
1221
|
+
* the wiringPi access mode in-use. Maybe sometime it might get a better
|
|
1222
|
+
* way for a bit more efficiency.
|
|
1223
|
+
*********************************************************************************
|
|
1224
|
+
*/
|
|
1225
|
+
|
|
1226
|
+
int waitForInterrupt (int pin, int mS)
|
|
1227
|
+
{
|
|
1228
|
+
int fd, x ;
|
|
1229
|
+
uint8_t c ;
|
|
1230
|
+
struct pollfd polls ;
|
|
1231
|
+
|
|
1232
|
+
/**/ if (wiringPiMode == WPI_MODE_PINS)
|
|
1233
|
+
pin = pinToGpio [pin] ;
|
|
1234
|
+
else if (wiringPiMode == WPI_MODE_PHYS)
|
|
1235
|
+
pin = physToGpio [pin] ;
|
|
1236
|
+
|
|
1237
|
+
if ((fd = sysFds [pin & 63]) == -1)
|
|
1238
|
+
return -2 ;
|
|
1239
|
+
|
|
1240
|
+
// Setup poll structure
|
|
1241
|
+
|
|
1242
|
+
polls.fd = fd ;
|
|
1243
|
+
polls.events = POLLPRI ; // Urgent data!
|
|
1244
|
+
|
|
1245
|
+
// Wait for it ...
|
|
1246
|
+
|
|
1247
|
+
x = poll (&polls, 1, mS) ;
|
|
1248
|
+
|
|
1249
|
+
// Do a dummy read to clear the interrupt
|
|
1250
|
+
// A one character read appars to be enough.
|
|
1251
|
+
|
|
1252
|
+
(void)read (fd, &c, 1) ;
|
|
1253
|
+
|
|
1254
|
+
return x ;
|
|
1255
|
+
}
|
|
1256
|
+
|
|
1257
|
+
|
|
1258
|
+
/*
|
|
1259
|
+
* interruptHandler:
|
|
1260
|
+
* This is a thread and gets started to wait for the interrupt we're
|
|
1261
|
+
* hoping to catch. It will call the user-function when the interrupt
|
|
1262
|
+
* fires.
|
|
1263
|
+
*********************************************************************************
|
|
1264
|
+
*/
|
|
1265
|
+
|
|
1266
|
+
static void *interruptHandler (void *arg)
|
|
1267
|
+
{
|
|
1268
|
+
int myPin = *(int *)arg ;
|
|
1269
|
+
|
|
1270
|
+
(void)piHiPri (55) ; // Only effective if we run as root
|
|
1271
|
+
|
|
1272
|
+
for (;;)
|
|
1273
|
+
if (waitForInterrupt (myPin, -1) > 0)
|
|
1274
|
+
isrFunctions [myPin] () ;
|
|
1275
|
+
|
|
1276
|
+
return NULL ;
|
|
1277
|
+
}
|
|
1278
|
+
|
|
1279
|
+
|
|
1280
|
+
/*
|
|
1281
|
+
* wiringPiISR:
|
|
1282
|
+
* Pi Specific.
|
|
1283
|
+
* Take the details and create an interrupt handler that will do a call-
|
|
1284
|
+
* back to the user supplied function.
|
|
1285
|
+
*********************************************************************************
|
|
1286
|
+
*/
|
|
1287
|
+
|
|
1288
|
+
int wiringPiISR (int pin, int mode, void (*function)(void))
|
|
1289
|
+
{
|
|
1290
|
+
pthread_t threadId ;
|
|
1291
|
+
char fName [64] ;
|
|
1292
|
+
char *modeS ;
|
|
1293
|
+
char pinS [8] ;
|
|
1294
|
+
pid_t pid ;
|
|
1295
|
+
int count, i ;
|
|
1296
|
+
uint8_t c ;
|
|
1297
|
+
|
|
1298
|
+
pin &= 63 ;
|
|
1299
|
+
|
|
1300
|
+
/**/ if (wiringPiMode == WPI_MODE_UNINITIALISED)
|
|
1301
|
+
(void)wiringPiFailure ("wiringPiISR: wiringPi has not been initialised. Unable to continue.\n") ;
|
|
1302
|
+
else if (wiringPiMode == WPI_MODE_PINS)
|
|
1303
|
+
pin = pinToGpio [pin] ;
|
|
1304
|
+
else if (wiringPiMode == WPI_MODE_PHYS)
|
|
1305
|
+
pin = physToGpio [pin] ;
|
|
1306
|
+
|
|
1307
|
+
// Now export the pin and set the right edge
|
|
1308
|
+
// We're going to use the gpio program to do this, so it assumes
|
|
1309
|
+
// a full installation of wiringPi. It's a bit 'clunky', but it
|
|
1310
|
+
// is a way that will work when we're running in "Sys" mode, as
|
|
1311
|
+
// a non-root user. (without sudo)
|
|
1312
|
+
|
|
1313
|
+
if (mode != INT_EDGE_SETUP)
|
|
1314
|
+
{
|
|
1315
|
+
/**/ if (mode == INT_EDGE_FALLING)
|
|
1316
|
+
modeS = "falling" ;
|
|
1317
|
+
else if (mode == INT_EDGE_RISING)
|
|
1318
|
+
modeS = "rising" ;
|
|
1319
|
+
else
|
|
1320
|
+
modeS = "both" ;
|
|
1321
|
+
|
|
1322
|
+
sprintf (pinS, "%d", pin) ;
|
|
1323
|
+
|
|
1324
|
+
if ((pid = fork ()) < 0) // Fail
|
|
1325
|
+
return pid ;
|
|
1326
|
+
|
|
1327
|
+
if (pid == 0) // Child, exec
|
|
1328
|
+
{
|
|
1329
|
+
execl ("/usr/local/bin/gpio", "gpio", "edge", pinS, modeS, (char *)NULL) ;
|
|
1330
|
+
return -1 ; // Failure ...
|
|
1331
|
+
}
|
|
1332
|
+
else // Parent, wait
|
|
1333
|
+
wait (NULL) ;
|
|
1334
|
+
}
|
|
1335
|
+
|
|
1336
|
+
// Now pre-open the /sys/class node - it may already be open if
|
|
1337
|
+
// we are in Sys mode, but this will do no harm.
|
|
1338
|
+
|
|
1339
|
+
sprintf (fName, "/sys/class/gpio/gpio%d/value", pin) ;
|
|
1340
|
+
if ((sysFds [pin] = open (fName, O_RDWR)) < 0)
|
|
1341
|
+
return -1 ;
|
|
1342
|
+
|
|
1343
|
+
// Clear any initial pending interrupt
|
|
1344
|
+
|
|
1345
|
+
ioctl (sysFds [pin], FIONREAD, &count) ;
|
|
1346
|
+
for (i = 0 ; i < count ; ++i)
|
|
1347
|
+
read (sysFds [pin], &c, 1) ;
|
|
1348
|
+
|
|
1349
|
+
isrFunctions [pin] = function ;
|
|
1350
|
+
|
|
1351
|
+
pthread_create (&threadId, NULL, interruptHandler, &pin) ;
|
|
1352
|
+
|
|
1353
|
+
delay (1) ;
|
|
1354
|
+
|
|
1355
|
+
return 0 ;
|
|
1356
|
+
}
|
|
1357
|
+
|
|
1358
|
+
|
|
1359
|
+
/*
|
|
1360
|
+
* initialiseEpoch:
|
|
1361
|
+
* Initialise our start-of-time variable to be the current unix
|
|
1362
|
+
* time in milliseconds and microseconds.
|
|
1363
|
+
*********************************************************************************
|
|
1364
|
+
*/
|
|
1365
|
+
|
|
1366
|
+
static void initialiseEpoch (void)
|
|
1367
|
+
{
|
|
1368
|
+
struct timeval tv ;
|
|
1369
|
+
|
|
1370
|
+
gettimeofday (&tv, NULL) ;
|
|
1371
|
+
epochMilli = (uint64_t)tv.tv_sec * (uint64_t)1000 + (uint64_t)(tv.tv_usec / 1000) ;
|
|
1372
|
+
epochMicro = (uint64_t)tv.tv_sec * (uint64_t)1000000 + (uint64_t)(tv.tv_usec) ;
|
|
1373
|
+
}
|
|
1374
|
+
|
|
1375
|
+
|
|
1376
|
+
/*
|
|
1377
|
+
* delay:
|
|
1378
|
+
* Wait for some number of milliseconds
|
|
1379
|
+
*********************************************************************************
|
|
1380
|
+
*/
|
|
1381
|
+
|
|
1382
|
+
void delay (unsigned int howLong)
|
|
1383
|
+
{
|
|
1384
|
+
struct timespec sleeper, dummy ;
|
|
1385
|
+
|
|
1386
|
+
sleeper.tv_sec = (time_t)(howLong / 1000) ;
|
|
1387
|
+
sleeper.tv_nsec = (long)(howLong % 1000) * 1000000 ;
|
|
1388
|
+
|
|
1389
|
+
nanosleep (&sleeper, &dummy) ;
|
|
1390
|
+
}
|
|
1391
|
+
|
|
1392
|
+
|
|
1393
|
+
/*
|
|
1394
|
+
* delayMicroseconds:
|
|
1395
|
+
* This is somewhat intersting. It seems that on the Pi, a single call
|
|
1396
|
+
* to nanosleep takes some 80 to 130 microseconds anyway, so while
|
|
1397
|
+
* obeying the standards (may take longer), it's not always what we
|
|
1398
|
+
* want!
|
|
1399
|
+
*
|
|
1400
|
+
* So what I'll do now is if the delay is less than 100uS we'll do it
|
|
1401
|
+
* in a hard loop, watching a built-in counter on the ARM chip. This is
|
|
1402
|
+
* somewhat sub-optimal in that it uses 100% CPU, something not an issue
|
|
1403
|
+
* in a microcontroller, but under a multi-tasking, multi-user OS, it's
|
|
1404
|
+
* wastefull, however we've no real choice )-:
|
|
1405
|
+
*
|
|
1406
|
+
* Plan B: It seems all might not be well with that plan, so changing it
|
|
1407
|
+
* to use gettimeofday () and poll on that instead...
|
|
1408
|
+
*********************************************************************************
|
|
1409
|
+
*/
|
|
1410
|
+
|
|
1411
|
+
void delayMicrosecondsHard (unsigned int howLong)
|
|
1412
|
+
{
|
|
1413
|
+
struct timeval tNow, tLong, tEnd ;
|
|
1414
|
+
|
|
1415
|
+
gettimeofday (&tNow, NULL) ;
|
|
1416
|
+
tLong.tv_sec = howLong / 1000000 ;
|
|
1417
|
+
tLong.tv_usec = howLong % 1000000 ;
|
|
1418
|
+
timeradd (&tNow, &tLong, &tEnd) ;
|
|
1419
|
+
|
|
1420
|
+
while (timercmp (&tNow, &tEnd, <))
|
|
1421
|
+
gettimeofday (&tNow, NULL) ;
|
|
1422
|
+
}
|
|
1423
|
+
|
|
1424
|
+
void delayMicroseconds (unsigned int howLong)
|
|
1425
|
+
{
|
|
1426
|
+
struct timespec sleeper ;
|
|
1427
|
+
|
|
1428
|
+
/**/ if (howLong == 0)
|
|
1429
|
+
return ;
|
|
1430
|
+
else if (howLong < 100)
|
|
1431
|
+
delayMicrosecondsHard (howLong) ;
|
|
1432
|
+
else
|
|
1433
|
+
{
|
|
1434
|
+
sleeper.tv_sec = 0 ;
|
|
1435
|
+
sleeper.tv_nsec = (long)(howLong * 1000) ;
|
|
1436
|
+
nanosleep (&sleeper, NULL) ;
|
|
1437
|
+
}
|
|
1438
|
+
}
|
|
1439
|
+
|
|
1440
|
+
|
|
1441
|
+
/*
|
|
1442
|
+
* millis:
|
|
1443
|
+
* Return a number of milliseconds as an unsigned int.
|
|
1444
|
+
*********************************************************************************
|
|
1445
|
+
*/
|
|
1446
|
+
|
|
1447
|
+
unsigned int millis (void)
|
|
1448
|
+
{
|
|
1449
|
+
struct timeval tv ;
|
|
1450
|
+
uint64_t now ;
|
|
1451
|
+
|
|
1452
|
+
gettimeofday (&tv, NULL) ;
|
|
1453
|
+
now = (uint64_t)tv.tv_sec * (uint64_t)1000 + (uint64_t)(tv.tv_usec / 1000) ;
|
|
1454
|
+
|
|
1455
|
+
return (uint32_t)(now - epochMilli) ;
|
|
1456
|
+
}
|
|
1457
|
+
|
|
1458
|
+
|
|
1459
|
+
/*
|
|
1460
|
+
* micros:
|
|
1461
|
+
* Return a number of microseconds as an unsigned int.
|
|
1462
|
+
*********************************************************************************
|
|
1463
|
+
*/
|
|
1464
|
+
|
|
1465
|
+
unsigned int micros (void)
|
|
1466
|
+
{
|
|
1467
|
+
struct timeval tv ;
|
|
1468
|
+
uint64_t now ;
|
|
1469
|
+
|
|
1470
|
+
gettimeofday (&tv, NULL) ;
|
|
1471
|
+
now = (uint64_t)tv.tv_sec * (uint64_t)1000000 + (uint64_t)tv.tv_usec ;
|
|
1472
|
+
|
|
1473
|
+
return (uint32_t)(now - epochMicro) ;
|
|
1474
|
+
}
|
|
1475
|
+
|
|
1476
|
+
|
|
1477
|
+
/*
|
|
1478
|
+
* wiringPiSetup:
|
|
1479
|
+
* Must be called once at the start of your program execution.
|
|
1480
|
+
*
|
|
1481
|
+
* Default setup: Initialises the system into wiringPi Pin mode and uses the
|
|
1482
|
+
* memory mapped hardware directly.
|
|
1483
|
+
*********************************************************************************
|
|
1484
|
+
*/
|
|
1485
|
+
|
|
1486
|
+
int wiringPiSetup (void)
|
|
1487
|
+
{
|
|
1488
|
+
int fd ;
|
|
1489
|
+
int boardRev ;
|
|
1490
|
+
|
|
1491
|
+
if (getenv (ENV_DEBUG) != NULL)
|
|
1492
|
+
wiringPiDebug = TRUE ;
|
|
1493
|
+
|
|
1494
|
+
if (getenv (ENV_CODES) != NULL)
|
|
1495
|
+
wiringPiCodes = TRUE ;
|
|
1496
|
+
|
|
1497
|
+
if (geteuid () != 0)
|
|
1498
|
+
(void)wiringPiFailure ("wiringPiSetup: Must be root. (Did you forget sudo?)\n") ;
|
|
1499
|
+
|
|
1500
|
+
if (wiringPiDebug)
|
|
1501
|
+
printf ("wiringPi: wiringPiSetup called\n") ;
|
|
1502
|
+
|
|
1503
|
+
boardRev = piBoardRev () ;
|
|
1504
|
+
|
|
1505
|
+
if (boardRev == 1)
|
|
1506
|
+
{
|
|
1507
|
+
pinToGpio = pinToGpioR1 ;
|
|
1508
|
+
physToGpio = physToGpioR1 ;
|
|
1509
|
+
}
|
|
1510
|
+
else
|
|
1511
|
+
{
|
|
1512
|
+
pinToGpio = pinToGpioR2 ;
|
|
1513
|
+
physToGpio = physToGpioR2 ;
|
|
1514
|
+
}
|
|
1515
|
+
|
|
1516
|
+
// Open the master /dev/memory device
|
|
1517
|
+
|
|
1518
|
+
if ((fd = open ("/dev/mem", O_RDWR | O_SYNC) ) < 0)
|
|
1519
|
+
(void)wiringPiFailure ("wiringPiSetup: Unable to open /dev/mem: %s\n", strerror (errno)) ;
|
|
1520
|
+
|
|
1521
|
+
// GPIO:
|
|
1522
|
+
|
|
1523
|
+
gpio = (uint32_t *)mmap(0, BLOCK_SIZE, PROT_READ|PROT_WRITE, MAP_SHARED, fd, GPIO_BASE) ;
|
|
1524
|
+
if ((int32_t)gpio == -1)
|
|
1525
|
+
(void)wiringPiFailure ("wiringPiSetup: mmap (GPIO) failed: %s\n", strerror (errno)) ;
|
|
1526
|
+
|
|
1527
|
+
// PWM
|
|
1528
|
+
|
|
1529
|
+
pwm = (uint32_t *)mmap(0, BLOCK_SIZE, PROT_READ|PROT_WRITE, MAP_SHARED, fd, GPIO_PWM) ;
|
|
1530
|
+
if ((int32_t)pwm == -1)
|
|
1531
|
+
(void)wiringPiFailure ("wiringPiSetup: mmap (PWM) failed: %s\n", strerror (errno)) ;
|
|
1532
|
+
|
|
1533
|
+
// Clock control (needed for PWM)
|
|
1534
|
+
|
|
1535
|
+
clk = (uint32_t *)mmap(0, BLOCK_SIZE, PROT_READ|PROT_WRITE, MAP_SHARED, fd, CLOCK_BASE) ;
|
|
1536
|
+
if ((int32_t)clk == -1)
|
|
1537
|
+
(void)wiringPiFailure ("wiringPiSetup: mmap (CLOCK) failed: %s\n", strerror (errno)) ;
|
|
1538
|
+
|
|
1539
|
+
// The drive pads
|
|
1540
|
+
|
|
1541
|
+
pads = (uint32_t *)mmap(0, BLOCK_SIZE, PROT_READ|PROT_WRITE, MAP_SHARED, fd, GPIO_PADS) ;
|
|
1542
|
+
if ((int32_t)pads == -1)
|
|
1543
|
+
(void)wiringPiFailure ("wiringPiSetup: mmap (PADS) failed: %s\n", strerror (errno)) ;
|
|
1544
|
+
|
|
1545
|
+
#ifdef USE_TIMER
|
|
1546
|
+
// The system timer
|
|
1547
|
+
|
|
1548
|
+
timer = (uint32_t *)mmap(0, BLOCK_SIZE, PROT_READ|PROT_WRITE, MAP_SHARED, fd, GPIO_TIMER) ;
|
|
1549
|
+
if ((int32_t)timer == -1)
|
|
1550
|
+
(void)wiringPiFailure ("wiringPiSetup: mmap (TIMER) failed: %s\n", strerror (errno)) ;
|
|
1551
|
+
|
|
1552
|
+
// Set the timer to free-running, 1MHz.
|
|
1553
|
+
// 0xF9 is 249, the timer divide is base clock / (divide+1)
|
|
1554
|
+
// so base clock is 250MHz / 250 = 1MHz.
|
|
1555
|
+
|
|
1556
|
+
*(timer + TIMER_CONTROL) = 0x0000280 ;
|
|
1557
|
+
*(timer + TIMER_PRE_DIV) = 0x00000F9 ;
|
|
1558
|
+
timerIrqRaw = timer + TIMER_IRQ_RAW ;
|
|
1559
|
+
#endif
|
|
1560
|
+
|
|
1561
|
+
initialiseEpoch () ;
|
|
1562
|
+
|
|
1563
|
+
wiringPiMode = WPI_MODE_PINS ;
|
|
1564
|
+
|
|
1565
|
+
return 0 ;
|
|
1566
|
+
}
|
|
1567
|
+
|
|
1568
|
+
|
|
1569
|
+
/*
|
|
1570
|
+
* wiringPiSetupGpio:
|
|
1571
|
+
* Must be called once at the start of your program execution.
|
|
1572
|
+
*
|
|
1573
|
+
* GPIO setup: Initialises the system into GPIO Pin mode and uses the
|
|
1574
|
+
* memory mapped hardware directly.
|
|
1575
|
+
*********************************************************************************
|
|
1576
|
+
*/
|
|
1577
|
+
|
|
1578
|
+
int wiringPiSetupGpio (void)
|
|
1579
|
+
{
|
|
1580
|
+
(void)wiringPiSetup () ;
|
|
1581
|
+
|
|
1582
|
+
if (wiringPiDebug)
|
|
1583
|
+
printf ("wiringPi: wiringPiSetupGpio called\n") ;
|
|
1584
|
+
|
|
1585
|
+
wiringPiMode = WPI_MODE_GPIO ;
|
|
1586
|
+
|
|
1587
|
+
return 0 ;
|
|
1588
|
+
}
|
|
1589
|
+
|
|
1590
|
+
|
|
1591
|
+
/*
|
|
1592
|
+
* wiringPiSetupPhys:
|
|
1593
|
+
* Must be called once at the start of your program execution.
|
|
1594
|
+
*
|
|
1595
|
+
* Phys setup: Initialises the system into Physical Pin mode and uses the
|
|
1596
|
+
* memory mapped hardware directly.
|
|
1597
|
+
*********************************************************************************
|
|
1598
|
+
*/
|
|
1599
|
+
|
|
1600
|
+
int wiringPiSetupPhys (void)
|
|
1601
|
+
{
|
|
1602
|
+
(void)wiringPiSetup () ;
|
|
1603
|
+
|
|
1604
|
+
if (wiringPiDebug)
|
|
1605
|
+
printf ("wiringPi: wiringPiSetupPhys called\n") ;
|
|
1606
|
+
|
|
1607
|
+
wiringPiMode = WPI_MODE_PHYS ;
|
|
1608
|
+
|
|
1609
|
+
return 0 ;
|
|
1610
|
+
}
|
|
1611
|
+
|
|
1612
|
+
|
|
1613
|
+
/*
|
|
1614
|
+
* wiringPiSetupSys:
|
|
1615
|
+
* Must be called once at the start of your program execution.
|
|
1616
|
+
*
|
|
1617
|
+
* Initialisation (again), however this time we are using the /sys/class/gpio
|
|
1618
|
+
* interface to the GPIO systems - slightly slower, but always usable as
|
|
1619
|
+
* a non-root user, assuming the devices are already exported and setup correctly.
|
|
1620
|
+
*/
|
|
1621
|
+
|
|
1622
|
+
int wiringPiSetupSys (void)
|
|
1623
|
+
{
|
|
1624
|
+
int boardRev ;
|
|
1625
|
+
int pin ;
|
|
1626
|
+
char fName [128] ;
|
|
1627
|
+
|
|
1628
|
+
if (getenv (ENV_DEBUG) != NULL)
|
|
1629
|
+
wiringPiDebug = TRUE ;
|
|
1630
|
+
|
|
1631
|
+
if (getenv (ENV_CODES) != NULL)
|
|
1632
|
+
wiringPiCodes = TRUE ;
|
|
1633
|
+
|
|
1634
|
+
if (wiringPiDebug)
|
|
1635
|
+
printf ("wiringPi: wiringPiSetupSys called\n") ;
|
|
1636
|
+
|
|
1637
|
+
boardRev = piBoardRev () ;
|
|
1638
|
+
|
|
1639
|
+
if (boardRev == 1)
|
|
1640
|
+
{
|
|
1641
|
+
pinToGpio = pinToGpioR1 ;
|
|
1642
|
+
physToGpio = physToGpioR1 ;
|
|
1643
|
+
}
|
|
1644
|
+
else
|
|
1645
|
+
{
|
|
1646
|
+
pinToGpio = pinToGpioR2 ;
|
|
1647
|
+
physToGpio = physToGpioR2 ;
|
|
1648
|
+
}
|
|
1649
|
+
|
|
1650
|
+
// Open and scan the directory, looking for exported GPIOs, and pre-open
|
|
1651
|
+
// the 'value' interface to speed things up for later
|
|
1652
|
+
|
|
1653
|
+
for (pin = 0 ; pin < 64 ; ++pin)
|
|
1654
|
+
{
|
|
1655
|
+
sprintf (fName, "/sys/class/gpio/gpio%d/value", pin) ;
|
|
1656
|
+
sysFds [pin] = open (fName, O_RDWR) ;
|
|
1657
|
+
}
|
|
1658
|
+
|
|
1659
|
+
initialiseEpoch () ;
|
|
1660
|
+
|
|
1661
|
+
wiringPiMode = WPI_MODE_GPIO_SYS ;
|
|
1662
|
+
|
|
1663
|
+
return 0 ;
|
|
1664
|
+
}
|