Exemple #1
0
bool Gpio::setStateRange(int state, int startPin, int endPin)
{
	if (!mInit){
		fprintf(stderr, "GPIO not initialised\n");
		return false;
	}

	int pwmVal;
	if (state == 0)
		pwmVal = 0;
	else
		pwmVal = 100000;

	for (std::list<Gpio*>::iterator iter =
		mOutputList.begin(); iter != mOutputList.end(); iter++)
	{
		Gpio *obj = *iter;
		int pin = obj->getPin();
		if (obj->getType() == OUT_PIN && pin >= startPin && pin <= endPin)
			digitalWrite(obj->getPin(), state);
	}

	for (auto iter = mMonitorList.begin(); iter != mMonitorList.end(); iter++)
	{
		Gpio *obj = *iter;
		int pin = obj->getPin();
		if (obj->getType() == PWM && pin >= startPin && pin <= endPin){
			if (mLastValue[pin] != pwmVal)
				resetPwm(pin, pwmVal);
		}
	}

	return true;
}
Exemple #2
0
/**
 * Start a thread to constantly monitor all the input pins we are
 * interested in. When a state change is detected we store the
 * time of the change.  This creates a buffer so we can still see
 * changes that happened a short time ago (so we don't miss any).
 *
 * It also writes PWM outputs and is responsible for writing random
 * data, sine waves etc. to these outputs. 
 */
bool Gpio::startMonitor()
{
	if (!mInit){
		fprintf(stderr, "GPIO not initialised\n");
		return false;
	}

	// Do we have anything to monitor?
	if (mMonitorList.size() == 0)
		return true;

	bool usingPwm = false;
	for (auto iter = mMonitorList.begin(); iter != mMonitorList.end(); iter++)
	{
		Gpio *obj = *iter;
		int pin = obj->getPin();

		if (obj->getType() == PWM){
			// Don't start outputting PWM until we execute a relevant command
			mMonType[pin] = INACTIVE;
			mMonMutex[pin] = PTHREAD_MUTEX_INITIALIZER;

			// Set to full range initially (range map is in millis)
			mRangeMapMin[pin] = 0;
			mRangeMapMax[pin] = 100000;
			usingPwm = true;
		}
		else {
			// Input pins are always monitored
			initMonitorInput(pin);
		}
	}

	if (usingPwm){
		// Start ServoBlaster. We use this instead of hardware
		// PWM as there is only one hardware PWM pin on the Pi
		// and hardware PWM interferes with analog audio.
		if (!startServoBlaster())
			return false;
	}

	// Start monitor thread
	if (pthread_create(&mMonitorId, NULL, monitor, NULL) != 0){
		fprintf(stderr, "** Failed to start gpio monitor\n");
		return false;
	}

	// Wait for monitor to start
	for (int retries = 0; retries < 15; retries++){
		if (mMonitorRunning)
			return true;

		Engine::sleep(200);
	}

	printf("** Failed to start gpio monitor\n");
	return false;
}
Exemple #3
0
bool Gpio::startServoBlaster()
{
	// Stop ServoBlaster if it's already running
	mServoBlasterPid = Engine::findProcess(SB_COMMAND);
	if (mServoBlasterPid != -1)
		stopServoBlaster();

	if (Engine::displayOn)
		printf("Starting ServoBlaster (%s)\n", SB_COMMAND);

	mServoBlasterPid = fork();
	if (mServoBlasterPid == -1){
		fprintf(stderr, "** Failed to create ServoBlaster process\n");
		return false;
	}

	if (mServoBlasterPid != 0){
		// This is the parent process

		// Make sure ServoBlaster started
		int status;
		for (int retries = 0; retries < 15; retries++){
			if (waitpid(mServoBlasterPid, &status, WNOHANG) != -1){
				sleep(1);
				mServoBlasterOut = open(SB_DEVICE, O_WRONLY|O_SYNC);
				if (mServoBlasterOut == -1){
					fprintf(stderr, "** Failed to open %s\n", SB_DEVICE);
					return false;
				}
				return true;
			}

			Engine::sleep(200);
		}
		fprintf(stderr, "ServoBlaster failed to start\n");
		return false;
	}

	// Make ServoBlaster use same pin mapping as wiringPi.
	// We are mapping wiringPi pin number to physical pin number.
	const int pinMap[] = {11,12,13,15,16,18,22,7,3,5,24,26,19,21,23,8,10};
	int servoBlasterPin[MAX_PWM_PINS];

	// ServoBlaster needs to know which pins we are using for PWM
	for (int i = 0; i < MAX_PWM_PINS; i++)
		servoBlasterPin[i] = 0;

	for (auto iter = mMonitorList.begin(); iter != mMonitorList.end(); iter++)
	{
		Gpio *obj = *iter;
		if (obj->getType() == PWM){
			int pin = obj->getPin();
			servoBlasterPin[pin] = pinMap[pin];
		}
	}

	// First arg is the pin list
	char argv1[256];
	sprintf(argv1, "--p1pins=%d", servoBlasterPin[0]);
	char addStr[64];
	for (int i = 1; i < MAX_PWM_PINS; i++){
		sprintf(addStr, ",%d", servoBlasterPin[i]);
		strcat(argv1, addStr);
	}

	// Second arg is the cycle time
	char argv2[256];
	sprintf(argv2, "--cycle-time=%dus", SB_CYCLE_TIME);

	const char *argv[16];
	argv[0] = SB_COMMAND;
	argv[1] = argv1;
	argv[2] = argv2;
	for (int i = 0;; i++){
		argv[i+3] = SB_PARAMS[i];
		if (SB_PARAMS[i] == NULL)
			break;
	}

	// redirect stdout and stderr
	freopen("/tmp/servoblaster.log", "w", stdout);
	freopen("/tmp/servoblaster.log", "w", stderr);

	// Try from current dir first
	char command[256];
	sprintf(command, "./%s", SB_COMMAND);
	execv(command, (char* const*)argv);
	// execv only returns if an error occurs

	// Now try from PATH
	execvp(SB_COMMAND, (char* const*)argv);
	// execv only returns if an error occurs

	fprintf(stderr, "** Failed to start ServoBlaster using command:\n");
	fprintf(stderr, "%s", SB_COMMAND);
	for (int i = 0; argv[i] != NULL; i++)
		fprintf(stderr, " %s", argv[i]);

	fprintf(stderr, "\n");
	return true;
}