/*******************************************************************************
* Copyright (c) 2008, 2011 Thomas Holland (thomas@innot.de) and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Thomas Holland - initial API and implementation
*******************************************************************************/
package de.innot.avreclipse.core.avrdude;
import java.util.ArrayList;
import java.util.List;
import org.eclipse.core.runtime.Assert;
import org.osgi.service.prefs.BackingStoreException;
import org.osgi.service.prefs.Preferences;
/**
* Container class for all Programmer specific options of AVRDude.
* <p>
* This class also acts as an Interface to the preference store. It knows how to save and delete
* configurations.
* </p>
*
* @author Thomas Holland
* @since 2.2
* @since 2.3 added invocation delay option
*
*/
public class ProgrammerConfig {
/** The unique identifier for this configuration */
private final String fId;
public final static String KEY_ID = "id";
/** The unique name of this configuration */
private String fName;
public final static String KEY_NAME = "name";
/** A custom description of this configuration */
private String fDescription;
public final static String KEY_DESCRIPTION = "description";
public final static String DEFAULT_DESCRIPTION = "Default AVRDude Programmer Configuration. Modify as required for your setup.";
/** The avrdude id of the programmer for this configuration */
private String fProgrammer;
public final static String KEY_PROGRAMMER = "programmer";
public final static String DEFAULT_PROGRAMMER = "stk500v2";
/**
* The port for this configuration. If empty it will not be included in the command line
* arguments.
*/
private String fPort;
public final static String KEY_PORT = "port";
/**
* The baudrate for this configuration. If empty it will not be included in the command line
* arguments.
*/
private String fBaudrate;
public final static String KEY_BAUDRATE = "baudrate";
/**
* The Exitspec for the resetline. If empty it will not be included in the command line
* arguments.
* <p>
* Valid values are "reset", "noreset" and ""
* </p>
*/
private String fExitReset;
public final static String KEY_EXITSPEC_RESET = "ppresetline";
/**
* The Exitspec for the Vcc lines. If empty or <code>null</code> it will not be included in
* the command line arguments.
* <p>
* Valid values are "vcc", "novcc" and ""
* </p>
*/
private String fExitVcc;
public final static String KEY_EXITSPEC_VCC = "ppvccline";
/**
* The optional delay in milliseconds to delay multiple successive calls to avrdude.
* <p>
* To be used if avrdude does not release its output port fast enough, causing "port blocked"
* failures.
* </p>
* <p>
* May be <code>null</code> or empty. If not empty it must contain an integer number.
* </p>
* <p>
* Unlike the other parameters in this class this is not used on the avrdude command line. But
* all classes that make successive calls to avrdude must respect this delay.
* </p>
*
*/
private String fPostAVRDudeDelay;
public final static String KEY_POSTAVRDUDE_DELAY_MS = "postAvrdudeDelayMs";
/**
* Other AVRDude options. Free text for avrdude options not directly
* supported by the plugin
*/
private String fOtherOptions;
public final static String KEY_OTHER_OPTIONS = "otherOptions";
/** Flag to mark modifications of this config */
private boolean fDirty;
/**
* Constructs a ProgrammerConfig with the given id and set the default values.
*
* @param id
* Unique id of the configuration.
*/
protected ProgrammerConfig(String id) {
fId = id;
fDirty = false;
defaults();
}
/**
* Constructs a ProgrammerConfig with the given id and load its values from the given
* <code>Preferences</code>.
*
* @param id
* Unique id of the configuration.
* @param prefs
* <code>Preferences</code> node from which to load.
*/
protected ProgrammerConfig(String id, Preferences prefs) {
fId = id;
fDirty = false;
loadFromPrefs(prefs);
}
/**
* Make a copy of the given <code>ProgrammerConfig</code>.
* <p>
* The copy does not reflect any changes of the original or vv.
* </p>
* Note: This copy can be saved, even when the given original has been deleted.
* </p>
*
* @param config
*/
protected ProgrammerConfig(ProgrammerConfig config) {
fId = config.fId;
loadFromConfig(config);
}
/**
* Persist this configuration to the preference storage.
* <p>
* This will not do anything if the configuration has not been modified.
* </p>
*
* @throws BackingStoreException
* If this configuration cannot be written to the preference storage area.
*/
protected synchronized void save(Preferences prefs) throws BackingStoreException {
if (fDirty) {
// write all values to the preferences
prefs.put(KEY_NAME, fName);
prefs.put(KEY_DESCRIPTION, fDescription);
prefs.put(KEY_PROGRAMMER, fProgrammer);
prefs.put(KEY_PORT, fPort);
prefs.put(KEY_BAUDRATE, fBaudrate);
prefs.put(KEY_EXITSPEC_RESET, fExitReset);
prefs.put(KEY_EXITSPEC_VCC, fExitVcc);
prefs.put(KEY_POSTAVRDUDE_DELAY_MS, fPostAVRDudeDelay);
prefs.put(KEY_OTHER_OPTIONS, fOtherOptions);
// flush the Preferences to the persistent storage
prefs.flush();
}
}
/**
* @return A <code>List<Strings></code> with all avrdude options as defined by this
* configuration
*/
public List<String> getArguments() {
List<String> args = new ArrayList<String>();
args.add("-c" + fProgrammer);
if (fPort.length() > 0) {
args.add("-P" + fPort);
}
if (fBaudrate.length() > 0) {
args.add("-b" + fBaudrate);
}
StringBuffer exitspec = new StringBuffer();
if (fExitReset.length() > 0) {
exitspec.append(fExitReset);
}
if (fExitVcc.length() > 0) {
if (fExitReset.length() > 0) {
exitspec.append(",");
}
exitspec.append(fExitVcc);
}
if (exitspec.length() > 0) {
args.add("-E" + exitspec.toString());
}
if (fOtherOptions!=null && fOtherOptions.length() > 0) {
String[] options = fOtherOptions.split("\\s+");
for (String option : options) {
args.add(option);
}
}
return args;
}
/**
* Gets the ID of this configuration.
*
* @return <code>String</code> with the ID.
*/
public String getId() {
return fId;
}
/**
* Sets the name of this configuration.
* <p>
* The name must not contain any slashes ('/'), as this would cause problems with the preference
* store.
* </p>
*
* @param name
* <code>String</code> with the new name.
*/
public void setName(String name) {
Assert.isTrue(!name.contains("/"));
fName = name;
fDirty = true;
}
/**
* @return The current name of this configuration.
*/
public String getName() {
return fName;
}
/**
* Sets the description of this configuration.
*
* @param name
* <code>String</code> with the new description.
*/
public void setDescription(String description) {
fDescription = description;
fDirty = true;
}
/**
* @return The current description of this configuration.
*/
public String getDescription() {
return fDescription;
}
/**
* Sets the avrdude programmer id of this configuration.
* <p>
* The programmer id is not checked for validity. It is up to the caller to ensure that the
* given id is valid.
* </p>
*
* @param name
* <code>String</code> with the new programmer id.
*/
public void setProgrammer(String programmer) {
fProgrammer = programmer;
fDirty = true;
}
/**
* @return The current avrdude programmer id of this configuration.
*/
public String getProgrammer() {
return fProgrammer;
}
/**
* Sets the port of this configuration.
* <p>
* The port name is not checked for validity. It is up to the caller to ensure that the port
* name is valid.
* </p>
*
* @param name
* <code>String</code> with the new port, may be an empty String to use the avrdude
* default port.
*/
public void setPort(String port) {
fPort = port;
fDirty = true;
}
/**
* @return The current port of this configuration, empty if default is to be used.
*/
public String getPort() {
return fPort;
}
/**
* Sets the baudrate of this configuration.
* <p>
* The baudrate is not checked for validity. It is up to the caller to ensure that the baudrate
* is a valid integer (or empty).
* </p>
*
* @param name
* <code>String</code> with the new baudrate, may be an empty String to use the
* avrdude default baudrate.
*/
public void setBaudrate(String baudrate) {
fBaudrate = baudrate;
fDirty = true;
}
/**
* @return The current baudrate of this configuration, empty if default is to be used.
*/
public String getBaudrate() {
return fBaudrate;
}
/**
* Sets the reset line ExitSpec of this configuration.
* <p>
* Only the values "reset", "noreset" and "" (empty String) are valid. It is up to the caller to
* ensure that the given value is valid.
* </p>
*
* @param name
* <code>String</code> with the resetline ExitSpec, may be an empty String to use
* the avrdude default.
*/
public void setExitspecResetline(String resetline) {
fExitReset = resetline;
fDirty = true;
}
/**
* @return The current reset line ExitSpec of this configuration, empty if default is to be
* used.
*/
public String getExitspecResetline() {
return fExitReset;
}
/**
* Sets the Vcc lines ExitSpec of this configuration.
* <p>
* Only the values "vcc", "novcc" and "" (empty String) are valid.It is up to the caller to
* ensure that the given value is valid.
* </p>
*
* @param name
* <code>String</code> with the resetline ExitSpec, may be an empty String to use
* the avrdude default.
*/
public void setExitspecVCCline(String vccline) {
fExitVcc = vccline;
fDirty = true;
}
/**
* @return The current Vcc lines ExitSpec of this configuration, empty if default is to be used.
*/
public String getExitspecVCCline() {
return fExitVcc;
}
/**
* Sets the post avrdude delay value in milliseconds.
* <p>
* The delay value is not checked for validity. It is up to the caller to ensure that the value
* is a valid integer (or empty).
* </p>
*
* @param delay
* String with integer value.
*/
public void setPostAvrdudeDelay(String delay) {
fPostAVRDudeDelay = delay;
fDirty = true;
}
/**
* Get the selected post avrdude delay value in milliseconds.
*
* @return Selected delay value or an empty string if no delay is required.
*/
public String getPostAvrdudeDelay() {
return fPostAVRDudeDelay;
}
/**
*
* @return the free text options passed as is to AVRDude
*/
public String getOtherOptions() {
return fOtherOptions;
}
/**
* Sets the free text options passed as is to AVRDude
*
* @param otherOptions
* free text to be passed as extra options to AVRDude
*/
public void setOtherOptions(String fOtherOptions) {
this.fOtherOptions = fOtherOptions;
}
/**
* Load the values of this Configuration from the preference storage area.
*
* @param prefs
* <code>Preferences</code> node for this configuration
*/
private void loadFromPrefs(Preferences prefs) {
fName = prefs.get(KEY_NAME, "");
fDescription = prefs.get(KEY_DESCRIPTION, "");
fProgrammer = prefs.get(KEY_PROGRAMMER, "");
fPort = prefs.get(KEY_PORT, "");
fBaudrate = prefs.get(KEY_BAUDRATE, "");
fExitReset = prefs.get(KEY_EXITSPEC_RESET, "");
fExitVcc = prefs.get(KEY_EXITSPEC_VCC, "");
fPostAVRDudeDelay = prefs.get(KEY_POSTAVRDUDE_DELAY_MS, "");
fOtherOptions = prefs.get(KEY_OTHER_OPTIONS, "");
}
/**
* Load the values of this Configuration from the given <code>ProgrammerConfig</code>.
*
* @param prefs
* Source <code>ProgrammerConfig</code>.
*/
protected void loadFromConfig(ProgrammerConfig config) {
fName = config.fName;
fDescription = config.fDescription;
fProgrammer = config.fProgrammer;
fPort = config.fPort;
fBaudrate = config.fBaudrate;
fExitReset = config.fExitReset;
fExitVcc = config.fExitVcc;
fDirty = config.fDirty;
fPostAVRDudeDelay = config.fPostAVRDudeDelay;
fOtherOptions = config.getOtherOptions();
}
/**
* Reset this Configuration to the default values.
* <p>
* The ID and the Name of this Configuration are not changed.
* </p>
*/
public void defaults() {
// Set the defaults
fDescription = DEFAULT_DESCRIPTION;
fProgrammer = DEFAULT_PROGRAMMER;
fPort = "";
fBaudrate = "";
fExitReset = "";
fExitVcc = "";
fPostAVRDudeDelay = "";
fOtherOptions = "";
}
/*
* (non-Javadoc)
*
* @see java.lang.Object#toString()
*/
@Override
public String toString() {
// for the debugger
return fName + " (" + fDescription + "): " + getArguments();
}
}