Experimenting
[gpio.git] / gpio.c
1 // Originally from http://elinux.org/RPi_Low-level_peripherals#C
2
3 #include <stdio.h>
4 #include <stdlib.h>
5 #include <fcntl.h>
6 #include <sys/mman.h>
7 #include <unistd.h>
8
9 #define BCM2708_PERI_BASE       0x3F000000
10 const unsigned int GPIO_BASE  = BCM2708_PERI_BASE + 0x200000; /* GPIO controller */
11
12 const unsigned short PAGE_SIZE = 4*1024;
13 const unsigned short BLOCK_SIZE = 4*1024;
14
15 const unsigned long REPEAT = 1000;
16 const unsigned long DELAY = 1000;
17
18 const unsigned long MARK = 100000;
19 const unsigned long SPACE = 100000;
20
21 int  mem_fd;
22 void *gpio_map;
23
24 volatile unsigned *gpio;
25
26 // GPIO setup macros. Always use INP_GPIO(x) before using OUT_GPIO(x) or SET_GPIO_ALT(x,y)
27 #define INP_GPIO(g) *(gpio+((g)/10)) &= ~(7<<(((g)%10)*3))
28 #define OUT_GPIO(g) *(gpio+((g)/10)) |=  (1<<(((g)%10)*3))
29 #define SET_GPIO_ALT(g,a) *(gpio+(((g)/10))) |= (((a)<=3?(a)+4:(a)==4?3:2)<<(((g)%10)*3))
30
31 #define GPIO_SET *(gpio+7)  // sets   bits which are 1 ignores bits which are 0
32 #define GPIO_CLR *(gpio+10) // clears bits which are 1 ignores bits which are 0
33
34 #define GET_GPIO(g) (*(gpio+13)&(1<<g)) // 0 if LOW, (1<<g) if HIGH
35
36 #define GPIO_PULL *(gpio+37) // Pull up/pull down
37 #define GPIO_PULLCLK0 *(gpio+38) // Pull up/pull down clock
38
39 //
40 // Set up a memory regions to access GPIO
41 //
42 void setup_io()
43 {
44     if ((mem_fd = open("/dev/mem", O_RDWR|O_SYNC) ) < 0)
45     {
46             printf("can't open /dev/mem (sudo?)\n");
47             exit(-1);
48     }
49
50     gpio_map = mmap(
51                        NULL,             //Any adddress in our space will do
52                        BLOCK_SIZE,       //Map length
53                        PROT_READ|PROT_WRITE,// Enable reading & writting to mapped memory
54                        MAP_SHARED,       //Shared with other processes
55                        mem_fd,           //File to map
56                        GPIO_BASE         //Offset to GPIO peripheral
57                    );
58
59     close(mem_fd); //No need to keep mem_fd open after mmap
60
61     if (gpio_map == MAP_FAILED)
62     {
63             printf("mmap error %d\n", (int)gpio_map);//errno also set!
64             exit(-1);
65     }
66
67     gpio = (volatile unsigned *)gpio_map;
68 }
69
70 void printButton(int g)
71 {
72     if (GET_GPIO(g)) // !=0 <-> bit is 1 <- port is HIGH=3.3V
73         printf("Button pressed!\n");
74     else // port is LOW=0V
75         printf("Button released!\n");
76 }
77
78 int main(int argc, char **argv)
79 {
80     int rep;
81     int g;
82
83     setup_io();
84 #if 0
85     for (rep=0; rep<REPEAT; rep++)
86     {
87        g=23;
88
89        printf ("OFF %d\n", g);
90        INP_GPIO(g);
91        usleep(DELAY);
92
93        GPIO_SET = 1<<g;
94        printf ("HIGH %d\n", g);
95
96        OUT_GPIO(g);
97        usleep(DELAY);
98
99        printf ("OFF %d\n", g);
100        INP_GPIO(g);
101        usleep(DELAY);
102
103        GPIO_SET = 1<<g;
104        printf ("HIGH %d\n", g);
105
106        OUT_GPIO(g);
107        usleep(DELAY);
108
109        printf ("OFF %d\n", g);
110        INP_GPIO(g);
111        usleep(DELAY);
112
113        GPIO_CLR = 1<<g;
114        printf ("LOW %d\n", g);
115
116        OUT_GPIO(g);
117        usleep(DELAY);
118
119        printf ("OFF %d\n", g);
120        INP_GPIO(g);
121        usleep(DELAY);
122
123        GPIO_CLR = 1<<g;
124        printf ("LOW %d\n", g);
125
126        OUT_GPIO(g);
127        usleep(DELAY);
128     }
129 #else
130     for (;;)
131     {
132             g=23;
133
134             printf ("OFF %d\n", g);
135             INP_GPIO(g);
136             usleep(SPACE);
137
138             GPIO_SET = 1<<g;
139             printf ("HIGH %d\n", g);
140
141             OUT_GPIO(g);
142             usleep(MARK);
143     }
144 #endif
145     printf ("OFF %d\n", g);
146     INP_GPIO(g);
147
148     return 0;
149 }