001package com.pi4j.io.gpio; 002 003import com.pi4j.io.gpio.event.PinListener; 004import com.pi4j.wiringpi.GpioInterruptEvent; 005import com.pi4j.wiringpi.GpioInterruptListener; 006import com.pi4j.wiringpi.GpioUtil; 007 008/* 009 * #%L 010 * ********************************************************************** 011 * ORGANIZATION : Pi4J 012 * PROJECT : Pi4J :: Java Library (Core) 013 * FILENAME : RaspiGpioProvider.java 014 * 015 * This file is part of the Pi4J project. More information about 016 * this project can be found here: http://www.pi4j.com/ 017 * ********************************************************************** 018 * %% 019 * Copyright (C) 2012 - 2015 Pi4J 020 * %% 021 * This program is free software: you can redistribute it and/or modify 022 * it under the terms of the GNU Lesser General Public License as 023 * published by the Free Software Foundation, either version 3 of the 024 * License, or (at your option) any later version. 025 * 026 * This program is distributed in the hope that it will be useful, 027 * but WITHOUT ANY WARRANTY; without even the implied warranty of 028 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 029 * GNU General Lesser Public License for more details. 030 * 031 * You should have received a copy of the GNU General Lesser Public 032 * License along with this program. If not, see 033 * <http://www.gnu.org/licenses/lgpl-3.0.html>. 034 * #L% 035 */ 036 037/** 038 * Raspberry PI {@link GpioProvider} implementation. 039 * 040 * @author Robert Savage (<a 041 * href="http://www.savagehomeautomation.com">http://www.savagehomeautomation.com</a>) 042 */ 043@SuppressWarnings("unused") 044public class RaspiGpioProvider extends GpioProviderBase implements GpioProvider, GpioInterruptListener { 045 046 public static final String NAME = "RaspberryPi GPIO Provider"; 047 048 public RaspiGpioProvider() { 049 // set wiringPi interface for internal use 050 // we will use the WiringPi pin number scheme with the wiringPi library 051 com.pi4j.wiringpi.Gpio.wiringPiSetup(); 052 } 053 054 @Override 055 public String getName() { 056 return NAME; 057 } 058 059 @Override 060 public boolean hasPin(Pin pin) { 061 return (com.pi4j.wiringpi.GpioUtil.isPinSupported(pin.getAddress()) > 0); 062 } 063 064 @Override 065 public void export(Pin pin, PinMode mode) { 066 export(pin, mode, null); 067 } 068 069 @Override 070 public void export(Pin pin, PinMode mode, PinState defaultState) { 071 super.export(pin, mode); 072 073 //System.out.println("-- EXPORTING PIN [" + pin.getAddress() + "] to mode [" + mode.getName() + "]"); 074 075 // get mode configured direction value 076 int direction = mode.getDirection().getValue(); 077 078 // if a default state was provided and the direction is OUT, then override the 079 // pin direction to include initial state value 080 if(defaultState != null && mode.getDirection() == PinDirection.OUT){ 081 if(defaultState == PinState.LOW) 082 direction = GpioUtil.DIRECTION_LOW; 083 else if(defaultState == PinState.HIGH) 084 direction = GpioUtil.DIRECTION_HIGH; 085 } 086 087 // if not already exported, export the pin and set the pin direction 088 if(!com.pi4j.wiringpi.GpioUtil.isExported(pin.getAddress())){ 089 com.pi4j.wiringpi.GpioUtil.export(pin.getAddress(), direction); 090 } 091 // if the pin is already exported, then check its current configured direction 092 // if the direction does not match, then set the new direction for the pin 093 else if(com.pi4j.wiringpi.GpioUtil.getDirection(pin.getAddress()) != mode.getDirection().getValue()){ 094 com.pi4j.wiringpi.GpioUtil.setDirection(pin.getAddress(), direction); 095 } 096 097 // set the pin input/output mode 098 setMode(pin, mode); 099 } 100 101 @Override 102 public boolean isExported(Pin pin) { 103 super.isExported(pin); 104 105 // return the pin exported state 106 return com.pi4j.wiringpi.GpioUtil.isExported(pin.getAddress()); 107 } 108 109 @Override 110 public void unexport(Pin pin) { 111 super.unexport(pin); 112 113 // unexport the pins 114 com.pi4j.wiringpi.GpioUtil.unexport(pin.getAddress()); 115 } 116 117 @Override 118 public void setMode(Pin pin, PinMode mode) { 119 super.setMode(pin, mode); 120 121 com.pi4j.wiringpi.Gpio.pinMode(pin.getAddress(), mode.getValue()); 122 123 // if this is an input pin, then configure edge detection 124 if (PinMode.allInputs().contains(mode)) { 125 com.pi4j.wiringpi.GpioUtil.setEdgeDetection(pin.getAddress(), PinEdge.BOTH.getValue()); 126 } 127 } 128 129 @Override 130 public PinMode getMode(Pin pin) { 131 // TODO : get actual pin mode from native impl 132 return super.getMode(pin); 133 } 134 135 @Override 136 public void setPullResistance(Pin pin, PinPullResistance resistance) { 137 super.setPullResistance(pin, resistance); 138 139 com.pi4j.wiringpi.Gpio.pullUpDnControl(pin.getAddress(), resistance.getValue()); 140 } 141 142 @Override 143 public PinPullResistance getPullResistance(Pin pin) { 144 // TODO : get actual pin pull resistance from native impl 145 return super.getPullResistance(pin); 146 } 147 148 @Override 149 public void setState(Pin pin, PinState state) { 150 super.setState(pin, state); 151 com.pi4j.wiringpi.Gpio.digitalWrite(pin.getAddress(), state.getValue()); 152 } 153 154 @Override 155 public PinState getState(Pin pin) { 156 super.getState(pin); 157 158 // return pin state 159 PinState state = null; 160 int ret = com.pi4j.wiringpi.Gpio.digitalRead(pin.getAddress()); 161 if (ret >= 0) { 162 state = PinState.getState(ret); 163 } 164 return state; 165 } 166 167 @Override 168 public void setValue(Pin pin, double value) { 169 super.setValue(pin, value); 170 throw new RuntimeException("This GPIO provider does not support analog pins."); 171 } 172 173 @Override 174 public double getValue(Pin pin) { 175 super.getValue(pin); 176 throw new RuntimeException("This GPIO provider does not support analog pins."); 177 } 178 179 @Override 180 public void setPwm(Pin pin, int value) { 181 super.setPwm(pin, value); 182 183 if (getMode(pin) == PinMode.PWM_OUTPUT) { 184 setPwmValue(pin, value); 185 } 186 } 187 188 @Override 189 public int getPwm(Pin pin) { 190 return super.getPwm(pin); 191 } 192 193 // internal 194 private void setPwmValue(Pin pin, int value) { 195 // set pin PWM value 196 com.pi4j.wiringpi.Gpio.pwmWrite(pin.getAddress(), value); 197 } 198 199 @Override 200 public void pinStateChange(GpioInterruptEvent event) { 201 // iterate over the pin listeners map 202 for (Pin pin : listeners.keySet()) { 203 // dispatch this event to the listener 204 // if a matching pin address is found 205 if (pin.getAddress() == event.getPin()) { 206 dispatchPinDigitalStateChangeEvent(pin, PinState.getState(event.getState())); 207 } 208 } 209 } 210 211 @Override 212 public void addListener(Pin pin, PinListener listener) { 213 super.addListener(pin, listener); 214 215 // update the native interrupt listener thread for callbacks 216 updateInterruptListener(pin); 217 } 218 219 @Override 220 public void removeListener(Pin pin, PinListener listener) { 221 super.removeListener(pin, listener); 222 223 // update the native interrupt listener thread for callbacks 224 updateInterruptListener(pin); 225 } 226 227 // internal 228 private void updateInterruptListener(Pin pin) { 229 if (listeners.size() > 0) { 230 // setup interrupt listener native thread and enable callbacks 231 if (!com.pi4j.wiringpi.GpioInterrupt.hasListener(this)) { 232 com.pi4j.wiringpi.GpioInterrupt.addListener(this); 233 } 234 com.pi4j.wiringpi.GpioInterrupt.enablePinStateChangeCallback(pin.getAddress()); 235 } else { 236 // remove interrupt listener, disable native thread and callbacks 237 com.pi4j.wiringpi.GpioInterrupt.disablePinStateChangeCallback(pin.getAddress()); 238 if (com.pi4j.wiringpi.GpioInterrupt.hasListener(this)) { 239 com.pi4j.wiringpi.GpioInterrupt.removeListener(this); 240 } 241 } 242 } 243}