924b27efafd3759627b10d8fc486092d42c83bee
[heating.git] / usr / lib / cgi-bin / 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       0x20000000
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 = 200000;
19 const unsigned long SPACE = 200000;
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     if (argc < 2)
81     {
82         puts ("gpio <pin> 0|1");
83         return 0;
84     }
85
86     int g = atoi (argv[1]);
87
88     setup_io();
89
90     if (argv[2][0] == '1')
91     {
92         GPIO_SET = 1<<g;
93         printf ("HIGH %d\n", g);
94     }
95     else if (argv[2][0] == '0')
96     {
97         GPIO_CLR = 1<<g;
98         printf ("LOW %d\n", g);
99     }
100     else
101     {
102         printf ("argv[2]=%s ...?\n", argv[2]);
103     }
104
105     OUT_GPIO(g);
106
107     return 0;
108 }