package com.diozero.internal.provider.wiringpi;

/*
 * #%L
 * Device I/O Zero - wiringPi provider
 * %%
 * Copyright (C) 2016 diozero
 * %%
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 * 
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 * #L%
 */

import org.pmw.tinylog.Logger;

import com.diozero.api.PwmType;
import com.diozero.internal.spi.AbstractDevice;
import com.diozero.internal.spi.DeviceFactoryInterface;
import com.diozero.internal.spi.PwmOutputDeviceInterface;
import com.diozero.util.RuntimeIOException;
import com.pi4j.wiringpi.Gpio;
import com.pi4j.wiringpi.GpioUtil;
import com.pi4j.wiringpi.SoftPwm;

public class WiringPiPwmOutputDevice extends AbstractDevice implements PwmOutputDeviceInterface {
	private static final boolean DISABLED = true;
	
	private int pinNumber;
	private float value;
	private PwmType pwmType;
	private int range;
	
	WiringPiPwmOutputDevice(String key, DeviceFactoryInterface deviceFactory, PwmType pwmType,
			int range, int pinNumber, float initialValue) throws RuntimeIOException {
		super(key, deviceFactory);
		
		this.pinNumber = pinNumber;
		this.value = initialValue;
		this.pwmType = pwmType;
		this.range = range;
		
		switch (pwmType) {
		case HARDWARE:
			if (DISABLED) {
				// This worked from the command line after a fresh restart
				// However, not yet got it to work in software even though using the same commands
				// http://raspberrypi.stackexchange.com/questions/4906/control-hardware-pwm-frequency/38070#38070?newreg=67e978faf30840a6a674ba040fbf1752
				throw new UnsupportedOperationException("Not yet worked out WiringPi Hardware PWM");
			}
			if (GpioUtil.isExported(pinNumber)) {
				GpioUtil.setDirection(pinNumber, GpioUtil.DIRECTION_OUT);
			} else {
				GpioUtil.export(pinNumber, GpioUtil.DIRECTION_OUT);
			}
			Gpio.pinMode(pinNumber, Gpio.PWM_OUTPUT);
			Gpio.pwmWrite(pinNumber, (int)(value * range));
			break;
		case SOFTWARE:
			int status = SoftPwm.softPwmCreate(pinNumber, (int)(value * range), range);
			if (status != 0) {
				throw new RuntimeIOException("Error setting up software controlled PWM GPIO on BCM pin " +
						pinNumber + ", status=" + status);
			}
			break;
		}
	}

	@Override
	public void closeDevice() throws RuntimeIOException {
		Logger.debug("closeDevice()");
		switch (pwmType) {
		case HARDWARE:
			GpioUtil.unexport(pinNumber);
		case SOFTWARE:
			SoftPwm.softPwmStop(pinNumber);
			GpioUtil.unexport(pinNumber);
			break;
		default:
		}
	}

	@Override
	public int getPin() {
		return pinNumber;
	}

	@Override
	public float getValue() {
		return value;
	}

	@Override
	public void setValue(float value) throws RuntimeIOException {
		this.value = value;
		int dc = (int)Math.floor(value * range);
		switch (pwmType) {
		case HARDWARE:
			Logger.info("setValue({}), range={}, dc={}", Float.valueOf(value), Integer.valueOf(range), Integer.valueOf(dc));
			Gpio.pwmWrite(pinNumber, dc);
			break;
		case SOFTWARE:
		default:
			SoftPwm.softPwmWrite(pinNumber, dc);
			break;
		}
	}
}

@@ -1695,57 +1695,8 @@
  %7B%0D%0A
-%09private static final boolean DISABLED = true;%0A%09%0A
 %09pri
@@ -1993,16 +1993,42 @@
 );%0D%0A%09%09%0D%0A
+%09%09this.pwmType = pwmType;%0A
 %09%09this.p
@@ -2083,35 +2083,8 @@
 ue;%0A
-%09%09this.pwmType = pwmType;%0D%0A
 %09%09th
@@ -2148,414 +2148,8 @@
 RE:%0A
-%09%09%09if (DISABLED) %7B%0A%09%09%09%09// This worked from the command line after a fresh restart%0A%09%09%09%09// However, not yet got it to work in software even though using the same commands%0A%09%09%09%09// http://raspberrypi.stackexchange.com/questions/4906/control-hardware-pwm-frequency/38070#38070?newreg=67e978faf30840a6a674ba040fbf1752%0A%09%09%09%09throw new UnsupportedOperationException(%22Not yet worked out WiringPi Hardware PWM%22);%0A%09%09%09%7D%0D%0A
 %09%09%09i
@@ -2369,16 +2369,111 @@
 UTPUT);%0A
+%09%09%09// Have to call this after setting the pin mode! Yuck%0A%09%09%09Gpio.pwmSetMode(Gpio.PWM_MODE_MS);%0A
 %09%09%09Gpio.
@@ -2489,34 +2489,42 @@
 pinNumber, (int)
-(v
+ (initialV
 alue * range));%0A
@@ -2607,17 +2607,24 @@
 , (int)(
-v
+initialV
 alue * r
@@ -3364,16 +3364,17 @@
  = (int)
+ 
 Math.flo

Set PWM MS mode after provisioning a h/w PWM pin