From 6982a9002923c2297cd2e2e1ec10ccb331b01eb5 Mon Sep 17 00:00:00 2001 From: Jeremy Tan Date: Fri, 27 Sep 2013 16:58:37 +0800 Subject: [PATCH] Small fixes + add ability to un/export pins from pin_test --- server/bbb_pin.c | 38 ++++++++++---- server/bbb_pin.h | 7 +-- server/bbb_pin_defines.c | 4 +- server/bbb_pin_defines.h | 8 +-- server/pin_test.c | 108 ++++++++++++++++++++++++++++----------- 5 files changed, 116 insertions(+), 49 deletions(-) diff --git a/server/bbb_pin.c b/server/bbb_pin.c index f351f53..a652b97 100644 --- a/server/bbb_pin.c +++ b/server/bbb_pin.c @@ -10,7 +10,6 @@ #include #include #include -#include #include "options.h" /** @@ -109,6 +108,7 @@ bool GPIO_Export(int pin) /** * Unexport a GPIO pin and close its' file descriptors + * @param pin The GPIO number to be unexported */ void GPIO_Unexport(int pin) { @@ -349,13 +349,21 @@ bool GPIO_Read(int pin, bool *result) } GPIO_Pin *gpio = &g_gpio[g_pin_gpio_to_index[pin]]; + if (!gpio->initialised) + { + AbortBool("GPIO %d is not initialised.", pin); + } if (pwrite(gpio->fd_direction, "in", 2, 0) != 2) - AbortBool("Couldn't set GPIO %d direction - %s", pin, strerror(errno)); + { + AbortBool("Couldn't set GPIO %d direction - %s", pin, strerror(errno)); + } char c = '0'; if (pread(gpio->fd_value, &c, 1, 0) != 1) + { AbortBool("Couldn't read GPIO %d value - %s", pin, strerror(errno)); + } *result = (c == '1'); return true; @@ -386,36 +394,36 @@ bool PWM_Set(int pin, bool polarity, long period, long duty) // Have to stop PWM before changing it if (pwrite(pwm->fd_run, "0", 1, 0) != 1) { - AbortBool("Couldn't stop PWM%d - %s", pin, strerror(errno)); + AbortBool("Couldn't stop PWM %d - %s", pin, strerror(errno)); } char c = polarity ? '1' : '0'; if (pwrite(pwm->fd_polarity, &c, 1, 0) != 1) { - AbortBool("Couldn't set PWM%d polarity - %s", pin, strerror(errno)); + AbortBool("Couldn't set PWM %d polarity - %s", pin, strerror(errno)); } //This must be done first, otherwise period/duty settings can conflict if (fwrite("0", 1, 1, pwm->file_duty) < 1) { - AbortBool("Couldn't zero the duty for PWM%d - %s", pin, strerror(errno)); + AbortBool("Couldn't zero the duty for PWM %d - %s", pin, strerror(errno)); } if (fprintf(pwm->file_period, "%lu", period) < 0) { - AbortBool("Couldn't set period for PWM%d - %s", pin, strerror(errno)); + AbortBool("Couldn't set period for PWM %d - %s", pin, strerror(errno)); } if (fprintf(pwm->file_duty, "%lu", duty) < 0) { - AbortBool("Couldn't set duty cycle for PWM%d - %s", pin, strerror(errno)); + AbortBool("Couldn't set duty cycle for PWM %d - %s", pin, strerror(errno)); } if (pwrite(pwm->fd_run, "1", 1, 0) != 1) { - AbortBool("Couldn't start PWM%d - %s", pin, strerror(errno)); + AbortBool("Couldn't start PWM %d - %s", pin, strerror(errno)); } return true; @@ -424,18 +432,25 @@ bool PWM_Set(int pin, bool polarity, long period, long duty) /** * Deactivate a PWM pin * @param pin - The syfs pin number + * @return true on success, false otherwise */ -void PWM_Stop(int pin) +bool PWM_Stop(int pin) { if (pin < 0 || pin >= PWM_NUM_PINS) { - Abort("Invalid PWM pin number %d specified.", pin); + AbortBool("Invalid PWM pin number %d specified.", pin); + } + else if (!g_pwm[pin].initialised) + { + AbortBool("PWM %d is not initialised.", pin); } if (pwrite(g_pwm[pin].fd_run, "0", 1, 0) != 1) { - Abort("Couldn't stop PWM %d - %s", pin, strerror(errno)); + AbortBool("Couldn't stop PWM %d - %s", pin, strerror(errno)); } + + return true; } /** @@ -461,6 +476,7 @@ bool ADC_Read(int id, int *value) { AbortBool("ADC %d read failed: %s", id, strerror(errno)); } + *value = strtol(adc_str, NULL, 10); return true; } \ No newline at end of file diff --git a/server/bbb_pin.h b/server/bbb_pin.h index 0b5f345..9eb011e 100644 --- a/server/bbb_pin.h +++ b/server/bbb_pin.h @@ -28,10 +28,10 @@ extern bool GPIO_Set(int pin, bool value); extern bool ADC_Read(int id, int *value); extern bool PWM_Set(int pin, bool polarity, long period, long duty); // period and duty are in ns -extern void PWM_Stop(int pin); +extern bool PWM_Stop(int pin); #else -//Empty defines so it compiles on any platform that's not the BBB +//'Empty' defines so it compiles on any platform that's not the BBB extern bool GPIO_Export(int pin); extern void GPIO_Unexport(int pin); @@ -45,13 +45,14 @@ extern void GPIO_Unexport(int pin); #define ADC_Export(pin) true #define ADC_Unexport(pin) +//Hack to both zero the result field (so it's never uninitialised) and return true #define GPIO_Read(pin, result) ((*(result) = 0) == 0) #define GPIO_Set(pin, value) true #define ADC_Read(id, value) ((*(value) = 0) == 0) #define PWM_Set(pin, polarity, period, duty) true -#define PWM_Stop(pin) +#define PWM_Stop(pin) true #endif //_BBB diff --git a/server/bbb_pin_defines.c b/server/bbb_pin_defines.c index df5b5c0..23e03c5 100644 --- a/server/bbb_pin_defines.c +++ b/server/bbb_pin_defines.c @@ -1,5 +1,7 @@ #include "bbb_pin_defines.h" +/* Luts and stuff. Yay magic numbers **/ + /** * A lookup table from the actual pin number to GPIO number. * e.g P8_13 is g_pin_real_to_gpio[0*46+13] = g_pin_real_to_gpio[13] @@ -50,4 +52,4 @@ const unsigned char g_pin_index_to_gpio[GPIO_NUM_PINS] = { */ const unsigned char g_pin_safe_pwm[PWM_NUM_SAFE_PINS] = { 0, 2, 4, 6, 7 -}; \ No newline at end of file +}; //blergh \ No newline at end of file diff --git a/server/bbb_pin_defines.h b/server/bbb_pin_defines.h index a7aa932..ea7de7e 100644 --- a/server/bbb_pin_defines.h +++ b/server/bbb_pin_defines.h @@ -114,19 +114,19 @@ #define GPIO2_31 95 #define GPIO2_32 96 -/* Luts */ +/** Export path **/ +#define GPIO_DEVICE_PATH "/sys/class/gpio" + /** Number of useable GPIO pins **/ #define GPIO_NUM_PINS 44 /** The max usable GPIO number **/ #define GPIO_MAX_NUMBER 117 +/* Luts */ extern const unsigned char g_pin_real_to_gpio[BBB_PIN_COUNT+1]; extern const unsigned char g_pin_gpio_to_index[GPIO_MAX_NUMBER+1]; extern const unsigned char g_pin_index_to_gpio[GPIO_NUM_PINS]; -/** Export path **/ -#define GPIO_DEVICE_PATH "/sys/class/gpio" - #define ADC_BITS 12 #define ADC_DIGITS 5 #define ADC0 0 diff --git a/server/pin_test.c b/server/pin_test.c index 2db079d..90ae626 100644 --- a/server/pin_test.c +++ b/server/pin_test.c @@ -12,16 +12,7 @@ */ void Pin_Init() { - //Don't export anything; make the user do it. - /*for (int i = 0; i < GPIO_NUM_PINS; ++i) - GPIO_Export(g_index_to_gpio[i]); - - for (int i = 0; i < ADC_NUM_PINS; ++i) - ADC_Export(i); - - //Only export 'safe' PWM pins that don't interfere with one another - for (int i = 0; i < PWM_NUM_SAFE_PINS; ++i) - PWM_Export(g_pin_safe_pwm[i]);*/ + } /** @@ -39,6 +30,34 @@ void Pin_Close() PWM_Unexport(g_pin_safe_pwm[i]); } +bool Pin_Configure(const char *type, int pin_export, int num) +{ + bool ret = true; + + if (strcmp(type, "gpo") == 0 || strcmp(type, "gpi") == 0) + { + if (pin_export < 0) + GPIO_Unexport(num); + else + ret = GPIO_Export(num); + } + else if (strcmp(type, "pwm") == 0) + { + if (pin_export < 0) + PWM_Unexport(num); + else + ret = PWM_Export(num); + } + else if (strcmp(type, "adc") == 0) + { + if (pin_export < 0) + ADC_Unexport(num); + else + ret = ADC_Export(num); + } + return ret; +} + /** * Handle a request to the Pin test module * @param context - The FastCGI context @@ -47,9 +66,10 @@ void Pin_Close() void Pin_Handler(FCGIContext *context, char * params) { - char * type = NULL; + const char * type = NULL; int num = 0; - bool set = true; + int pin_export = 0; + bool set = false; bool pol = false; double freq = 50; double duty = 0.5; @@ -59,6 +79,7 @@ void Pin_Handler(FCGIContext *context, char * params) FCGIValue values[] = { {"type", &type, FCGI_REQUIRED(FCGI_STRING_T)}, {"num", &num, FCGI_REQUIRED(FCGI_INT_T)}, + {"export", &pin_export, FCGI_INT_T}, {"set", &set, FCGI_BOOL_T}, {"pol", &pol, FCGI_BOOL_T}, {"freq", &freq, FCGI_DOUBLE_T}, @@ -69,6 +90,7 @@ void Pin_Handler(FCGIContext *context, char * params) typedef enum { TYPE, NUM, + EXPORT, SET, POL, FREQ, @@ -82,7 +104,19 @@ void Pin_Handler(FCGIContext *context, char * params) return; } - Log(LOGDEBUG, "Params: type = %s, num = %d, set = %d, pol = %d, freq = %f, duty = %f", type, num, set, pol, freq, duty); + Log(LOGDEBUG, "Params: type = %s, num = %d, export = %d, set = %d, pol = %d, freq = %f, duty = %f", type, num, pin_export, set, pol, freq, duty); + if (pin_export != 0) + { + if (!Pin_Configure(type, pin_export, num)) + { + FCGI_RejectJSON(context, "Failed to (un)export the pin. Check that a valid number has been specified."); + return; + } + FCGI_BeginJSON(context, STATUS_OK); + FCGI_JSONPair("description", "Pin (un)export OK!"); + FCGI_EndJSON(); + return; + } if (strcmp(type, "gpo") == 0) { @@ -93,10 +127,15 @@ void Pin_Handler(FCGIContext *context, char * params) } Log(LOGDEBUG, "Setting GPIO%d to %d", num, set); - GPIO_Set(num, set); - - FCGI_PrintRaw("Content-type: text/plain\r\n\r\n"); - FCGI_PrintRaw("GPIO%d set to %d\n", num, set); + if (!GPIO_Set(num, set)) + { + FCGI_RejectJSON(context, "Failed to set the GPIO pin. Check that it's exported."); + } + else + { + FCGI_PrintRaw("Content-type: text/plain\r\n\r\n"); + FCGI_PrintRaw("GPIO%d set to %d\n", num, set); + } } else if (strcmp(type, "gpi") == 0) { @@ -106,13 +145,16 @@ void Pin_Handler(FCGIContext *context, char * params) return; } Log(LOGDEBUG, "Reading GPIO%d", num); - FCGI_PrintRaw("Content-type: text/plain\r\n\r\n"); - bool ret; - if (!GPIO_Read(num, &ret)) - FCGI_PrintRaw("GPIO%d read failed. Is it exported?", num); + bool val; + if (!GPIO_Read(num, &val)) + { + FCGI_RejectJSON(context, "Failed to read from the GPIO pin. Check that it's exported."); + } else - FCGI_PrintRaw("GPIO%d reads %d\n", num, ret); - + { + FCGI_PrintRaw("Content-type: text/plain\r\n\r\n"); + FCGI_PrintRaw("GPIO%d reads %d\n", num, val); + } } else if (strcmp(type, "adc") == 0) { @@ -122,14 +164,14 @@ void Pin_Handler(FCGIContext *context, char * params) return; } Log(LOGDEBUG, "Reading ADC%d", num, set); - FCGI_PrintRaw("Content-type: text/plain\r\n\r\n"); int raw_adc; if (!ADC_Read(num, &raw_adc)) { - FCGI_PrintRaw("ADC%d read failed. Is it initialised?", num); + FCGI_RejectJSON(context, "ADC read failed. Check that it's exported."); } else { + FCGI_PrintRaw("Content-type: text/plain\r\n\r\n"); FCGI_PrintRaw("ADC%d reads %d\n", num, raw_adc); } } @@ -140,8 +182,6 @@ void Pin_Handler(FCGIContext *context, char * params) FCGI_RejectJSON(context, "Invalid PWM pin"); return; } - - FCGI_PrintRaw("Content-type: text/plain\r\n\r\n"); if (set) { @@ -149,14 +189,22 @@ void Pin_Handler(FCGIContext *context, char * params) duty = duty < 0 ? 0 : duty > 1 ? 1 : duty; long period_ns = (long)(1e9 / freq); long duty_ns = (long)(duty * period_ns); - PWM_Set(g_pin_safe_pwm[num], pol, period_ns, duty_ns); - FCGI_PrintRaw("PWM%d set to period_ns = %lu (%f Hz), duty_ns = %lu (%f), polarity = %d", - num, period_ns, freq, duty_ns, duty*100, (int)pol); + if (!PWM_Set(num, pol, period_ns, duty_ns)) + { + FCGI_RejectJSON(context, "PWM set failed. Check if it's exported, and that there's no channel conflict."); + } + else + { + FCGI_PrintRaw("Content-type: text/plain\r\n\r\n"); + FCGI_PrintRaw("PWM%d set to period_ns = %lu (%f Hz), duty_ns = %lu (%f), polarity = %d", + num, period_ns, freq, duty_ns, duty*100, (int)pol); + } } else { Log(LOGDEBUG, "Stopping PWM%d",num); PWM_Stop(g_pin_safe_pwm[num]); + FCGI_PrintRaw("Content-type: text/plain\r\n\r\n"); FCGI_PrintRaw("PWM%d stopped",num); } } -- 2.20.1