From ead840a6e5b98790edb419bde8a02e476b443dc4 Mon Sep 17 00:00:00 2001 From: Jeremy Tan Date: Thu, 26 Sep 2013 23:06:29 +0800 Subject: [PATCH] semifix. PWM stuff mostly works. ADC should work. CLEANUP NECESSARY --- server/actuator.c | 1 - server/bbb_pin.c | 204 ++++++++++++++++++--------------------- server/bbb_pin.h | 4 +- server/bbb_pin_defines.c | 8 ++ server/bbb_pin_defines.h | 27 ++++-- server/options.h | 2 +- server/pin_test.c | 13 +-- server/run.sh | Bin 1510 -> 2275 bytes 8 files changed, 131 insertions(+), 128 deletions(-) diff --git a/server/actuator.c b/server/actuator.c index 40f9b46..f5d7cd6 100644 --- a/server/actuator.c +++ b/server/actuator.c @@ -32,7 +32,6 @@ void Actuator_Init() // Initialise pins used GPIO_Export(GPIO1_16); PWM_Export(EHRPWM0A); - PWM_Export(EHRPWM0B); } diff --git a/server/bbb_pin.c b/server/bbb_pin.c index 5ab14e9..373bbac 100644 --- a/server/bbb_pin.c +++ b/server/bbb_pin.c @@ -126,123 +126,122 @@ void GPIO_Unexport(int pin) } - - /** - * Export all PWM pins and open file descriptors - * @param pin - The pin number + * Initialise all PWM pins and open file descriptors + * @param pin - The sysfs pin number */ void PWM_Export(int pin) { - if (pin < 0 || pin > PWM_NUM_PINS) + if (pin < 0 || pin >= PWM_NUM_PINS) { - Abort("Invalid pin number %d", pin); + Abort("Invalid PWM pin number %d specified.", pin); } - - // Export the pin - sprintf(g_buffer, "%s/export", PWM_DEVICE_PATH); - FILE * export = fopen(g_buffer, "w"); - if (export == NULL) + + PWM_Pin *pwm = &g_pwm[pin]; + + if (pwm->file_duty != NULL) { - Abort("Couldn't open %s to export PWM pin %d - %s", g_buffer, pin, strerror(errno)); + Abort("PWM %d already exported.", pin); } - - fprintf(export, "%d\n", pin); - fclose(export); // Open file descriptors sprintf(g_buffer, "%s/pwm%d/run", PWM_DEVICE_PATH, pin); - g_pwm[pin].fd_run = open(g_buffer, O_WRONLY); - if (g_pwm[pin].fd_run < 0) + pwm->fd_run = open(g_buffer, O_WRONLY); + if (pwm->fd_run < 0) { - Abort("Couldn't open %s for PWM pin %d - %s", g_buffer, pin, strerror(errno)); + Abort("Couldn't open %s for PWM%d - %s", g_buffer, pin, strerror(errno)); } - sprintf(g_buffer, "%s/pwm%d/polarity",PWM_DEVICE_PATH, pin); - g_pwm[pin].fd_polarity = open(g_buffer, O_WRONLY); - if (g_pwm[pin].fd_polarity < 0) + sprintf(g_buffer, "%s/pwm%d/polarity", PWM_DEVICE_PATH, pin); + pwm->fd_polarity = open(g_buffer, O_WRONLY); + if (pwm->fd_polarity < 0) { - Abort("Couldn't open %s for PWM pin %d - %s", g_buffer, pin, strerror(errno)); + Abort("Couldn't open %s for PWM%d - %s", g_buffer, pin, strerror(errno)); } - sprintf(g_buffer, "%s/pwm%d/period_ns",PWM_DEVICE_PATH, pin); - g_pwm[pin].file_period = fopen(g_buffer, "w"); - if (g_pwm[pin].file_period == NULL) + sprintf(g_buffer, "%s/pwm%d/period_ns", PWM_DEVICE_PATH, pin); + pwm->file_period = fopen(g_buffer, "w"); + if (pwm->file_period == NULL) { - Abort("Couldn't open %s for PWM pin %d - %s", g_buffer, pin, strerror(errno)); + Abort("Couldn't open %s for PWM%d - %s", g_buffer, pin, strerror(errno)); } - sprintf(g_buffer, "%s/pwm%d/duty_ns",PWM_DEVICE_PATH, pin); - g_pwm[pin].file_duty = fopen(g_buffer, "w"); - if (g_pwm[pin].file_duty == NULL) + sprintf(g_buffer, "%s/pwm%d/duty_ns", PWM_DEVICE_PATH, pin); + pwm->file_duty = fopen(g_buffer, "w"); + if (pwm->file_duty == NULL) { - Abort("Couldn't open %s for PWM pin %d - %s", g_buffer, pin, strerror(errno)); + Abort("Couldn't open %s for PWM%d - %s", g_buffer, pin, strerror(errno)); } // Don't buffer the streams - setbuf(g_pwm[pin].file_period, NULL); - setbuf(g_pwm[pin].file_duty, NULL); + setbuf(pwm->file_period, NULL); + setbuf(pwm->file_duty, NULL); - + Log(LOGDEBUG, "Exported PWM%d", pin); } /** * Unexport a PWM pin and close its file descriptors - * @param pin - The pin number + * @param pin - The sysfs pin number */ void PWM_Unexport(int pin) { - if (pin < 0 || pin > PWM_NUM_PINS) + if (pin < 0 || pin >= PWM_NUM_PINS) { - Abort("Invalid pin number %d", pin); + Abort("Invalid PWM pin number %d specified.", pin); } + PWM_Pin *pwm = &g_pwm[pin]; // Close the file descriptors - close(g_pwm[pin].fd_polarity); - close(g_pwm[pin].fd_run); - fclose(g_pwm[pin].file_period); - fclose(g_pwm[pin].file_duty); - - //Unexport the pin - sprintf(g_buffer, "%s/unexport", PWM_DEVICE_PATH); - FILE * export = fopen(g_buffer, "w"); - if (export == NULL) - { - Abort("Couldn't open %s to unexport PWM pin %d - %s", g_buffer, pin, strerror(errno)); - } - - fprintf(export, "%d", pin); - fclose(export); + if (pwm->fd_polarity != -1) + close(pwm->fd_polarity); + if (pwm->fd_run != -1) + close(pwm->fd_run); + if (pwm->file_period != NULL) + fclose(pwm->file_period); + if (pwm->file_duty != NULL) + fclose(pwm->file_duty); + + //So that another call to PWM_Unexport is OK. + pwm->fd_polarity = pwm->fd_run = -1; + pwm->file_period = pwm->file_duty = NULL; } + /** - * Export ADC pins; http://beaglebone.cameon.net/home/reading-the-analog-inputs-adc - * Can't use sysfs like GPIO or PWM pins - * Bloody annoying how inconsistent stuff is on the Beaglebone + * Initialise ADC structures + * @param pin The ADC pin number */ -void ADC_Export() +void ADC_Export(int pin) { - for (int i = 0; i < ADC_NUM_PINS; ++i) + if (pin < 0 || pin >= ADC_NUM_PINS) { - sprintf(g_buffer, "%s/AIN%d", g_options.adc_device_path, i); - g_adc[i].fd_value = open(g_buffer, O_RDONLY); - if (g_adc[i].fd_value < 0) - { - Abort("Couldn't open ADC %d device file %s - %s", i, g_buffer, strerror(errno)); - } - - //setbuf(g_adc[i].file_value, NULL); + Abort("Invalid ADC pin %d specified.", pin); + } + sprintf(g_buffer, "%s/in_voltage%d_raw", g_options.adc_device_path, pin); + g_adc[pin].fd_value = open(g_buffer, O_RDONLY); + if (g_adc[pin].fd_value <0) + { + Abort("Couldn't open ADC %d device file %s - %s", pin, g_buffer, strerror(errno)); } + Log(LOGDEBUG, "Opened ADC %d", pin); } /** * Unexport ADC pins + * @param pin The ADC pin number */ -void ADC_Unexport() +void ADC_Unexport(int pin) { - for (int i = 0; i < ADC_NUM_PINS; ++i) - close(g_adc[i].fd_value); + if (pin < 0 || pin >= ADC_NUM_PINS) + { + Abort("Invalid ADC pin %d specified.", pin); + } + if (pin != -1) + close(g_adc[pin].fd_value); + + g_adc[pin].fd_value = -1; } /** @@ -297,7 +296,7 @@ bool GPIO_Read(int pin) /** * Activate a PWM pin - * @param pin - The pin to activate + * @param pin - The sysfs pin number * @param polarity - if true, pin is active high, else active low * @param period - The period in ns * @param duty - The time the pin is active in ns @@ -306,50 +305,52 @@ void PWM_Set(int pin, bool polarity, long period, long duty) { Log(LOGDEBUG, "Pin %d, pol %d, period: %lu, duty: %lu", pin, polarity, period, duty); - rewind(g_pwm[pin].file_duty); - - if (fprintf(g_pwm[pin].file_duty, "0") == 0) + if (pin < 0 || pin >= PWM_NUM_PINS) { - Abort("Couldn't zero the duty cycle for PWM %d - s", pin, strerror(errno)); + Abort("Invalid PWM pin number %d specified.", pin); } - + + PWM_Pin *pwm = &g_pwm[pin]; + // Have to stop PWM before changing it - if (pwrite(g_pwm[pin].fd_run, "0", 1, 0) != 1) + if (pwrite(pwm->fd_run, "0", 1, 0) != 1) { - Abort("Couldn't stop PWM %d - %s", pin, strerror(errno)); + Abort("Couldn't stop PWM%d - %s", pin, strerror(errno)); } - char c = '0' + polarity; - if (pwrite(g_pwm[pin].fd_polarity, &c, 1, 0) != 1) + char c = polarity ? '1' : '0'; + if (pwrite(pwm->fd_polarity, &c, 1, 0) != 1) { - Abort("Couldn't set PWM %d polarity - %s", pin, strerror(errno)); + Abort("Couldn't set PWM%d polarity - %s", pin, strerror(errno)); } - - rewind(g_pwm[pin].file_period); - rewind(g_pwm[pin].file_duty); - if (fprintf(g_pwm[pin].file_period, "%lu", period) == 0) + + if (fprintf(pwm->file_period, "%lu", period) < 0) { - Abort("Couldn't set period for PWM %d - %s", pin, strerror(errno)); + Abort("Couldn't set period for PWM%d - %s", pin, strerror(errno)); } - if (fprintf(g_pwm[pin].file_duty, "%lu", duty) == 0) + if (fprintf(pwm->file_duty, "%lu", duty) < 0) { - Abort("Couldn't set duty cycle for PWM %d - %s", pin, strerror(errno)); + Abort("Couldn't set duty cycle for PWM%d - %s", pin, strerror(errno)); } - if (pwrite(g_pwm[pin].fd_run, "1", 1, 0) != 1) + if (pwrite(pwm->fd_run, "1", 1, 0) != 1) { - Abort("Couldn't start PWM %d - %s", pin, strerror(errno)); + Abort("Couldn't start PWM%d - %s", pin, strerror(errno)); } - } /** * Deactivate a PWM pin - * @param pin - The pin to turn off + * @param pin - The syfs pin number */ void PWM_Stop(int pin) { + if (pin < 0 || pin >= PWM_NUM_PINS) + { + Abort("Invalid PWM pin number %d specified.", pin); + } + if (pwrite(g_pwm[pin].fd_run, "0", 1, 0) != 1) { Abort("Couldn't stop PWM %d - %s", pin, strerror(errno)); @@ -363,26 +364,13 @@ void PWM_Stop(int pin) */ int ADC_Read(int id) { - char adc_str[ADC_DIGITS] = ""; - lseek(g_adc[id].fd_value, 0, SEEK_SET); - - int i = 0; - for (i = 0; i < ADC_DIGITS-1; ++i) + char adc_str[ADC_DIGITS] = {0}; + + if (pread(g_adc[id].fd_value, adc_str, ADC_DIGITS-1, 0) == -1) { - if (read(g_adc[id].fd_value, adc_str+i, 1) != 1) - break; - if (adc_str[i] == '\n') - { - adc_str[i] = '\0'; - break; - } + Log(LOGERR, "ADC %d read failed: %s", id, strerror(errno)); + return 0; } - char * end; - int val = strtol(adc_str, &end, 10); - if (*end != '\0') - { - Log(LOGERR, "Read non integer from ADC %d - %s", id, adc_str); - } - return val; + return strtol(adc_str, NULL, 10); } diff --git a/server/bbb_pin.h b/server/bbb_pin.h index 04c02b6..ef8e1be 100644 --- a/server/bbb_pin.h +++ b/server/bbb_pin.h @@ -17,8 +17,8 @@ extern void GPIO_Unexport(int pin); extern void PWM_Export(int pin); extern void PWM_Unexport(int pin); -extern void ADC_Export(); -extern void ADC_Unexport(); +extern void ADC_Export(int pin); +extern void ADC_Unexport(int pin); // Pin reading/setting functions extern bool GPIO_Read(int pin); diff --git a/server/bbb_pin_defines.c b/server/bbb_pin_defines.c index e89c6dc..ff7caea 100644 --- a/server/bbb_pin_defines.c +++ b/server/bbb_pin_defines.c @@ -42,4 +42,12 @@ const unsigned char g_index_to_gpio[GPIO_NUM_PINS] = { 30, 31, 44, 45, 46, 47, 48, 49, 50, 51, 60, 61, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 86, 87, 88, 89, 112, 115, 117 +}; + +/** + * Converts PWM index to PWM number + * e.g index 3 becomes 6 for /sys/class/pwm/pwm6 + */ +const unsigned char g_pin_safe_pwm[PWM_NUM_SAFE_PINS] = { + 0, 2, 4, 6, 7 }; \ No newline at end of file diff --git a/server/bbb_pin_defines.h b/server/bbb_pin_defines.h index 844b406..05eb5a9 100644 --- a/server/bbb_pin_defines.h +++ b/server/bbb_pin_defines.h @@ -138,22 +138,29 @@ extern const unsigned char g_index_to_gpio[GPIO_NUM_PINS]; /** Number of ADC pins **/ #define ADC_NUM_PINS 8 -/** Path to export ADCs with**/ -#define ADC_EXPORT_PATH "/sys/devices/bone_capemgr.9/slots" -/** Path at which ADCs appear **/ -#define ADC_DEVICE_PATH "/sys/devices/ocp.3/helper.16" - -/** PWM defines **/ -#define EHRPWM0A 0 -#define EHRPWM0B 1 -// No other PWM pins work! +#define ADC_DEVICE_PATH "/sys/bus/iio/devices/iio:device0/" + +/** PWM names to sysfs numbers **/ +#define EHRPWM0A 0 //P9_22 +#define EHRPWM0B 1 //P9_21 - period paired with EHRPWM0A +#define EHRPWM1A 3 //P9_14 +#define EHRPWM1B 4 //P9_16 - period paired with EHRPWM1A +#define ECAP0 2 //P9_42 +#define ECAP2 7 //P9_28 +#define EHRPWM2A 5 //P8_19 +#define EHRPWM2B 6 //P8_13 - period paired with EHRPWM2A /** Number of PWM pins **/ -#define PWM_NUM_PINS 2 +#define PWM_NUM_PINS 8 + +/** Number of PWM pins which are guaranteed not to interfere with one another **/ +#define PWM_NUM_SAFE_PINS 5 /** Path to PWM sysfs **/ #define PWM_DEVICE_PATH "/sys/class/pwm" +/** Maps internal pin number to safe 'pwmX' number **/ +extern const unsigned char g_pin_safe_pwm[PWM_NUM_SAFE_PINS]; #endif //_BBB_PIN_DEFINES_H diff --git a/server/options.h b/server/options.h index f702e01..05f7ddf 100644 --- a/server/options.h +++ b/server/options.h @@ -20,7 +20,7 @@ typedef struct struct timeval end_time; /** Path to ADC files **/ - char * adc_device_path; + const char * adc_device_path; /*** Horrible horrible hack ***/ int argc; diff --git a/server/pin_test.c b/server/pin_test.c index bcdf92e..9e3ad23 100644 --- a/server/pin_test.c +++ b/server/pin_test.c @@ -16,10 +16,11 @@ void Pin_Init() GPIO_Export(g_index_to_gpio[i]); for (int i = 0; i < ADC_NUM_PINS; ++i) - ADC_Export(); + ADC_Export(i); + //Only export 'safe' PWM pins that don't interfere with one another for (int i = 0; i < PWM_NUM_PINS; ++i) - PWM_Export(i); + PWM_Export(g_pin_safe_pwm[i]); } /** @@ -34,7 +35,7 @@ void Pin_Close() ADC_Unexport(i); for (int i = 0; i < PWM_NUM_PINS; ++i) - PWM_Unexport(i); + PWM_Unexport(g_pin_safe_pwm[i]); } /** @@ -121,7 +122,7 @@ void Pin_Handler(FCGIContext *context, char * params) } else if (strcmp(type, "pwm") == 0) { - if (num < 0 || num >= PWM_NUM_PINS) + if (num < 0 || num >= PWM_NUM_SAFE_PINS) { FCGI_RejectJSON(context, "Invalid PWM pin"); return; @@ -135,14 +136,14 @@ 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(num, pol, period_ns, duty_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); } else { Log(LOGDEBUG, "Stopping PWM%d",num); - PWM_Stop(num); + PWM_Stop(g_pin_safe_pwm[num]); FCGI_PrintRaw("PWM%d stopped",num); } } diff --git a/server/run.sh b/server/run.sh index 18af55b05e1a2477cf8838e6a750acea08f936de..c3e134cbb708ccf275fcabf1f67bdac359228108 100755 GIT binary patch delta 1085 zcmah|O^ee|6t#>Zd9GaP!o`t9OdV^Rw(~_C!Er_qM(EB(r<63gZ3F3hF-dKQamY__ z(LW;iX9Smm3x9<8-b>RKX9fegyySkJ^X|F7?)|*~^>-x?hv>qxeJ_KRMk2#!j1r3B zO$B5VXJ;3k{l0UcZA-`OS6!XRr;`CCGQ9x@O|;O)4tBAZ zOTP&Xl{C&ckbB&re!CcjI z2~Kg5BVO`JyQiA^Kg|kl>&`22uTa~1F9w2>+MNDo+r^8mN4W+XNVk$TPUV8&_3@jO z-L!>AM>Xlcinv^(rN4yuzwLWc=9TM*q5v}r;Ki3hdRyJ-;@#GliuvvPmQ$&i3**j@ JySMbi{sMy?QJDY$ delta 320 zcmaDX_>6nQD@GCJ-29Y+qWq*(g@W?j_>$D(5-yF&jZET`(^*C8mDBQz6bkZ-N)$5l z6ap;cjSRu05r{N20h4B65lawh43;$k%38!58iProxJA4%P$iHAs4 zT*{oO$rizL8@*NJJ5dJ%*_1B@vJhF9oYId QpJy{