All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.pi4j.component.servo.impl.RPIServoBlasterProvider Maven / Gradle / Ivy

package com.pi4j.component.servo.impl;

/*
 * #%L
 * **********************************************************************
 * ORGANIZATION  :  Pi4J
 * PROJECT       :  Pi4J :: Device Abstractions
 * FILENAME      :  RPIServoBlasterProvider.java  
 * 
 * This file is part of the Pi4J project. More information about 
 * this project can be found here:  http://www.pi4j.com/
 * **********************************************************************
 * %%
 * Copyright (C) 2012 - 2015 Pi4J
 * %%
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as
 * published by the Free Software Foundation, either version 3 of the
 * License, or (at your option) any later version.
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Lesser Public License for more details.
 * 
 * You should have received a copy of the GNU General Lesser Public
 * License along with this program.  If not, see
 * .
 * #L%
 */

import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.Writer;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import com.pi4j.component.servo.ServoDriver;
import com.pi4j.component.servo.ServoProvider;
import com.pi4j.io.gpio.Pin;
import com.pi4j.io.gpio.RaspiPin;


/**
 * Implementation of https://github.com/richardghirst/PiBits/tree/master/ServoBlaster
 * 
 *
 * @author Daniel Sendula
 */
public class RPIServoBlasterProvider implements ServoProvider {

    // Default servo mapping of ServoBlaster's servod:
    //
    //    0 on P1-7           GPIO-4
    //    1 on P1-11          GPIO-17
    //    2 on P1-12          GPIO-18
    //    3 on P1-13          GPIO-27
    //    4 on P1-15          GPIO-22
    //    5 on P1-16          GPIO-23
    //    6 on P1-18          GPIO-24
    //    7 on P1-22          GPIO-25

    public static final String PIN_P1_3  = "P1-3";
    public static final String PIN_P1_5  = "P1-5";
    public static final String PIN_P1_7  = "P1-7";
    public static final String PIN_P1_11 = "P1-11";
    public static final String PIN_P1_12 = "P1-12";
    public static final String PIN_P1_13 = "P1-13";
    public static final String PIN_P1_15 = "P1-15";
    public static final String PIN_P1_16 = "P1-16";
    public static final String PIN_P1_18 = "P1-18";
    public static final String PIN_P1_19 = "P1-19";
    public static final String PIN_P1_21 = "P1-21";
    public static final String PIN_P1_22 = "P1-22";
    public static final String PIN_P1_23 = "P1-23";
    public static final String PIN_P1_24 = "P1-24";
    public static final String PIN_P1_25 = "P1-25";
    public static final String PIN_P1_26 = "P1-26";

    public static final String PIN_P5_3 = "P5-3";
    public static final String PIN_P5_4 = "P5-4";
    public static final String PIN_P5_5 = "P5-5";
    public static final String PIN_P5_6 = "P5-6";

    public static Map PIN_MAP;
    public static Map REVERSE_PIN_MAP;
    
    static {
        PIN_MAP = new HashMap();
        REVERSE_PIN_MAP = new HashMap();
        definePin(RaspiPin.GPIO_08, PIN_P1_3);
        definePin(RaspiPin.GPIO_09, PIN_P1_5);
        definePin(RaspiPin.GPIO_07, PIN_P1_7);
        definePin(RaspiPin.GPIO_00, PIN_P1_11);
        definePin(RaspiPin.GPIO_01, PIN_P1_12);
        definePin(RaspiPin.GPIO_02, PIN_P1_13);
        definePin(RaspiPin.GPIO_03, PIN_P1_15);
        definePin(RaspiPin.GPIO_04, PIN_P1_16);
        definePin(RaspiPin.GPIO_05, PIN_P1_18);
        definePin(RaspiPin.GPIO_12, PIN_P1_19);
        definePin(RaspiPin.GPIO_13, PIN_P1_21);
        definePin(RaspiPin.GPIO_06, PIN_P1_22);
        definePin(RaspiPin.GPIO_14, PIN_P1_23);
        definePin(RaspiPin.GPIO_10, PIN_P1_24);
        definePin(RaspiPin.GPIO_11, PIN_P1_26);

        definePin(RaspiPin.GPIO_17, PIN_P5_3);
        definePin(RaspiPin.GPIO_18, PIN_P5_4);
        definePin(RaspiPin.GPIO_19, PIN_P5_5);
        definePin(RaspiPin.GPIO_20, PIN_P5_6);
    }

    static void definePin(Pin pin, String s) {
        PIN_MAP.put(pin, s);
        REVERSE_PIN_MAP.put(s, pin);
    }
    
    public static final String SERVO_BLASTER_DEV = "/dev/servoblaster";
    public static final String SERVO_BLASTER_DEV_CFG = "/dev/servoblaster-cfg";
    
    protected File servoBlasterDev;
    protected File servoBlasterDevCfg;
    
    protected Writer writer;
    
    protected Map allocatedDrivers = new HashMap();
    
    /**
     * Constructor. It checks if /dev/servoblaster file exists.
     * 
     * @throws IOException thrown in case file /dev/servoblaster does not exist.
     */
    public RPIServoBlasterProvider() throws IOException {
        servoBlasterDev = new File(SERVO_BLASTER_DEV);
        if (!servoBlasterDev.exists()) {
            throw new FileNotFoundException("File " + SERVO_BLASTER_DEV + " is not present." +
                    " Please check https://github.com/richardghirst/PiBits/tree/master/ServoBlaster for details.");
        }
        servoBlasterDevCfg = new File(SERVO_BLASTER_DEV_CFG);
        if (!servoBlasterDevCfg.exists()) {
            throw new FileNotFoundException("File " + SERVO_BLASTER_DEV_CFG + " is not present." +
                    " Please check https://github.com/richardghirst/PiBits/tree/master/ServoBlaster for details.");
        }
        
    }
    
    public List getDefinedServoPins() throws IOException {
        List servoPins = new ArrayList();
        FileReader in = new FileReader(servoBlasterDevCfg);
        try {
            @SuppressWarnings("unused")
            String p1pins = null;
            @SuppressWarnings("unused")
            String p5pins = null;
            boolean mappingStarted = false;
            
            @SuppressWarnings("resource")
            BufferedReader reader = new BufferedReader(in);

            String line = reader.readLine();
            while (line != null) {
                if (mappingStarted) {
                    line = line.trim();
                    int i = line.indexOf(" on ");
                    if (i > 0) {
                        try {
                            int index = Integer.parseInt(line.substring(0, i));
                            String pin = line.substring(i + 4).trim();
                            i = pin.indexOf(' ');
                            pin = pin.substring(0, i);
                            
                            Pin gpio = REVERSE_PIN_MAP.get(pin);
                            if (gpio != null) {
                                if (index == servoPins.size()) {
                                    servoPins.add(gpio);
                                } else if (index > servoPins.size()) {
                                    while (servoPins.size() < index) {
                                        servoPins.add(null);
                                    }
                                    servoPins.add(gpio);
                                } else {
                                    servoPins.set(index, gpio);
                                }
                            } else {
                                System.err.println("Unrecognised pin " + pin);
                            }
                            
                        } catch (NumberFormatException ignore) { }
                    }
                } else {
                    if (line.startsWith("p1pins=")) {
                        p1pins = line.substring(7);
                    }
                    if (line.startsWith("p5pins=")) {
                        p5pins = line.substring(7);
                    }
                    if (line.trim().equals("Servo mapping:")) {
                        mappingStarted = true;
                    }
                }
                line = reader.readLine();
            }
        } finally {
            try {
                in.close();
            } catch (IOException ignore) {
            }
        }
        return servoPins;
    }
    
    /**
     * Returns new instance of {@link RPIServoBlasterServoDriver}.
     * 
     * @param servoPin servo pin.
     * @return instance of {@link RPIServoBlasterServoDriver}.
     */
    public synchronized ServoDriver getServoDriver(Pin servoPin) throws IOException {
        List servoPins = getDefinedServoPins();
        int index = servoPins.indexOf(servoPin);
        if (index < 0) {
            throw new IllegalArgumentException("Servo driver cannot drive pin " + servoPin);
        }

        RPIServoBlasterServoDriver driver = allocatedDrivers.get(servoPin);
        if (driver == null) {
            driver = new RPIServoBlasterServoDriver(servoPin, index, PIN_MAP.get(servoPin), this);
            ensureWriterIsCreated();
        }
        
        return driver;
    }

    protected synchronized void ensureWriterIsCreated() throws IOException {
        if (writer == null) {
            // Not really singleton, but it will work...
            writer = new FileWriter(servoBlasterDev);
        }
    }
    
    protected synchronized void updateServo(String pinName, int value) {
        StringBuilder b = new StringBuilder();
        b.append(pinName).append('=').append(Integer.toString(value)).append('\n');
        try {
            writer.write(b.toString());
            writer.flush();
        } catch (IOException e) {
            try {
                writer.close();
            } catch (IOException ignore) { }
        }
        try {
            ensureWriterIsCreated();
            writer.write(b.toString());
            writer.flush();
        } catch (IOException e) {
            throw new RuntimeException("Failed to write to /dev/servoblaster device", e);
        }
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy