14 #define PAGE_SIZE (4*1024)
15 #define BLOCK_SIZE (4*1024)
17 /* Direct access to GPIO hardware */
19 // Access from ARM Running Linux
20 // For Raspberry Pi 2 and Pi 3, change BCM2708_PERI_BASE to 0x3F000000 for the code to work.
22 //#define BCM2708_PERI_BASE 0x20000000
23 #define BCM2708_PERI_BASE 0x3F000000
24 #define GPIO_BASE (BCM2708_PERI_BASE + 0x200000) /* GPIO controller */
28 volatile unsigned *gpio;
31 // GPIO setup macros. Always use INP_GPIO(x) before using OUT_GPIO(x) or SET_GPIO_ALT(x,y)
32 #define INP_GPIO(g) *(gpio+((g)/10)) &= ~(7<<(((g)%10)*3))
33 #define OUT_GPIO(g) *(gpio+((g)/10)) |= (1<<(((g)%10)*3))
34 #define SET_GPIO_ALT(g,a) *(gpio+(((g)/10))) |= (((a)<=3?(a)+4:(a)==4?3:2)<<(((g)%10)*3))
36 #define GPIO_SET *(gpio+7) // sets bits which are 1 ignores bits which are 0
37 #define GPIO_CLR *(gpio+10) // clears bits which are 1 ignores bits which are 0
39 #define GET_GPIO(g) (*(gpio+13)&(1<<g)) // 0 if LOW, (1<<g) if HIGH
41 #define GPIO_PULL *(gpio+37) // Pull up/pull down
42 #define GPIO_PULLCLK0 *(gpio+38) // Pull up/pull down clock
48 /* GPIO pin assignments */
51 #define OUTPUT_GREEN 14
52 #define OUTPUT_BLUE 15
53 #define OUTPUT_WHITE 4
55 const int N_COLORS = 4; // The number of LED colors
67 * We need to get the segment named
68 * SHM_KEY, created by the server.
73 * Create the shared memory segment if it does not exist yet.
75 if ((shmid = shmget(key, sizeof(struct pwm) * (N_COLORS + 1), 0666)) < 0)
78 if ((shmid = shmget(key, sizeof(struct pwm) * (N_COLORS + 1), IPC_CREAT | 0666)) < 0)
84 // Now we attach the new segment to our data space.
85 if ((shm = shmat(shmid, (const void *)NULL, 0)) == (void *) -1)
90 signals = (struct pwm *)shm;
91 signals[0].output = LED_RED;
92 signals[1].output = LED_GREEN;
93 signals[2].output = LED_BLUE;
94 signals[3].output = LED_WHITE;
98 // Now we attach the existing segment to our data space.
99 if ((shm = shmat(shmid, (const void *)NULL, 0)) == (void *) -1)
106 signals = (struct pwm *)shm;
108 // Set up gpi pointer for direct register access
111 INP_GPIO(OUTPUT_RED); // must use INP_GPIO before we can use OUT_GPIO
112 OUT_GPIO(OUTPUT_RED);
113 INP_GPIO(OUTPUT_GREEN); // must use INP_GPIO before we can use OUT_GPIO
114 OUT_GPIO(OUTPUT_GREEN);
115 INP_GPIO(OUTPUT_BLUE); // must use INP_GPIO before we can use OUT_GPIO
116 OUT_GPIO(OUTPUT_BLUE);
117 INP_GPIO(OUTPUT_WHITE); // must use INP_GPIO before we can use OUT_GPIO
118 OUT_GPIO(OUTPUT_WHITE);
123 fd[1] = OUTPUT_GREEN;
125 fd[3] = OUTPUT_WHITE;
132 if (signals->interval != 0)
134 usleep(signals->interval);
136 if (signals->output == -1)
138 /* End of the list: Turn all 4 outputs on */
139 GPIO_SET = 1 << fd[0];
140 GPIO_SET = 1 << fd[1];
141 GPIO_SET = 1 << fd[2];
142 GPIO_SET = 1 << fd[3];
144 signals = (struct pwm *)shm;
148 //write(fd[signals->output], "0", 1);
149 GPIO_CLR = 1 << fd[signals->output];
154 /* Turn all outputs off */
156 GPIO_CLR = 1 << fd[0];
157 GPIO_CLR = 1 << fd[1];
158 GPIO_CLR = 1 << fd[2];
159 GPIO_CLR = 1 << fd[3];
165 // Set up a memory regions to access GPIO
173 if ((mem_fd = open("/dev/mem", O_RDWR|O_SYNC) ) < 0)
175 printf("can't open /dev/mem \n");
181 NULL, //Any adddress in our space will do
182 BLOCK_SIZE, //Map length
183 PROT_READ|PROT_WRITE,// Enable reading & writting to mapped memory
184 MAP_SHARED, //Shared with other processes
185 mem_fd, //File to map
186 GPIO_BASE //Offset to GPIO peripheral
189 close(mem_fd); //No need to keep mem_fd open after mmap
191 if (gpio_map == MAP_FAILED)
193 printf("mmap error %d\n", gpio_map);//errno also set!
197 // Always use volatile pointer!
198 gpio = (volatile unsigned *)gpio_map;