001package com.pi4j.wiringpi;
002
003/*
004 * #%L
005 * **********************************************************************
006 * ORGANIZATION  :  Pi4J
007 * PROJECT       :  Pi4J :: Java Library (Core)
008 * FILENAME      :  SoftPwm.java
009 *
010 * This file is part of the Pi4J project. More information about
011 * this project can be found here:  https://www.pi4j.com/
012 * **********************************************************************
013 * %%
014 * Copyright (C) 2012 - 2021 Pi4J
015 * %%
016 * This program is free software: you can redistribute it and/or modify
017 * it under the terms of the GNU Lesser General Public License as
018 * published by the Free Software Foundation, either version 3 of the
019 * License, or (at your option) any later version.
020 *
021 * This program is distributed in the hope that it will be useful,
022 * but WITHOUT ANY WARRANTY; without even the implied warranty of
023 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
024 * GNU General Lesser Public License for more details.
025 *
026 * You should have received a copy of the GNU General Lesser Public
027 * License along with this program.  If not, see
028 * <http://www.gnu.org/licenses/lgpl-3.0.html>.
029 * #L%
030 */
031
032
033import com.pi4j.util.NativeLibraryLoader;
034
035/**
036 * <p>
037 * WiringPi includes a software-driven PWM handler capable of outputting a PWM signal on any of the
038 * Raspberry Pi's GPIO pins.
039 * </p>
040 *
041 * <p>
042 * There are some limitations. To maintain a low CPU usage, the minimum pulse width is 100uS. That
043 * combined with the default suggested range of 100 gives a PWM frequency of 100Hz. You can lower
044 * the range to get a higher frequency, at the expense of resolution, or increase to get more
045 * resolution, but that will lower the frequency. If you change the pulse-width in the drive code,
046 * then be aware that at delays of less than 100uS wiringPi does it in a software loop, which means
047 * that CPU usage will rise dramatically, and controlling more than one pin will be almost
048 * impossible.
049 * </p>
050 *
051 * <p>
052 * Also note that while the routines run themselves at a higher and real-time priority, Linux can
053 * still affect the accuracy of the generated signal.
054 * </p>
055 *
056 * <p>
057 * However, within these limitations, control of a light/LED or a motor is very achievable.
058 * </p>
059 *
060 * <p>
061 * <b> You must initialize wiringPi with one of wiringPiSetup() or wiringPiSetupGpio() functions
062 * beforehand. wiringPiSetupSys() is not fast enough, so you must run your programs with sudo. </b>
063 * </p>
064 *
065 * <p>
066 * Before using the Pi4J library, you need to ensure that the Java VM in configured with access to
067 * the following system libraries:
068 * <ul>
069 * <li>pi4j</li>
070 * <li>wiringPi</li>
071 * <li>pthread</li>
072 * </ul>
073 * <blockquote> This library depends on the wiringPi native system library.</br> (developed by
074 * Gordon Henderson @ <a href="http://wiringpi.com/">http://wiringpi.com/</a>)
075 * </blockquote>
076 * </p>
077 *
078 * @see <a href="https://www.pi4j.com/">https://www.pi4j.com/</a>
079 * @see <a
080 *      href="http://wiringpi.com/reference/software-pwm-library/">http://wiringpi.com/reference/software-pwm-library/</a>
081 * @author Robert Savage (<a
082 *         href="http://www.savagehomeautomation.com">http://www.savagehomeautomation.com</a>)
083 */
084public class SoftPwm {
085
086    // private constructor
087    private SoftPwm() {
088        // forbid object construction
089    }
090
091    static {
092        // Load the platform library
093        NativeLibraryLoader.load("libpi4j.so", "pi4j");
094    }
095
096    /**
097     * <p>int softPwmCreate (int pin, int initialValue, int pwmRange);</p>
098     *
099     * <p>
100     * This creates a software controlled PWM pin. You can use any GPIO pin and the pin numbering
101     * will be that of the wiringPiSetup function you used. Use 100 for the pwmRange, then the value
102     * can be anything from 0 (off) to 100 (fully on) for the given pin.
103     * </p>
104     *
105     * @see <a
106     *      href="http://wiringpi.com/reference/software-pwm-library/">http://wiringpi.com/reference/software-pwm-library/</a>
107     *
108     * @param pin The GPIO pin to use as a PWM pin.
109     *            </p>
110     * @param value The value to initialize the PWM pin (between 0 <i>(off)</i> to 100 <i>(fully
111     *            on)</i>)
112     * @param range The maximum range. Use 100 for the pwmRange.
113     * @return The return value is 0 for success. Anything else and you should check the global
114     *         errno variable to see what went wrong.
115     */
116    public static native int softPwmCreate(int pin, int value, int range);
117
118    /**
119     * <p>void softPwmWrite (int pin, int value);</p>
120     *
121     * <p>
122     * This updates the PWM value on the given pin. The value is checked to be in-range and pins
123     * that haven't previously been initialized via softPwmCreate will be silently ignored.
124     * </p>
125     *
126     * @see <a
127     *      href="http://wiringpi.com/reference/software-pwm-library/">http://wiringpi.com/reference/software-pwm-library/</a>
128     *
129     * @param pin The GPIO pin to use as a PWM pin.
130     * @param value The value to initialize the PWM pin (between 0 <i>(off)</i> to 100 <i>(fully
131     *            on)</i>)
132     */
133    public static native void softPwmWrite(int pin, int value);
134
135    /**
136     /**
137     * <p>void softPwmStop (int pin);</p>
138     *
139     * <p>
140     * This stops the software emulated PWM driver/thread for the given pin.
141     * </p>
142     *
143     * @see <a
144     *      href="http://wiringpi.com/reference/software-pwm-library/">http://wiringpi.com/reference/software-pwm-library/>     *
145     * @param pin The GPIO pin to use as a PWM pin.
146     */
147    public static native void softPwmStop(int pin);
148}