3 * @purpose Implementation of BBB pin control functions and structures
4 * THIS CODE IS NOT THREADSAFE
16 * Structure to represent a GPIO pin
17 * Note: Only accessable to this file; to use the functions pass a GPIOId
26 * Structure to represent an ADC pin
27 * Note: Only accessable to this file; to use the functions pass a ADCId
35 * Structure to represent a PWM pin
36 * Note: Only accessable to this file; to use the functions pass a PWMId
46 /** Array of GPIO pins **/
47 static GPIO_Pin g_gpio[GPIO_NUM_PINS] = {{0}};
48 /** Array of ADC pins **/
49 static ADC_Pin g_adc[ADC_NUM_PINS] = {{0}};
50 /** Array of PWM pins **/
51 static PWM_Pin g_pwm[PWM_NUM_PINS] = {{0}};
53 static char g_buffer[BUFSIZ] = "";
55 #define GPIO_LUT_SIZE 93
56 #define GPIO_INDEX_SIZE 128
59 * A lookup table from header number to GPIO pin number.
60 * e.g P8_13 is g_gpio_lut[0*46+13] = g_gpio_lut[13]
61 * e.g P9_13 is g_gpio_lut[1*46+13] = g_gpio_lut[59]
63 * Where the returned value is 0, there is no GPIO pin
66 const unsigned char g_gpio_lut[GPIO_LUT_SIZE] = {
67 0, 0, 0, 0, 0, 0, 0, 66, 67, 69, 68, 45, 44, 23,
68 26, 47, 46, 27, 65, 22, 0, 0, 0, 0, 0, 0, 61, 86,
69 88, 87, 89, 10, 11, 9, 81, 8, 80, 78, 79, 76, 77, 74,
70 75, 72, 73, 70, 71, 0, 0, 0, 0, 0, 0, 0, 0, 0,
71 0, 30, 60, 31, 50, 48, 51, 5, 4, 0, 0, 3, 2, 49,
72 15, 117, 14, 115, 0, 0, 112, 0, 0, 0, 0, 0, 0, 0,
73 0, 0, 0, 0, 0, 0, 0, 0, 0
77 * Converts GPIO number to index into g_gpio, or 128 if no map.
79 const unsigned char g_gpio_index[GPIO_INDEX_SIZE] = {
80 128, 128, 0, 1, 2, 3, 128, 128, 4, 5, 6, 7, 128, 128,
81 8, 9, 128, 128, 128, 128, 128, 128, 10, 11, 128, 128, 12, 13,
82 128, 128, 14, 15, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
83 128, 128, 16, 17, 18, 19, 20, 21, 22, 23, 128, 128, 128, 128,
84 128, 128, 128, 128, 24, 25, 128, 128, 128, 26, 27, 28, 29, 30,
85 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 128, 128,
86 128, 128, 43, 44, 45, 46, 128, 128, 128, 128, 128, 128, 128, 128,
87 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
88 47, 128, 128, 48, 128, 49, 128, 128, 128, 128, 128, 128, 128, 128,
93 * Export a GPIO pin and open the file descriptors
95 void GPIO_Export(int pin)
97 if (pin < 0 || pin >= GPIO_INDEX_SIZE || g_gpio_index[pin] == 128)
99 Abort("Not a useable pin (number %d)", pin);
103 sprintf(g_buffer, "%s/export", GPIO_DEVICE_PATH);
104 FILE * export = fopen(g_buffer, "w");
107 Abort("Couldn't open %s to export GPIO pin %d - %s", g_buffer, pin, strerror(errno));
110 fprintf(export, "%d", pin);
113 GPIO_Pin *gpio = &g_gpio[g_gpio_index[pin]];
114 // Setup direction file descriptor
115 sprintf(g_buffer, "%s/gpio%d/direction", GPIO_DEVICE_PATH, pin);
116 gpio->fd_direction = open(g_buffer, O_RDWR);
117 if (gpio->fd_direction < 0)
119 Abort("Couldn't open %s for GPIO pin %d - %s", g_buffer, pin, strerror(errno));
123 // Setup value file descriptor
124 sprintf(g_buffer, "%s/gpio%d/value", GPIO_DEVICE_PATH, pin);
125 gpio->fd_value = open(g_buffer, O_RDWR);
126 if (gpio->fd_value < 0)
128 Abort("Couldn't open %s for GPIO pin %d - %s", g_buffer, pin, strerror(errno));
131 Log(LOGDEBUG, "Exported GPIO%d", pin);
136 * Unexport a GPIO pin and close its' file descriptors
138 void GPIO_Unexport(int pin)
141 if (pin < 0 || pin >= GPIO_INDEX_SIZE || g_gpio_index[pin] == 128)
143 Abort("Not a useable pin (number %d)", pin);
146 GPIO_Pin *gpio = &g_gpio[g_gpio_index[pin]];
147 // Close file descriptors
148 close(gpio->fd_value);
149 close(gpio->fd_direction);
153 if (g_buffer[0] == '\0')
154 sprintf(g_buffer, "%s/unexport", GPIO_DEVICE_PATH);
155 FILE * export = fopen(g_buffer, "w");
158 Abort("Couldn't open %s to export GPIO pin %d - %s", g_buffer, pin, strerror(errno));
161 fprintf(export, "%d", pin);
169 * Export all PWM pins and open file descriptors
170 * @param pin - The pin number
172 void PWM_Export(int pin)
174 if (pin < 0 || pin > PWM_NUM_PINS)
176 Abort("Invalid pin number %d", pin);
180 sprintf(g_buffer, "%s/export", PWM_DEVICE_PATH);
181 FILE * export = fopen(g_buffer, "w");
184 Abort("Couldn't open %s to export PWM pin %d - %s", g_buffer, pin, strerror(errno));
187 fprintf(export, "%d\n", pin);
190 // Open file descriptors
191 sprintf(g_buffer, "%s/pwm%d/run", PWM_DEVICE_PATH, pin);
192 g_pwm[pin].fd_run = open(g_buffer, O_WRONLY);
193 if (g_pwm[pin].fd_run < 0)
195 Abort("Couldn't open %s for PWM pin %d - %s", g_buffer, pin, strerror(errno));
198 sprintf(g_buffer, "%s/pwm%d/polarity",PWM_DEVICE_PATH, pin);
199 g_pwm[pin].fd_polarity = open(g_buffer, O_WRONLY);
200 if (g_pwm[pin].fd_polarity < 0)
202 Abort("Couldn't open %s for PWM pin %d - %s", g_buffer, pin, strerror(errno));
205 sprintf(g_buffer, "%s/pwm%d/period_ns",PWM_DEVICE_PATH, pin);
206 g_pwm[pin].file_period = fopen(g_buffer, "w");
207 if (g_pwm[pin].file_period == NULL)
209 Abort("Couldn't open %s for PWM pin %d - %s", g_buffer, pin, strerror(errno));
212 sprintf(g_buffer, "%s/pwm%d/duty_ns",PWM_DEVICE_PATH, pin);
213 g_pwm[pin].file_duty = fopen(g_buffer, "w");
214 if (g_pwm[pin].file_duty == NULL)
216 Abort("Couldn't open %s for PWM pin %d - %s", g_buffer, pin, strerror(errno));
219 // Don't buffer the streams
220 setbuf(g_pwm[pin].file_period, NULL);
221 setbuf(g_pwm[pin].file_duty, NULL);
227 * Unexport a PWM pin and close its file descriptors
228 * @param pin - The pin number
230 void PWM_Unexport(int pin)
232 if (pin < 0 || pin > PWM_NUM_PINS)
234 Abort("Invalid pin number %d", pin);
237 // Close the file descriptors
238 close(g_pwm[pin].fd_polarity);
239 close(g_pwm[pin].fd_run);
240 fclose(g_pwm[pin].file_period);
241 fclose(g_pwm[pin].file_duty);
244 sprintf(g_buffer, "%s/unexport", PWM_DEVICE_PATH);
245 FILE * export = fopen(g_buffer, "w");
248 Abort("Couldn't open %s to unexport PWM pin %d - %s", g_buffer, pin, strerror(errno));
251 fprintf(export, "%d", pin);
256 * Export ADC pins; http://beaglebone.cameon.net/home/reading-the-analog-inputs-adc
257 * Can't use sysfs like GPIO or PWM pins
258 * Bloody annoying how inconsistent stuff is on the Beaglebone
262 for (int i = 0; i < ADC_NUM_PINS; ++i)
264 sprintf(g_buffer, "%s/AIN%d", g_options.adc_device_path, i);
265 g_adc[i].fd_value = open(g_buffer, O_RDONLY);
266 if (g_adc[i].fd_value < 0)
268 Abort("Couldn't open ADC %d device file %s - %s", i, g_buffer, strerror(errno));
271 //setbuf(g_adc[i].file_value, NULL);
281 for (int i = 0; i < ADC_NUM_PINS; ++i)
282 close(g_adc[i].fd_value);
287 * @param pin - The pin to set. MUST have been exported before calling this function.
289 void GPIO_Set(int pin, bool value)
291 if (pin < 0 || pin >= GPIO_INDEX_SIZE || g_gpio_index[pin] == 128)
293 Abort("Not a useable pin (number %d)", pin);
296 GPIO_Pin *gpio = &g_gpio[g_gpio_index[pin]];
297 if (pwrite(gpio->fd_direction, "out", 3, 0) != 3)
299 Abort("Couldn't set GPIO %d direction - %s", pin, strerror(errno));
302 char c = '0' + (value);
303 if (pwrite(gpio->fd_value, &c, 1, 0) != 1)
305 Abort("Couldn't read GPIO %d value - %s", pin, strerror(errno));
311 * Read from a GPIO Pin
312 * @param pin - The pin to read
314 bool GPIO_Read(int pin)
316 if (pin < 0 || pin >= GPIO_INDEX_SIZE || g_gpio_index[pin] == 128)
318 Log(LOGERR, "Not a useable pin (number %d)", pin);
322 GPIO_Pin *gpio = &g_gpio[g_gpio_index[pin]];
323 if (pwrite(gpio->fd_direction, "in", 2, 0) != 2)
324 Log(LOGERR,"Couldn't set GPIO %d direction - %s", pin, strerror(errno));
326 if (pread(gpio->fd_value, &c, 1, 0) != 1)
327 Log(LOGERR,"Couldn't read GPIO %d value - %s", pin, strerror(errno));
335 * @param pin - The pin to activate
336 * @param polarity - if true, pin is active high, else active low
337 * @param period - The period in ns
338 * @param duty - The time the pin is active in ns
340 void PWM_Set(int pin, bool polarity, long period, long duty)
342 Log(LOGDEBUG, "Pin %d, pol %d, period: %lu, duty: %lu", pin, polarity, period, duty);
344 rewind(g_pwm[pin].file_duty);
346 if (fprintf(g_pwm[pin].file_duty, "0") == 0)
348 Abort("Couldn't zero the duty cycle for PWM %d - s", pin, strerror(errno));
351 // Have to stop PWM before changing it
352 if (pwrite(g_pwm[pin].fd_run, "0", 1, 0) != 1)
354 Abort("Couldn't stop PWM %d - %s", pin, strerror(errno));
357 char c = '0' + polarity;
358 if (pwrite(g_pwm[pin].fd_polarity, &c, 1, 0) != 1)
360 Abort("Couldn't set PWM %d polarity - %s", pin, strerror(errno));
363 rewind(g_pwm[pin].file_period);
364 rewind(g_pwm[pin].file_duty);
365 if (fprintf(g_pwm[pin].file_period, "%lu", period) == 0)
367 Abort("Couldn't set period for PWM %d - %s", pin, strerror(errno));
370 if (fprintf(g_pwm[pin].file_duty, "%lu", duty) == 0)
372 Abort("Couldn't set duty cycle for PWM %d - %s", pin, strerror(errno));
375 if (pwrite(g_pwm[pin].fd_run, "1", 1, 0) != 1)
377 Abort("Couldn't start PWM %d - %s", pin, strerror(errno));
383 * Deactivate a PWM pin
384 * @param pin - The pin to turn off
386 void PWM_Stop(int pin)
388 if (pwrite(g_pwm[pin].fd_run, "0", 1, 0) != 1)
390 Abort("Couldn't stop PWM %d - %s", pin, strerror(errno));
396 * @param id - The ID of the ADC pin to read
397 * @returns - The reading of the ADC channel
401 char adc_str[ADC_DIGITS] = "";
402 lseek(g_adc[id].fd_value, 0, SEEK_SET);
405 for (i = 0; i < ADC_DIGITS-1; ++i)
407 if (read(g_adc[id].fd_value, adc_str+i, 1) != 1)
409 if (adc_str[i] == '\n')
417 int val = strtol(adc_str, &end, 10);
420 Log(LOGERR, "Read non integer from ADC %d - %s", id, adc_str);