1
0
mirror of https://github.com/arduino/Arduino.git synced 2025-02-19 13:54:23 +01:00

First integration of the Arduino code in Processing 5503: PreProcessor and Compiler have been integrated with changes to the Sketch.

Compilation still has problems (Thread error on success, and can't handle non-pde files in a sketch).
Modified the Mac OS X make.sh to copy the hardware, avr tools, and example over.
Removing some of the antlr stuff.  
Disabling the Commander (command-line execution) for now.
Added Library, LibraryManager, and Target.
Added support for prefixed preferences (e.g. for boards and programmers).
This commit is contained in:
David A. Mellis 2009-06-01 08:32:11 +00:00
parent 22ed6cdb73
commit 2fa8deb92d
163 changed files with 26394 additions and 3624 deletions

BIN
app/lib/oro.jar Normal file

Binary file not shown.

View File

@ -74,6 +74,7 @@ public class Base {
static private File examplesFolder;
static private File librariesFolder;
static private File toolsFolder;
static private File hardwareFolder;
// maps imported packages to their library folder
static HashMap<String, File> importToLibraryTable;
@ -186,7 +187,7 @@ public class Base {
"p { font: 11pt \"Lucida Grande\"; margin-top: 8px }"+
"</style> </head> <body>" +
"<b>The standard menu bar has been disabled.</b>" +
"<p>Due to an Apple bug, the Processing menu bar " +
"<p>Due to an Apple bug, the Arduino menu bar " +
"is unusable on Mac OS X 10.5. <br>" +
"As a workaround, the menu bar will be placed inside " +
"the editor window. This <br>setting can be changed in the " +
@ -224,7 +225,7 @@ public class Base {
platform.setLookAndFeel();
} catch (Exception e) {
System.err.println("Non-fatal error while setting the Look & Feel.");
System.err.println("The error message follows, however Processing should run fine.");
System.err.println("The error message follows, however Arduino should run fine.");
System.err.println(e.getMessage());
//e.printStackTrace();
}
@ -272,7 +273,7 @@ public class Base {
} catch (ClassNotFoundException cnfe) {
Base.showPlatforms();
Base.showError("Please install JDK 1.5 or later",
"Processing requires a full JDK (not just a JRE)\n" +
"Arduino requires a full JDK (not just a JRE)\n" +
"to run. Please install JDK 1.5 or later.\n" +
"More information can be found in the reference.", cnfe);
}
@ -298,9 +299,9 @@ public class Base {
if (!skechbookFolder.exists()) {
Base.showWarning("Sketchbook folder disappeared",
"The sketchbook folder no longer exists.\n" +
"Processing will switch to the default sketchbook\n" +
"Arduino will switch to the default sketchbook\n" +
"location, and create a new sketchbook folder if\n" +
"necessary. Procesing will then stop talking about\n" +
"necessary. Arduino will then stop talking about\n" +
"himself in the third person.", null);
sketchbookPath = null;
}
@ -668,7 +669,7 @@ public class Base {
public void handleOpenPrompt() {
// get the frontmost window frame for placing file dialog
FileDialog fd = new FileDialog(activeEditor,
"Open a Processing sketch...",
"Open an Arduino sketch...",
FileDialog.LOAD);
// This was annoying people, so disabled it in 0125.
//fd.setDirectory(Preferences.get("sketchbook.path"));
@ -792,7 +793,7 @@ public class Base {
"p { font: 11pt \"Lucida Grande\"; margin-top: 8px }"+
"</style> </head>" +
"<b>Are you sure you want to Quit?</b>" +
"<p>Closing the last open sketch will quit Processing.";
"<p>Closing the last open sketch will quit Arduino.";
int result = JOptionPane.showOptionDialog(editor,
prompt,
@ -1022,7 +1023,7 @@ public class Base {
} else {
showWarning("Sketch Does Not Exist",
"The selected sketch no longer exists.\n" +
"You may need to restart Processing to update\n" +
"You may need to restart Arduino to update\n" +
"the sketchbook menu.", null);
}
}
@ -1310,7 +1311,7 @@ public class Base {
settingsFolder = platform.getSettingsFolder();
} catch (Exception e) {
showError("Problem getting data folder",
"Error getting the Processing data folder.", e);
"Error getting the Arduino data folder.", e);
}
}
@ -1318,7 +1319,7 @@ public class Base {
if (!settingsFolder.exists()) {
if (!settingsFolder.mkdirs()) {
showError("Settings issues",
"Processing cannot run because it could not\n" +
"Arduino cannot run because it could not\n" +
"create a folder to store your settings.", null);
}
}
@ -1396,7 +1397,30 @@ public class Base {
static public String getToolsPath() {
return toolsFolder.getAbsolutePath();
}
static public File getHardwareFolder() {
// calculate on the fly because it's needed by Preferences.init() to find
// the boards.txt and programmers.txt preferences files (which happens
// before the other folders / paths get cached).
return getContentFile("hardware");
}
static public String getHardwarePath() {
return getHardwareFolder().getAbsolutePath();
}
static public String getAvrBasePath() {
if(Base.isLinux()) {
return ""; // avr tools are installed system-wide and in the path
} else {
return getHardwarePath() + File.separator + "tools" +
File.separator + "avr" + File.separator + "bin" + File.separator;
}
}
static public File getSketchbookFolder() {
return new File(Preferences.get("sketchbook.path"));
@ -1426,7 +1450,7 @@ public class Base {
if (!result) {
showError("You forgot your sketchbook",
"Processing cannot run because it could not\n" +
"Arduino cannot run because it could not\n" +
"create a folder to store your sketchbook.", null);
}

View File

@ -1561,7 +1561,10 @@ public class Editor extends JFrame implements RunnerListener {
presenting = present;
try {
String appletClassName = sketch.compile();
// XXX: DAM: don't hardcode this to "arduino"
String appletClassName = sketch.compile(
new Target(Base.getHardwarePath() + File.separator + "cores",
"arduino"));
if (appletClassName != null) {
runtime = new Runner(sketch, appletClassName, presenting, Editor.this);

View File

@ -71,7 +71,7 @@ public class Platform {
public File getSettingsFolder() throws Exception {
// otherwise make a .processing directory int the user's home dir
File home = new File(System.getProperty("user.home"));
File dataFolder = new File(home, ".processing");
File dataFolder = new File(home, ".arduino");
return dataFolder;
/*

View File

@ -146,6 +146,7 @@ public class Preferences {
static Hashtable defaults;
static Hashtable table = new Hashtable();;
static Hashtable prefixes = new Hashtable();
static File preferencesFile;
@ -221,6 +222,25 @@ public class Preferences {
// "You'll need to reinstall Processing.", te);
// }
}
try {
load(new FileInputStream(new File(Base.getHardwareFolder(), "boards.txt")),
"boards");
} catch (Exception ex) {
Base.showError("Error reading board definitions",
"Error reading the board definitions file (" +
new File(Base.getHardwareFolder(), "boards.txt").getAbsolutePath() + "). " +
"Please re-download or re-unzip Arduino.\n", ex);
}
try {
load(new FileInputStream(new File(Base.getHardwareFolder(), "programmers.txt")),
"programmers");
} catch (Exception ex) {
Base.showError("Error reading programmers definitions",
"Error reading the programmers definitions file. " +
"Please re-download or re-unzip Arduino.\n", ex);
}
}
@ -701,6 +721,16 @@ public class Preferences {
static protected void load(InputStream input) throws IOException {
load(input, table);
}
static protected void load(InputStream input, String prefix) throws IOException {
Map table = new LinkedHashMap();
prefixes.put(prefix, table);
load(input, table);
}
static protected void load(InputStream input, Map table) throws IOException {
String[] lines = PApplet.loadStrings(input); // Reads as UTF-8
for (String line : lines) {
if ((line.length() == 0) ||
@ -755,6 +785,18 @@ public class Preferences {
//}
static public String get(String attribute /*, String defaultValue */) {
// if the attribute starts with a prefix used by one of our subsidiary
// preference files, look up the attribute in that file's Hashtable
// (don't override with or fallback to the main file). otherwise,
// look up the attribute in the main file's Hashtable.
Map table = Preferences.table;
if (attribute.indexOf('.') != -1) {
String prefix = attribute.substring(0, attribute.indexOf('.'));
if (prefixes.containsKey(prefix)) {
table = (Map) prefixes.get(prefix);
attribute = attribute.substring(attribute.indexOf('.') + 1);
}
}
return (String) table.get(attribute);
/*
//String value = (properties != null) ?
@ -767,6 +809,28 @@ public class Preferences {
}
/**
* Get the top-level key prefixes defined in the subsidiary file loaded with
* the given prefix. For example, if the file contains:
* foo.count=1
* bar.count=2
* baz.count=3
* this will return { "foo", "bar", "baz" }.
*/
static public Iterator getSubKeys(String prefix) {
if (!prefixes.containsKey(prefix))
return null;
Set subkeys = new LinkedHashSet();
for (Iterator i = ((Map) prefixes.get(prefix)).keySet().iterator(); i.hasNext(); ) {
String subkey = (String) i.next();
if (subkey.indexOf('.') != -1)
subkey = subkey.substring(0, subkey.indexOf('.'));
subkeys.add(subkey);
}
return subkeys.iterator();
}
static public String getDefault(String attribute) {
return (String) defaults.get(attribute);
}

View File

@ -24,7 +24,10 @@
package processing.app;
import processing.app.debug.Compiler;
import processing.app.debug.Library;
import processing.app.debug.LibraryManager;
import processing.app.debug.RunnerException;
import processing.app.debug.Target;
import processing.app.preproc.*;
import processing.core.*;
@ -92,7 +95,7 @@ public class Sketch {
* DLLs or JNILIBs.
*/
private String libraryPath;
private ArrayList<File> importedLibraries;
public Vector importedLibraries;
/**
* path is location of the main .pde file, because this is also
@ -366,7 +369,7 @@ public class Sketch {
if (renamingCode) { // If creating a new tab, don't show this error
if (current == code[0]) { // If this is the main tab, disallow
Base.showWarning("Problem with rename",
"The main .pde file cannot be .java file.\n" +
"The main file can't use an extension.\n" +
"(It may be time for your to graduate to a\n" +
"\"real\" programming environment)", null);
return;
@ -912,10 +915,8 @@ public class Sketch {
// if the file appears to be code related, drop it
// into the code folder, instead of the data folder
if (filename.toLowerCase().endsWith(".class") ||
filename.toLowerCase().endsWith(".jar") ||
filename.toLowerCase().endsWith(".dll") ||
filename.toLowerCase().endsWith(".jnilib") ||
if (filename.toLowerCase().endsWith(".o") ||
filename.toLowerCase().endsWith(".a") ||
filename.toLowerCase().endsWith(".so")) {
//if (!codeFolder.exists()) codeFolder.mkdirs();
@ -1026,7 +1027,7 @@ public class Sketch {
// make sure the user didn't hide the sketch folder
ensureExistence();
String list[] = Compiler.packageListFromClassPath(jarPath);
String list[] = Compiler.headerListFromIncludePath(jarPath);
// import statements into the main sketch file (code[0])
// if the current code is a .java file, insert into current
@ -1039,9 +1040,9 @@ public class Sketch {
// commented out, then this will be a problem.
StringBuffer buffer = new StringBuffer();
for (int i = 0; i < list.length; i++) {
buffer.append("import ");
buffer.append("#include <");
buffer.append(list[i]);
buffer.append(".*;\n");
buffer.append(">\n");
}
buffer.append('\n');
buffer.append(editor.getText());
@ -1138,7 +1139,7 @@ public class Sketch {
* X. afterwards, some of these steps need a cleanup function
* </PRE>
*/
protected String compile() throws RunnerException {
protected String compile(Target target) throws RunnerException {
// make sure the user didn't hide the sketch folder
ensureExistence();
@ -1169,7 +1170,7 @@ public class Sketch {
cleanup();
// handle preprocessing the main file's code
return build(tempBuildFolder.getAbsolutePath());
return build(tempBuildFolder.getAbsolutePath(), target);
}
@ -1188,31 +1189,31 @@ public class Sketch {
* @param buildPath Location to copy all the .java files
* @return null if compilation failed, main class name if not
*/
public String preprocess(String buildPath) throws RunnerException {
public String preprocess(String buildPath, Target target) throws RunnerException {
// make sure the user didn't hide the sketch folder
ensureExistence();
String[] codeFolderPackages = null;
classPath = buildPath;
// figure out the contents of the code folder to see if there
// are files that need to be added to the imports
if (codeFolder.exists()) {
libraryPath = codeFolder.getAbsolutePath();
// get a list of .jar files in the "code" folder
// (class files in subfolders should also be picked up)
String codeFolderClassPath =
Compiler.contentsToClassPath(codeFolder);
// append the jar files in the code folder to the class path
classPath += File.pathSeparator + codeFolderClassPath;
// get list of packages found in those jars
codeFolderPackages =
Compiler.packageListFromClassPath(codeFolderClassPath);
} else {
libraryPath = "";
}
// // figure out the contents of the code folder to see if there
// // are files that need to be added to the imports
// if (codeFolder.exists()) {
// libraryPath = codeFolder.getAbsolutePath();
//
// // get a list of .jar files in the "code" folder
// // (class files in subfolders should also be picked up)
// String codeFolderClassPath =
// Compiler.contentsToClassPath(codeFolder);
// // append the jar files in the code folder to the class path
// classPath += File.pathSeparator + codeFolderClassPath;
// // get list of packages found in those jars
// codeFolderPackages =
// Compiler.packageListFromClassPath(codeFolderClassPath);
//
// } else {
// libraryPath = "";
// }
// 1. concatenate all .pde files to the 'main' pde
// store line number for starting point of each code bit
@ -1260,16 +1261,6 @@ public class Sketch {
// it only applies to the code after it's been written to the .java file.
int headerOffset = 0;
PdePreprocessor preprocessor = new PdePreprocessor();
try {
headerOffset = preprocessor.writePrefix(bigCode.toString(),
buildPath,
name,
codeFolderPackages);
} catch (FileNotFoundException fnfe) {
fnfe.printStackTrace();
String msg = "Build folder disappeared or could not be written";
throw new RunnerException(msg);
}
// 2. run preproc on that code using the sugg class name
// to create a single .java file and write to buildpath
@ -1279,7 +1270,12 @@ public class Sketch {
try {
// if (i != 0) preproc will fail if a pde file is not
// java mode, since that's required
String className = preprocessor.write();
String className = preprocessor.write(bigCode.toString(),
buildPath,
name,
codeFolderPackages,
target);
headerOffset = preprocessor.headerCount;
if (className == null) {
throw new RunnerException("Could not find main class");
@ -1294,106 +1290,12 @@ public class Sketch {
}
// store this for the compiler and the runtime
primaryClassName = className;
} catch (antlr.RecognitionException re) {
// re also returns a column that we're not bothering with for now
// first assume that it's the main file
int errorFile = 0;
int errorLine = re.getLine() - 1;
// then search through for anyone else whose preprocName is null,
// since they've also been combined into the main pde.
for (int i = 1; i < codeCount; i++) {
if (code[i].isExtension("pde") &&
(code[i].getPreprocOffset() < errorLine)) {
// keep looping until the errorLine is past the offset
errorFile = i;
}
}
errorLine -= code[errorFile].getPreprocOffset();
// System.out.println("i found this guy snooping around..");
// System.out.println("whatcha want me to do with 'im boss?");
// System.out.println(errorLine + " " + errorFile + " " + code[errorFile].getPreprocOffset());
String msg = re.getMessage();
if (msg.equals("expecting RCURLY, found 'null'")) {
// This can be a problem since the error is sometimes listed as a line
// that's actually past the number of lines. For instance, it might
// report "line 15" of a 14 line program. Added code to highlightLine()
// inside Editor to deal with this situation (since that code is also
// useful for other similar situations).
throw new RunnerException("Found one too many { characters " +
"without a } to match it.",
errorFile, errorLine, re.getColumn());
}
if (msg.indexOf("expecting RBRACK") != -1) {
System.err.println(msg);
throw new RunnerException("Syntax error, " +
"maybe a missing ] character?",
errorFile, errorLine, re.getColumn());
}
if (msg.indexOf("expecting SEMI") != -1) {
System.err.println(msg);
throw new RunnerException("Syntax error, " +
"maybe a missing semicolon?",
errorFile, errorLine, re.getColumn());
}
if (msg.indexOf("expecting RPAREN") != -1) {
System.err.println(msg);
throw new RunnerException("Syntax error, " +
"maybe a missing right parenthesis?",
errorFile, errorLine, re.getColumn());
}
if (msg.indexOf("preproc.web_colors") != -1) {
throw new RunnerException("A web color (such as #ffcc00) " +
"must be six digits.",
errorFile, errorLine, re.getColumn(), false);
}
//System.out.println("msg is " + msg);
throw new RunnerException(msg, errorFile,
errorLine, re.getColumn());
} catch (antlr.TokenStreamRecognitionException tsre) {
// while this seems to store line and column internally,
// there doesn't seem to be a method to grab it..
// so instead it's done using a regexp
// System.err.println("and then she tells me " + tsre.toString());
// TODO not tested since removing ORO matcher.. ^ could be a problem
String mess = "^line (\\d+):(\\d+):\\s";
String[] matches = PApplet.match(tsre.toString(), mess);
if (matches != null) {
int errorLine = Integer.parseInt(matches[1]) - 1;
int errorColumn = Integer.parseInt(matches[2]);
int errorFile = 0;
for (int i = 1; i < codeCount; i++) {
if (code[i].isExtension("pde") &&
(code[i].getPreprocOffset() < errorLine)) {
errorFile = i;
}
}
errorLine -= code[errorFile].getPreprocOffset();
throw new RunnerException(tsre.getMessage(),
errorFile, errorLine, errorColumn);
} else {
// this is bad, defaults to the main class.. hrm.
String msg = tsre.toString();
throw new RunnerException(msg, 0, -1, -1);
}
primaryClassName = className + ".cpp";
} catch (FileNotFoundException fnfe) {
fnfe.printStackTrace();
String msg = "Build folder disappeared or could not be written";
throw new RunnerException(msg);
} catch (RunnerException pe) {
// RunnerExceptions are caught here and re-thrown, so that they don't
// get lost in the more general "Exception" handler below.
@ -1408,34 +1310,35 @@ public class Sketch {
// grab the imports from the code just preproc'd
importedLibraries = new ArrayList<File>();
for (String item : preprocessor.getExtraImports()) {
// remove things up to the last dot
int dot = item.lastIndexOf('.');
// http://dev.processing.org/bugs/show_bug.cgi?id=1145
String entry = (dot == -1) ? item : item.substring(0, dot);
File libFolder = (File) Base.importToLibraryTable.get(entry);
if (libFolder != null) {
importedLibraries.add(libFolder);
classPath += Compiler.contentsToClassPath(libFolder);
libraryPath += File.pathSeparator + libFolder.getAbsolutePath();
importedLibraries = new Vector();
ArrayList<String> imports = preprocessor.getExtraImports();
try {
LibraryManager libraryManager = new LibraryManager();
Collection libraries = libraryManager.getAll();
for (Iterator i = libraries.iterator(); i.hasNext(); ) {
Library library = (Library) i.next();
File[] headerFiles = library.getHeaderFiles();
for (int j = 0; j < headerFiles.length; j++)
for (int k = 0; k < imports.size(); k++)
if (headerFiles[j].getName().equals(imports.get(k)) &&
!importedLibraries.contains(library)) {
importedLibraries.add(library);
//System.out.println("Adding library " + library.getName());
}
}
} catch (IOException e) {
System.err.println("Error finding libraries:");
e.printStackTrace();
throw new RunnerException(e.getMessage());
}
// Finally, add the regular Java CLASSPATH
String javaClassPath = System.getProperty("java.class.path");
// Remove quotes if any.. An annoying (and frequent) Windows problem
if (javaClassPath.startsWith("\"") && javaClassPath.endsWith("\"")) {
javaClassPath = javaClassPath.substring(1, javaClassPath.length() - 1);
}
classPath += File.pathSeparator + javaClassPath;
// 3. then loop over the code[] and save each .java file
for (SketchCode sc : code) {
if (sc.isExtension("java")) {
if (sc.isExtension("c") || sc.isExtension("cpp") || sc.isExtension("h")) {
// no pre-processing services necessary for java files
// just write the the contents of 'program' to a .java file
// into the build directory. uses byte stream and reader/writer
@ -1468,14 +1371,14 @@ public class Sketch {
*
* @return null if compilation failed, main class name if not
*/
public String build(String buildPath) throws RunnerException {
public String build(String buildPath, Target target) throws RunnerException {
// run the preprocessor
String primaryClassName = preprocess(buildPath);
String primaryClassName = preprocess(buildPath, target);
// compile the program. errors will happen as a RunnerException
// that will bubble up to whomever called build().
Compiler compiler = new Compiler();
if (compiler.compile(this, buildPath, primaryClassName)) {
if (compiler.compile(this, buildPath, primaryClassName, target)) {
return primaryClassName;
}
return null;
@ -1491,369 +1394,9 @@ public class Sketch {
* Handle export to applet.
*/
public boolean exportApplet(String appletPath) throws RunnerException, IOException {
// Make sure the user didn't hide the sketch folder
ensureExistence();
// Reload the code when an external editor is being used
if (Preferences.getBoolean("editor.external")) {
// nuke previous files and settings
load();
}
File appletFolder = new File(appletPath);
// Nuke the old applet folder because it can cause trouble
if (Preferences.getBoolean("export.delete_target_folder")) {
Base.removeDir(appletFolder);
}
// Create a fresh applet folder (needed before preproc is run below)
appletFolder.mkdirs();
Hashtable zipFileContents = new Hashtable();
// build the sketch
String foundName = build(appletFolder.getPath());
// (already reported) error during export, exit this function
if (foundName == null) return false;
// If name != exportSketchName, then that's weirdness
// BUG unfortunately, that can also be a bug in the preproc :(
if (!name.equals(foundName)) {
Base.showWarning("Error during export",
"Sketch name is " + name + " but the sketch\n" +
"name in the code was " + foundName, null);
return false;
}
int wide = PApplet.DEFAULT_WIDTH;
int high = PApplet.DEFAULT_HEIGHT;
String renderer = "";
// This matches against any uses of the size() function, whether numbers
// or variables or whatever. This way, no warning is shown if size() isn't
// actually used in the applet, which is the case especially for anyone
// who is cutting/pasting from the reference.
String sizeRegex =
"(?:^|\\s|;)size\\s*\\(\\s*(\\S+)\\s*,\\s*(\\d+),?\\s*([^\\)]*)\\s*\\)";
String scrubbed = scrubComments(code[0].getProgram());
String[] matches = PApplet.match(scrubbed, sizeRegex);
if (matches != null) {
try {
wide = Integer.parseInt(matches[1]);
high = Integer.parseInt(matches[2]);
// Adding back the trim() for 0136 to handle Bug #769
if (matches.length == 4) renderer = matches[3].trim();
} catch (NumberFormatException e) {
// found a reference to size, but it didn't
// seem to contain numbers
final String message =
"The size of this applet could not automatically be\n" +
"determined from your code. You'll have to edit the\n" +
"HTML file to set the size of the applet.\n" +
"Use only numeric values (not variables) for the size()\n" +
"command. See the size() reference for an explanation.";
Base.showWarning("Could not find applet size", message, null);
}
} // else no size() command found
// Grab the Javadoc-style description from the main code.
// Originally tried to grab this with a regexp matcher, but it wouldn't
// span over multiple lines for the match. This could prolly be forced,
// but since that's the case better just to parse by hand.
StringBuffer dbuffer = new StringBuffer();
String lines[] = PApplet.split(code[0].getProgram(), '\n');
for (int i = 0; i < lines.length; i++) {
if (lines[i].trim().startsWith("/**")) { // this is our comment
// some smartass put the whole thing on the same line
//if (lines[j].indexOf("*/") != -1) break;
for (int j = i+1; j < lines.length; j++) {
if (lines[j].trim().endsWith("*/")) {
// remove the */ from the end, and any extra *s
// in case there's also content on this line
// nah, don't bother.. make them use the three lines
break;
}
int offset = 0;
while ((offset < lines[j].length()) &&
((lines[j].charAt(offset) == '*') ||
(lines[j].charAt(offset) == ' '))) {
offset++;
}
// insert the return into the html to help w/ line breaks
dbuffer.append(lines[j].substring(offset) + "\n");
}
}
}
String description = dbuffer.toString();
// Add links to all the code
StringBuffer sources = new StringBuffer();
for (int i = 0; i < codeCount; i++) {
sources.append("<a href=\"" + code[i].getFileName() + "\">" +
code[i].getPrettyName() + "</a> ");
}
// Copy the source files to the target, since we like
// to encourage people to share their code
for (int i = 0; i < codeCount; i++) {
try {
File exportedSource = new File(appletFolder, code[i].getFileName());
//Base.copyFile(code[i].getFile(), exportedSource);
code[i].copyTo(exportedSource);
} catch (IOException e) {
e.printStackTrace(); // ho hum, just move on...
}
}
// Use separate jarfiles whenever a library or code folder is in use.
boolean separateJar =
Preferences.getBoolean("export.applet.separate_jar_files") ||
codeFolder.exists() ||
(libraryPath.length() != 0);
// Copy the loading gif to the applet
String LOADING_IMAGE = "loading.gif";
// Check if the user already has their own loader image
File loadingImage = new File(folder, LOADING_IMAGE);
if (!loadingImage.exists()) {
File skeletonFolder = new File(Base.getContentFile("lib"), "export");
loadingImage = new File(skeletonFolder, LOADING_IMAGE);
}
Base.copyFile(loadingImage, new File(appletFolder, LOADING_IMAGE));
// Create new .jar file
FileOutputStream zipOutputFile =
new FileOutputStream(new File(appletFolder, name + ".jar"));
ZipOutputStream zos = new ZipOutputStream(zipOutputFile);
ZipEntry entry;
StringBuffer archives = new StringBuffer();
archives.append(name + ".jar");
// Add the manifest file
addManifest(zos);
// add the contents of the code folder to the jar
// unpacks all jar files, unless multi jar files selected in prefs
if (codeFolder.exists()) {
String includes = Compiler.contentsToClassPath(codeFolder);
String[] codeList = PApplet.splitTokens(includes, File.separator);
String cp = "";
for (int i = 0; i < codeList.length; i++) {
if (codeList[i].toLowerCase().endsWith(".jar") ||
codeList[i].toLowerCase().endsWith(".zip")) {
if (separateJar) {
File exportFile = new File(codeFolder, codeList[i]);
String exportFilename = exportFile.getName();
Base.copyFile(exportFile, new File(appletFolder, exportFilename));
} else {
cp += codeList[i] + File.pathSeparatorChar;
//packClassPathIntoZipFile(cp, zos);
}
}
}
if (!separateJar) {
packClassPathIntoZipFile(cp, zos, zipFileContents);
}
}
// add contents of 'library' folders to the jar file
// if a file called 'export.txt' is in there, it contains
// a list of the files that should be exported.
// otherwise, all files are exported.
for (File libraryFolder : importedLibraries) {
// Enumeration en = importedLibraries.elements();
// while (en.hasMoreElements()) {
// in the list is a File object that points the
// library sketch's "library" folder
// File libraryFolder = (File)en.nextElement();
File exportSettings = new File(libraryFolder, "export.txt");
Hashtable exportTable = readSettings(exportSettings);
String appletList = (String) exportTable.get("applet");
String exportList[] = null;
if (appletList != null) {
exportList = PApplet.splitTokens(appletList, ", ");
} else {
exportList = libraryFolder.list();
}
for (int i = 0; i < exportList.length; i++) {
if (exportList[i].equals(".") ||
exportList[i].equals("..")) continue;
exportList[i] = PApplet.trim(exportList[i]);
if (exportList[i].equals("")) continue;
File exportFile = new File(libraryFolder, exportList[i]);
if (!exportFile.exists()) {
System.err.println("File " + exportList[i] + " does not exist");
} else if (exportFile.isDirectory()) {
System.err.println("Ignoring sub-folder \"" + exportList[i] + "\"");
} else if (exportFile.getName().toLowerCase().endsWith(".zip") ||
exportFile.getName().toLowerCase().endsWith(".jar")) {
if (separateJar) {
String exportFilename = exportFile.getName();
Base.copyFile(exportFile, new File(appletFolder, exportFilename));
if (renderer.equals("OPENGL") &&
exportFilename.indexOf("natives") != -1) {
// don't add these to the archives list
} else {
archives.append("," + exportFilename);
}
} else {
String path = exportFile.getAbsolutePath();
packClassPathIntoZipFile(path, zos, zipFileContents);
}
} else { // just copy the file over.. prolly a .dll or something
Base.copyFile(exportFile,
new File(appletFolder, exportFile.getName()));
}
}
}
File bagelJar = Base.isMacOS() ?
Base.getContentFile("core.jar") :
Base.getContentFile("lib/core.jar");
if (separateJar) {
Base.copyFile(bagelJar, new File(appletFolder, "core.jar"));
archives.append(",core.jar");
} else {
String bagelJarPath = bagelJar.getAbsolutePath();
packClassPathIntoZipFile(bagelJarPath, zos, zipFileContents);
}
if (dataFolder.exists()) {
String dataFiles[] = Base.listFiles(dataFolder, false);
int offset = folder.getAbsolutePath().length() + 1;
for (int i = 0; i < dataFiles.length; i++) {
if (Base.isWindows()) {
dataFiles[i] = dataFiles[i].replace('\\', '/');
}
File dataFile = new File(dataFiles[i]);
if (dataFile.isDirectory()) continue;
// don't export hidden files
// skipping dot prefix removes all: . .. .DS_Store
if (dataFile.getName().charAt(0) == '.') continue;
entry = new ZipEntry(dataFiles[i].substring(offset));
zos.putNextEntry(entry);
zos.write(Base.loadBytesRaw(dataFile));
zos.closeEntry();
}
}
// add the project's .class files to the jar
// just grabs everything from the build directory
// since there may be some inner classes
// (add any .class files from the applet dir, then delete them)
// TODO this needs to be recursive (for packages)
String classfiles[] = appletFolder.list();
for (int i = 0; i < classfiles.length; i++) {
if (classfiles[i].endsWith(".class")) {
entry = new ZipEntry(classfiles[i]);
zos.putNextEntry(entry);
zos.write(Base.loadBytesRaw(new File(appletFolder, classfiles[i])));
zos.closeEntry();
}
}
// remove the .class files from the applet folder. if they're not
// removed, the msjvm will complain about an illegal access error,
// since the classes are outside the jar file.
for (int i = 0; i < classfiles.length; i++) {
if (classfiles[i].endsWith(".class")) {
File deadguy = new File(appletFolder, classfiles[i]);
if (!deadguy.delete()) {
Base.showWarning("Could not delete",
classfiles[i] + " could not \n" +
"be deleted from the applet folder. \n" +
"You'll need to remove it by hand.", null);
}
}
}
// close up the jar file
zos.flush();
zos.close();
//
// convert the applet template
// @@sketch@@, @@width@@, @@height@@, @@archive@@, @@source@@
// and now @@description@@
File htmlOutputFile = new File(appletFolder, "index.html");
// UTF-8 fixes http://dev.processing.org/bugs/show_bug.cgi?id=474
PrintWriter htmlWriter = PApplet.createWriter(htmlOutputFile);
InputStream is = null;
// if there is an applet.html file in the sketch folder, use that
File customHtml = new File(folder, "applet.html");
if (customHtml.exists()) {
is = new FileInputStream(customHtml);
}
if (is == null) {
if (renderer.equals("OPENGL")) {
is = Base.getLibStream("export/applet-opengl.html");
} else {
is = Base.getLibStream("export/applet.html");
}
}
BufferedReader reader = PApplet.createReader(is);
String line = null;
while ((line = reader.readLine()) != null) {
if (line.indexOf("@@") != -1) {
StringBuffer sb = new StringBuffer(line);
int index = 0;
while ((index = sb.indexOf("@@sketch@@")) != -1) {
sb.replace(index, index + "@@sketch@@".length(),
name);
}
while ((index = sb.indexOf("@@source@@")) != -1) {
sb.replace(index, index + "@@source@@".length(),
sources.toString());
}
while ((index = sb.indexOf("@@archive@@")) != -1) {
sb.replace(index, index + "@@archive@@".length(),
archives.toString());
}
while ((index = sb.indexOf("@@width@@")) != -1) {
sb.replace(index, index + "@@width@@".length(),
String.valueOf(wide));
}
while ((index = sb.indexOf("@@height@@")) != -1) {
sb.replace(index, index + "@@height@@".length(),
String.valueOf(high));
}
while ((index = sb.indexOf("@@description@@")) != -1) {
sb.replace(index, index + "@@description@@".length(),
description);
}
line = sb.toString();
}
htmlWriter.println(line);
}
reader.close();
htmlWriter.flush();
htmlWriter.close();
return true;
return false;
}
/**
* Replace all commented portions of a given String as spaces.
* Utility function used here and in the preprocessor.
@ -1906,185 +1449,6 @@ public class Sketch {
public boolean exportApplicationPrompt() throws IOException, RunnerException {
JPanel panel = new JPanel();
panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS));
panel.add(Box.createVerticalStrut(6));
//Box panel = Box.createVerticalBox();
//Box labelBox = Box.createHorizontalBox();
// String msg = "<html>Click Export to Application to create a standalone, " +
// "double-clickable application for the selected plaforms.";
// String msg = "Export to Application creates a standalone, \n" +
// "double-clickable application for the selected plaforms.";
String line1 = "Export to Application creates double-clickable,";
String line2 = "standalone applications for the selected plaforms.";
JLabel label1 = new JLabel(line1, SwingConstants.CENTER);
JLabel label2 = new JLabel(line2, SwingConstants.CENTER);
label1.setAlignmentX(Component.LEFT_ALIGNMENT);
label2.setAlignmentX(Component.LEFT_ALIGNMENT);
// label1.setAlignmentX();
// label2.setAlignmentX(0);
panel.add(label1);
panel.add(label2);
int wide = label2.getPreferredSize().width;
panel.add(Box.createVerticalStrut(12));
final JCheckBox windowsButton = new JCheckBox("Windows");
//windowsButton.setMnemonic(KeyEvent.VK_W);
windowsButton.setSelected(Preferences.getBoolean("export.application.platform.windows"));
windowsButton.addItemListener(new ItemListener() {
public void itemStateChanged(ItemEvent e) {
Preferences.setBoolean("export.application.platform.windows", windowsButton.isSelected());
}
});
final JCheckBox macosxButton = new JCheckBox("Mac OS X");
//macosxButton.setMnemonic(KeyEvent.VK_M);
macosxButton.setSelected(Preferences.getBoolean("export.application.platform.macosx"));
macosxButton.addItemListener(new ItemListener() {
public void itemStateChanged(ItemEvent e) {
Preferences.setBoolean("export.application.platform.macosx", macosxButton.isSelected());
}
});
final JCheckBox linuxButton = new JCheckBox("Linux");
//linuxButton.setMnemonic(KeyEvent.VK_L);
linuxButton.setSelected(Preferences.getBoolean("export.application.platform.linux"));
linuxButton.addItemListener(new ItemListener() {
public void itemStateChanged(ItemEvent e) {
Preferences.setBoolean("export.application.platform.linux", linuxButton.isSelected());
}
});
JPanel platformPanel = new JPanel();
//platformPanel.setLayout(new BoxLayout(platformPanel, BoxLayout.X_AXIS));
platformPanel.add(windowsButton);
platformPanel.add(Box.createHorizontalStrut(6));
platformPanel.add(macosxButton);
platformPanel.add(Box.createHorizontalStrut(6));
platformPanel.add(linuxButton);
platformPanel.setBorder(new TitledBorder("Platforms"));
//Dimension goodIdea = new Dimension(wide, platformPanel.getPreferredSize().height);
//platformPanel.setMaximumSize(goodIdea);
wide = Math.max(wide, platformPanel.getPreferredSize().width);
platformPanel.setAlignmentX(Component.LEFT_ALIGNMENT);
panel.add(platformPanel);
// Box indentPanel = Box.createHorizontalBox();
// indentPanel.add(Box.createHorizontalStrut(new JCheckBox().getPreferredSize().width));
final JCheckBox showStopButton = new JCheckBox("Show a Stop button");
//showStopButton.setMnemonic(KeyEvent.VK_S);
showStopButton.setSelected(Preferences.getBoolean("export.application.stop"));
showStopButton.addItemListener(new ItemListener() {
public void itemStateChanged(ItemEvent e) {
Preferences.setBoolean("export.application.stop", showStopButton.isSelected());
}
});
showStopButton.setEnabled(Preferences.getBoolean("export.application.fullscreen"));
showStopButton.setBorder(new EmptyBorder(3, 13, 6, 13));
// indentPanel.add(showStopButton);
// indentPanel.setAlignmentX(Component.LEFT_ALIGNMENT);
final JCheckBox fullScreenButton = new JCheckBox("Full Screen (Present mode)");
//fullscreenButton.setMnemonic(KeyEvent.VK_F);
fullScreenButton.setSelected(Preferences.getBoolean("export.application.fullscreen"));
fullScreenButton.addItemListener(new ItemListener() {
public void itemStateChanged(ItemEvent e) {
boolean sal = fullScreenButton.isSelected();
Preferences.setBoolean("export.application.fullscreen", sal);
showStopButton.setEnabled(sal);
}
});
fullScreenButton.setBorder(new EmptyBorder(3, 13, 3, 13));
JPanel optionPanel = new JPanel();
optionPanel.setLayout(new BoxLayout(optionPanel, BoxLayout.Y_AXIS));
optionPanel.add(fullScreenButton);
optionPanel.add(showStopButton);
// optionPanel.add(indentPanel);
optionPanel.setBorder(new TitledBorder("Options"));
wide = Math.max(wide, platformPanel.getPreferredSize().width);
//goodIdea = new Dimension(wide, optionPanel.getPreferredSize().height);
optionPanel.setAlignmentX(Component.LEFT_ALIGNMENT);
//optionPanel.setMaximumSize(goodIdea);
panel.add(optionPanel);
Dimension good;
//label1, label2, platformPanel, optionPanel
good = new Dimension(wide, label1.getPreferredSize().height);
label1.setMaximumSize(good);
good = new Dimension(wide, label2.getPreferredSize().height);
label2.setMaximumSize(good);
good = new Dimension(wide, platformPanel.getPreferredSize().height);
platformPanel.setMaximumSize(good);
good = new Dimension(wide, optionPanel.getPreferredSize().height);
optionPanel.setMaximumSize(good);
// JPanel actionPanel = new JPanel();
// optionPanel.setLayout(new BoxLayout(optionPanel, BoxLayout.X_AXIS));
// optionPanel.add(Box.createHorizontalGlue());
// final JDialog frame = new JDialog(editor, "Export to Application");
// JButton cancelButton = new JButton("Cancel");
// cancelButton.addActionListener(new ActionListener() {
// public void actionPerformed(ActionEvent e) {
// frame.dispose();
// return false;
// }
// });
// Add the buttons in platform-specific order
// if (PApplet.platform == PConstants.MACOSX) {
// optionPanel.add(cancelButton);
// optionPanel.add(exportButton);
// } else {
// optionPanel.add(exportButton);
// optionPanel.add(cancelButton);
// }
String[] options = { "Export", "Cancel" };
final JOptionPane optionPane = new JOptionPane(panel,
JOptionPane.PLAIN_MESSAGE,
//JOptionPane.QUESTION_MESSAGE,
JOptionPane.YES_NO_OPTION,
null,
options,
options[0]);
final JDialog dialog = new JDialog(editor, "Export Options", true);
dialog.setContentPane(optionPane);
optionPane.addPropertyChangeListener(new PropertyChangeListener() {
public void propertyChange(PropertyChangeEvent e) {
String prop = e.getPropertyName();
if (dialog.isVisible() &&
(e.getSource() == optionPane) &&
(prop.equals(JOptionPane.VALUE_PROPERTY))) {
//If you were going to check something
//before closing the window, you'd do
//it here.
dialog.setVisible(false);
}
}
});
dialog.pack();
dialog.setResizable(false);
Rectangle bounds = editor.getBounds();
dialog.setLocation(bounds.x + (bounds.width - dialog.getSize().width) / 2,
bounds.y + (bounds.height - dialog.getSize().height) / 2);
dialog.setVisible(true);
Object value = optionPane.getValue();
if (value.equals(options[0])) {
return exportApplication();
} else if (value.equals(options[1]) || value.equals(new Integer(-1))) {
// closed window by hitting Cancel or ESC
editor.statusNotice("Export to Application canceled.");
}
return false;
}
@ -2093,28 +1457,7 @@ public class Sketch {
* Export to application via GUI.
*/
protected boolean exportApplication() throws IOException, RunnerException {
if (Preferences.getBoolean("export.application.platform.windows")) {
String windowsPath =
new File(folder, "application.windows").getAbsolutePath();
if (!exportApplication(windowsPath, PConstants.WINDOWS)) {
return false;
}
}
if (Preferences.getBoolean("export.application.platform.macosx")) {
String macosxPath =
new File(folder, "application.macosx").getAbsolutePath();
if (!exportApplication(macosxPath, PConstants.MACOSX)) {
return false;
}
}
if (Preferences.getBoolean("export.application.platform.linux")) {
String linuxPath =
new File(folder, "application.linux").getAbsolutePath();
if (!exportApplication(linuxPath, PConstants.LINUX)) {
return false;
}
}
return true;
return false;
}
@ -2123,408 +1466,7 @@ public class Sketch {
*/
public boolean exportApplication(String destPath,
int exportPlatform) throws IOException, RunnerException {
// make sure the user didn't hide the sketch folder
ensureExistence();
// fix for issue posted on the board. make sure that the code
// is reloaded when exporting and an external editor is being used.
if (Preferences.getBoolean("editor.external")) {
// don't do from the command line
if (editor != null) {
// nuke previous files and settings
load();
}
}
File destFolder = new File(destPath);
if (Preferences.getBoolean("export.delete_target_folder")) {
Base.removeDir(destFolder);
}
destFolder.mkdirs();
// build the sketch
String foundName = build(destFolder.getPath());
// (already reported) error during export, exit this function
if (foundName == null) return false;
// if name != exportSketchName, then that's weirdness
// BUG unfortunately, that can also be a bug in the preproc :(
if (!name.equals(foundName)) {
Base.showWarning("Error during export",
"Sketch name is " + name + " but the sketch\n" +
"name in the code was " + foundName, null);
return false;
}
/// figure out where the jar files will be placed
File jarFolder = new File(destFolder, "lib");
/// where all the skeleton info lives
File skeletonFolder = new File(Base.getContentFile("lib"), "export");
/// on macosx, need to copy .app skeleton since that's
/// also where the jar files will be placed
File dotAppFolder = null;
if (exportPlatform == PConstants.MACOSX) {
dotAppFolder = new File(destFolder, name + ".app");
String APP_SKELETON = "skeleton.app";
//File dotAppSkeleton = new File(folder, APP_SKELETON);
File dotAppSkeleton = new File(skeletonFolder, APP_SKELETON);
Base.copyDir(dotAppSkeleton, dotAppFolder);
String stubName = "Contents/MacOS/JavaApplicationStub";
// need to set the stub to executable
// will work on osx or *nix, but just dies on windows, oh well..
if (Base.isWindows()) {
File warningFile = new File(destFolder, "readme.txt");
PrintWriter pw = PApplet.createWriter(warningFile);
pw.println("This application was created on Windows, which does not");
pw.println("properly support setting files as \"executable\",");
pw.println("a necessity for applications on Mac OS X.");
pw.println();
pw.println("To fix this, use the Terminal on Mac OS X, and from this");
pw.println("directory, type the following:");
pw.println();
pw.println("chmod +x " + dotAppFolder.getName() + "/" + stubName);
pw.flush();
pw.close();
} else {
File stubFile = new File(dotAppFolder, stubName);
String stubPath = stubFile.getAbsolutePath();
Runtime.getRuntime().exec(new String[] { "chmod", "+x", stubPath });
}
// set the jar folder to a different location than windows/linux
jarFolder = new File(dotAppFolder, "Contents/Resources/Java");
}
/// make the jar folder (windows and linux)
if (!jarFolder.exists()) jarFolder.mkdirs();
/// on windows, copy the exe file
if (exportPlatform == PConstants.WINDOWS) {
Base.copyFile(new File(skeletonFolder, "application.exe"),
new File(destFolder, this.name + ".exe"));
}
/// start copying all jar files
Vector jarListVector = new Vector();
/// create the main .jar file
Hashtable zipFileContents = new Hashtable();
FileOutputStream zipOutputFile =
new FileOutputStream(new File(jarFolder, name + ".jar"));
ZipOutputStream zos = new ZipOutputStream(zipOutputFile);
ZipEntry entry;
// add the manifest file so that the .jar can be double clickable
addManifest(zos);
// add the project's .class files to the jar
// (just grabs everything from the build directory,
// since there may be some inner classes)
// TODO this needs to be recursive (for packages)
String classfiles[] = destFolder.list();
for (int i = 0; i < classfiles.length; i++) {
if (classfiles[i].endsWith(".class")) {
entry = new ZipEntry(classfiles[i]);
zos.putNextEntry(entry);
zos.write(Base.loadBytesRaw(new File(destFolder, classfiles[i])));
zos.closeEntry();
}
}
// add the data folder to the main jar file
if (dataFolder.exists()) {
String dataFiles[] = Base.listFiles(dataFolder, false);
int offset = folder.getAbsolutePath().length() + 1;
for (int i = 0; i < dataFiles.length; i++) {
if (Base.isWindows()) {
dataFiles[i] = dataFiles[i].replace('\\', '/');
}
File dataFile = new File(dataFiles[i]);
if (dataFile.isDirectory()) continue;
// don't export hidden files
// skipping dot prefix removes all: . .. .DS_Store
if (dataFile.getName().charAt(0) == '.') continue;
entry = new ZipEntry(dataFiles[i].substring(offset));
zos.putNextEntry(entry);
zos.write(Base.loadBytesRaw(dataFile));
zos.closeEntry();
}
}
// add the contents of the code folder to the jar
if (codeFolder.exists()) {
String includes = Compiler.contentsToClassPath(codeFolder);
// Use tokens to get rid of extra blanks, which causes huge exports
String[] codeList = PApplet.splitTokens(includes, File.separator);
String cp = "";
for (int i = 0; i < codeList.length; i++) {
if (codeList[i].toLowerCase().endsWith(".jar") ||
codeList[i].toLowerCase().endsWith(".zip")) {
File exportFile = new File(codeFolder, codeList[i]);
String exportFilename = exportFile.getName();
Base.copyFile(exportFile, new File(jarFolder, exportFilename));
jarListVector.add(exportFilename);
} else {
cp += codeList[i] + File.separatorChar;
}
}
packClassPathIntoZipFile(cp, zos, zipFileContents);
}
zos.flush();
zos.close();
jarListVector.add(name + ".jar");
/// add core.jar to the jar destination folder
File bagelJar = Base.isMacOS() ?
Base.getContentFile("core.jar") :
Base.getContentFile("lib/core.jar");
Base.copyFile(bagelJar, new File(jarFolder, "core.jar"));
jarListVector.add("core.jar");
/// add contents of 'library' folders to the export
// if a file called 'export.txt' is in there, it contains
// a list of the files that should be exported.
// otherwise, all files are exported.
for (File libraryFolder : importedLibraries) {
//System.out.println(libraryFolder + " " + libraryFolder.getAbsolutePath());
// in the list is a File object that points the
// library sketch's "library" folder
File exportSettings = new File(libraryFolder, "export.txt");
Hashtable exportTable = readSettings(exportSettings);
String commaList = null;
String exportList[] = null;
// first check to see if there's something like application.blargh
if (exportPlatform == PConstants.MACOSX) {
commaList = (String) exportTable.get("application.macosx");
} else if (exportPlatform == PConstants.WINDOWS) {
commaList = (String) exportTable.get("application.windows");
} else if (exportPlatform == PConstants.LINUX) {
commaList = (String) exportTable.get("application.linux");
} else {
// next check to see if something for 'application' is specified
commaList = (String) exportTable.get("application");
}
if (commaList == null) {
// otherwise just dump the whole folder
exportList = libraryFolder.list();
} else {
exportList = PApplet.splitTokens(commaList, ", ");
}
// add each item from the library folder / export list to the output
for (int i = 0; i < exportList.length; i++) {
if (exportList[i].equals(".") ||
exportList[i].equals("..")) continue;
exportList[i] = PApplet.trim(exportList[i]);
if (exportList[i].equals("")) continue;
File exportFile = new File(libraryFolder, exportList[i]);
if (!exportFile.exists()) {
System.err.println("File " + exportList[i] + " does not exist");
} else if (exportFile.isDirectory()) {
System.err.println("Ignoring sub-folder \"" + exportList[i] + "\"");
} else if (exportFile.getName().toLowerCase().endsWith(".zip") ||
exportFile.getName().toLowerCase().endsWith(".jar")) {
//packClassPathIntoZipFile(exportFile.getAbsolutePath(), zos);
Base.copyFile(exportFile, new File(jarFolder, exportList[i]));
jarListVector.add(exportList[i]);
} else if ((exportPlatform == PConstants.MACOSX) &&
(exportFile.getName().toLowerCase().endsWith(".jnilib"))) {
// jnilib files can be placed in Contents/Resources/Java
Base.copyFile(exportFile, new File(jarFolder, exportList[i]));
} else {
// copy the file to the main directory.. prolly a .dll or something
Base.copyFile(exportFile,
new File(destFolder, exportFile.getName()));
}
}
}
/// create platform-specific CLASSPATH based on included jars
String jarList[] = new String[jarListVector.size()];
jarListVector.copyInto(jarList);
StringBuffer exportClassPath = new StringBuffer();
if (exportPlatform == PConstants.MACOSX) {
for (int i = 0; i < jarList.length; i++) {
if (i != 0) exportClassPath.append(":");
exportClassPath.append("$JAVAROOT/" + jarList[i]);
}
} else if (exportPlatform == PConstants.WINDOWS) {
for (int i = 0; i < jarList.length; i++) {
if (i != 0) exportClassPath.append(",");
exportClassPath.append(jarList[i]);
}
} else {
for (int i = 0; i < jarList.length; i++) {
if (i != 0) exportClassPath.append(":");
exportClassPath.append("$APPDIR/lib/" + jarList[i]);
}
}
/// figure out run options for the VM
String runOptions = Preferences.get("run.options");
if (Preferences.getBoolean("run.options.memory")) {
runOptions += " -Xms" +
Preferences.get("run.options.memory.initial") + "m";
runOptions += " -Xmx" +
Preferences.get("run.options.memory.maximum") + "m";
}
/// macosx: write out Info.plist (template for classpath, etc)
if (exportPlatform == PConstants.MACOSX) {
String PLIST_TEMPLATE = "template.plist";
File plistTemplate = new File(folder, PLIST_TEMPLATE);
if (!plistTemplate.exists()) {
plistTemplate = new File(skeletonFolder, PLIST_TEMPLATE);
}
File plistFile = new File(dotAppFolder, "Contents/Info.plist");
PrintWriter pw = PApplet.createWriter(plistFile);
String lines[] = PApplet.loadStrings(plistTemplate);
for (int i = 0; i < lines.length; i++) {
if (lines[i].indexOf("@@") != -1) {
StringBuffer sb = new StringBuffer(lines[i]);
int index = 0;
while ((index = sb.indexOf("@@vmoptions@@")) != -1) {
sb.replace(index, index + "@@vmoptions@@".length(),
runOptions);
}
while ((index = sb.indexOf("@@sketch@@")) != -1) {
sb.replace(index, index + "@@sketch@@".length(),
name);
}
while ((index = sb.indexOf("@@classpath@@")) != -1) {
sb.replace(index, index + "@@classpath@@".length(),
exportClassPath.toString());
}
while ((index = sb.indexOf("@@lsuipresentationmode@@")) != -1) {
sb.replace(index, index + "@@lsuipresentationmode@@".length(),
Preferences.getBoolean("export.application.fullscreen") ? "4" : "0");
}
lines[i] = sb.toString();
}
// explicit newlines to avoid Windows CRLF
pw.print(lines[i] + "\n");
}
pw.flush();
pw.close();
} else if (exportPlatform == PConstants.WINDOWS) {
File argsFile = new File(destFolder + "/lib/args.txt");
PrintWriter pw = PApplet.createWriter(argsFile);
pw.println(runOptions);
pw.println(this.name);
pw.println(exportClassPath);
pw.flush();
pw.close();
} else {
File shellScript = new File(destFolder, this.name);
PrintWriter pw = PApplet.createWriter(shellScript);
// do the newlines explicitly so that windows CRLF
// isn't used when exporting for unix
pw.print("#!/bin/sh\n\n");
//ps.print("APPDIR=`dirname $0`\n");
pw.print("APPDIR=$(dirname \"$0\")\n"); // more posix compliant
// another fix for bug #234, LD_LIBRARY_PATH ignored on some platforms
//ps.print("LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$APPDIR\n");
pw.print("java " + Preferences.get("run.options") +
" -Djava.library.path=\"$APPDIR\"" +
" -cp \"" + exportClassPath + "\"" +
" " + this.name + "\n");
pw.flush();
pw.close();
String shellPath = shellScript.getAbsolutePath();
// will work on osx or *nix, but just dies on windows, oh well..
if (!Base.isWindows()) {
Runtime.getRuntime().exec(new String[] { "chmod", "+x", shellPath });
}
}
/// copy the source files to the target
/// (we like to encourage people to share their code)
File sourceFolder = new File(destFolder, "source");
sourceFolder.mkdirs();
for (int i = 0; i < codeCount; i++) {
try {
// Base.copyFile(code[i].getFile(),
// new File(sourceFolder, code[i].file.getFileName()));
code[i].copyTo(new File(sourceFolder, code[i].getFileName()));
} catch (IOException e) {
e.printStackTrace();
}
}
// move the .java file from the preproc there too
String preprocFilename = this.name + ".java";
File preprocFile = new File(destFolder, preprocFilename);
if (preprocFile.exists()) {
preprocFile.renameTo(new File(sourceFolder, preprocFilename));
}
/// remove the .class files from the export folder.
for (int i = 0; i < classfiles.length; i++) {
if (classfiles[i].endsWith(".class")) {
File deadguy = new File(destFolder, classfiles[i]);
if (!deadguy.delete()) {
Base.showWarning("Could not delete",
classfiles[i] + " could not \n" +
"be deleted from the applet folder. \n" +
"You'll need to remove it by hand.", null);
}
}
}
/// goodbye
return true;
return false;
}
@ -2792,7 +1734,7 @@ public class Sketch {
* Returns a String[] array of proper extensions.
*/
public String[] getExtensions() {
return new String[] { "pde", "java" };
return new String[] { "pde", "c", "cpp", "h" };
}

View File

@ -24,6 +24,7 @@
package processing.app.debug;
import processing.app.Base;
import processing.app.Preferences;
import processing.app.Sketch;
import processing.app.SketchCode;
import processing.core.*;
@ -32,11 +33,18 @@ import java.io.*;
import java.util.*;
import java.util.zip.*;
import org.eclipse.jdt.core.compiler.batch.BatchCompiler;
import org.eclipse.jdt.core.compiler.CompilationProgress;
public class Compiler implements MessageConsumer {
static final String BUGS_URL =
"https://developer.berlios.de/bugs/?group_id=3590";
static final String SUPER_BADNESS =
"Compiler error, please submit this code to " + BUGS_URL;
public class Compiler {
Sketch sketch;
String buildPath;
String primaryClassName;
RunnerException exception;
public Compiler() { }
@ -50,619 +58,465 @@ public class Compiler {
*/
public boolean compile(Sketch sketch,
String buildPath,
String primaryClassName) throws RunnerException {
// This will be filled in if anyone gets angry
RunnerException exception = null;
boolean success = false;
String primaryClassName,
Target target) throws RunnerException {
this.sketch = sketch;
this.buildPath = buildPath;
this.primaryClassName = primaryClassName;
String baseCommand[] = new String[] {
"-Xemacs",
//"-noExit", // not necessary for ecj
"-source", "1.5",
"-target", "1.5",
"-classpath", sketch.getClassPath(),
"-nowarn", // we're not currently interested in warnings (works in ecj)
"-d", buildPath // output the classes in the buildPath
};
//PApplet.println(baseCommand);
// the pms object isn't used for anything but storage
MessageStream pms = new MessageStream(this);
// make list of code files that need to be compiled
// (some files are skipped if they contain no class)
String[] sourceFiles = new String[sketch.getCodeCount()];
int sourceCount = 0;
sourceFiles[sourceCount++] =
new File(buildPath, primaryClassName + ".java").getAbsolutePath();
String userdir = System.getProperty("user.dir") + File.separator;
// LibraryManager libraryManager;
//
// try {
// libraryManager = new LibraryManager();
// } catch (IOException e) {
// throw new RunnerException(e.getMessage());
// }
String avrBasePath = Base.getAvrBasePath();
List includePaths = new ArrayList();
includePaths.add(target.getPath());
// use lib directories as include paths
for (int i = 0; i < sketch.importedLibraries.size(); i++) {
includePaths.add(
((Library) sketch.importedLibraries.get(i)).getFolder().getPath());
}
List baseCommandLinker = new ArrayList(Arrays.asList(new String[] {
avrBasePath + "avr-gcc",
"-Os",
"-Wl,--gc-sections",
"-mmcu=" + Preferences.get("boards." + Preferences.get("board") + ".build.mcu"),
"-o",
buildPath + File.separator + primaryClassName + ".elf"
}));
String runtimeLibraryName = buildPath + File.separator + "core.a";
for (SketchCode code : sketch.getCode()) {
if (code.isExtension("java")) {
String path = new File(buildPath, code.getFileName()).getAbsolutePath();
sourceFiles[sourceCount++] = path;
List baseCommandAR = new ArrayList(Arrays.asList(new String[] {
avrBasePath + "avr-ar",
"rcs",
runtimeLibraryName
}));
// use lib object files
for (Iterator i = sketch.importedLibraries.iterator(); i.hasNext(); ) {
Library library = (Library) i.next();
File[] objectFiles = library.getObjectFiles();
for (int j = 0; j < objectFiles.length; j++)
baseCommandLinker.add(objectFiles[j].getPath());
}
List baseCommandObjcopy = new ArrayList(Arrays.asList(new String[] {
avrBasePath + "avr-objcopy",
"-O",
"-R",
}));
// make list of code files that need to be compiled and the object files
// that they will be compiled to (includes code from the sketch and the
// library for the target platform)
List sourceNames = new ArrayList();
List sourceNamesCPP = new ArrayList();
List objectNames = new ArrayList();
List objectNamesCPP = new ArrayList();
List targetObjectNames = new ArrayList();
List sketchObjectNames = new ArrayList();
sourceNamesCPP.add(buildPath + File.separator + primaryClassName);
objectNamesCPP.add(buildPath + File.separator + primaryClassName + ".o");
sketchObjectNames.add(buildPath + File.separator + primaryClassName + ".o");
for (int i = 0; i < sketch.getCodeCount(); i++) {
//if (sketch.getCode(i).preprocName != null) {
if (sketch.getCode(i).isExtension(".c")) {
sourceNames.add(buildPath + File.separator + sketch.getCode(i).getPrettyName());
objectNames.add(buildPath + File.separator + sketch.getCode(i).getPrettyName() + ".o");
sketchObjectNames.add(buildPath + File.separator + sketch.getCode(i).getPrettyName() + ".o");
} else if (sketch.getCode(i).isExtension(".cpp")) {
sourceNamesCPP.add(buildPath + File.separator + sketch.getCode(i).getPrettyName());
objectNamesCPP.add(buildPath + File.separator + sketch.getCode(i).getPrettyName() + ".o");
sketchObjectNames.add(buildPath + File.separator + sketch.getCode(i).getPrettyName() + ".o");
}
//}
}
for (Iterator iter = target.getSourceFilenames().iterator(); iter.hasNext(); ) {
String filename = (String) iter.next();
if (filename != null) {
targetObjectNames.add(buildPath + File.separator + filename + ".o");
if (filename.endsWith(".c")) {
sourceNames.add(target.getPath() + File.separator + filename);
objectNames.add(buildPath + File.separator + filename + ".o");
} else if (filename.endsWith(".cpp")) {
sourceNamesCPP.add(target.getPath() + File.separator + filename);
objectNamesCPP.add(buildPath + File.separator + filename + ".o");
}
}
}
String[] command = new String[baseCommand.length + sourceCount];
System.arraycopy(baseCommand, 0, command, 0, baseCommand.length);
// append each of the files to the command string
System.arraycopy(sourceFiles, 0, command, baseCommand.length, sourceCount);
baseCommandLinker.addAll(sketchObjectNames);
//baseCommandLinker.addAll(targetObjectNames);
baseCommandLinker.add(runtimeLibraryName);
baseCommandLinker.add("-L" + buildPath);
baseCommandLinker.add("-lm");
//PApplet.println(command);
firstErrorFound = false; // haven't found any errors yet
secondErrorFound = false;
int result = 0; // pre-initialized to quiet a bogus warning from jikes
try {
// Load errors into a local StringBuffer
final StringBuffer errorBuffer = new StringBuffer();
// execute the compiler, and create threads to deal
// with the input and error streams
//
// Create single method dummy writer class to slurp errors from javac
Writer internalWriter = new Writer() {
public void write(char[] buf, int off, int len) {
errorBuffer.append(buf, off, len);
}
public void flush() { }
public void close() { }
};
// Wrap as a PrintWriter since that's what compile() wants
PrintWriter writer = new PrintWriter(internalWriter);
//result = com.sun.tools.javac.Main.compile(command, writer);
CompilationProgress progress = null;
PrintWriter outWriter = new PrintWriter(System.out);
success = BatchCompiler.compile(command, outWriter, writer, progress);
// Close out the stream for good measure
writer.flush();
writer.close();
BufferedReader reader =
new BufferedReader(new StringReader(errorBuffer.toString()));
//System.err.println(errorBuffer.toString());
String line = null;
while ((line = reader.readLine()) != null) {
//System.out.println("got line " + line); // debug
// get first line, which contains file name, line number,
// and at least the first line of the error message
String errorFormat = "([\\w\\d_]+.java):(\\d+):\\s*(.*):\\s*(.*)\\s*";
String[] pieces = PApplet.match(line, errorFormat);
//PApplet.println(pieces);
// if it's something unexpected, die and print the mess to the console
if (pieces == null) {
exception = new RunnerException("Cannot parse error text: " + line);
exception.hideStackTrace();
// Send out the rest of the error message to the console.
System.err.println(line);
while ((line = reader.readLine()) != null) {
System.err.println(line);
}
break;
}
// translate the java filename and line number into a un-preprocessed
// location inside a source file or tab in the environment.
String dotJavaFilename = pieces[1];
// Line numbers are 1-indexed from javac
int dotJavaLineIndex = PApplet.parseInt(pieces[2]) - 1;
String errorMessage = pieces[4];
int codeIndex = 0; //-1;
int codeLine = -1;
// first check to see if it's a .java file
for (int i = 0; i < sketch.getCodeCount(); i++) {
SketchCode code = sketch.getCode(i);
if (code.isExtension("java")) {
if (dotJavaFilename.equals(code.getFileName())) {
codeIndex = i;
codeLine = dotJavaLineIndex;
}
}
}
// if it's not a .java file, codeIndex will still be 0
if (codeIndex == 0) { // main class, figure out which tab
//for (int i = 1; i < sketch.getCodeCount(); i++) {
for (int i = 0; i < sketch.getCodeCount(); i++) {
SketchCode code = sketch.getCode(i);
if (code.isExtension("pde")) {
if (code.getPreprocOffset() <= dotJavaLineIndex) {
codeIndex = i;
//System.out.println("i'm thinkin file " + i);
codeLine = dotJavaLineIndex - code.getPreprocOffset();
}
}
}
//if (codeLine != -1) {
//codeLine = dotJavaLineIndex - sketch.getCode(codeIndex).getPreprocOffset();
//}
}
//System.out.println("code line now " + codeLine);
exception = new RunnerException(errorMessage, codeIndex, codeLine, -1, false);
// for a test case once message parsing is implemented,
// use new Font(...) since that wasn't getting picked up properly.
/*
if (errorMessage.equals("cannot find symbol")) {
handleCannotFindSymbol(reader, exception);
} else if (errorMessage.indexOf("is already defined") != -1) {
reader.readLine(); // repeats the line of code w/ error
int codeColumn = caretColumn(reader.readLine());
exception = new RunnerException(errorMessage,
codeIndex, codeLine, codeColumn);
} else if (errorMessage.startsWith("package") &&
errorMessage.endsWith("does not exist")) {
// Because imports are stripped out and re-added to the 0th line of
// the preprocessed code, codeLine will always be wrong for imports.
exception = new RunnerException("P" + errorMessage.substring(1) +
". You might be missing a library.");
} else {
exception = new RunnerException(errorMessage);
}
*/
if (errorMessage.startsWith("The import ") &&
errorMessage.endsWith("cannot be resolved")) {
// The import poo cannot be resolved
//import poo.shoe.blah.*;
String what = errorMessage.substring("The import ".length());
what = what.substring(0, what.indexOf(' '));
System.err.println("Note that release 1.0, libraries must be " +
"installed in a folder named 'libraries' " +
"inside the 'sketchbook' folder.");
exception.setMessage("The package " +
"\u201C" + what + "\u201D" +
" does not exist. " +
"You might be missing a library.");
// Actually create the folder and open it for the user
File sketchbookLibraries = Base.getSketchbookLibrariesFolder();
if (!sketchbookLibraries.exists()) {
if (sketchbookLibraries.mkdirs()) {
Base.openFolder(sketchbookLibraries);
}
}
} else if (errorMessage.endsWith("cannot be resolved to a type")) {
// xxx cannot be resolved to a type
//xxx c;
String what = errorMessage.substring(0, errorMessage.indexOf(' '));
if (what.equals("BFont") ||
what.equals("BGraphics") ||
what.equals("BImage")) {
handleCrustyCode(exception);
} else {
exception.setMessage("Cannot find a class or type " +
"named \u201C" + what + "\u201D");
}
} else if (errorMessage.endsWith("cannot be resolved")) {
// xxx cannot be resolved
//println(xxx);
String what = errorMessage.substring(0, errorMessage.indexOf(' '));
if (what.equals("LINE_LOOP") ||
what.equals("LINE_STRIP") ||
what.equals("framerate")) {
handleCrustyCode(exception);
} else {
exception.setMessage("Cannot find anything " +
"named \u201C" + what + "\u201D");
}
} else if (errorMessage.startsWith("Duplicate")) {
// "Duplicate nested type xxx"
// "Duplicate local variable xxx"
} else {
String[] parts = null;
// The method xxx(String) is undefined for the type Temporary_XXXX_XXXX
//xxx("blah");
// The method xxx(String, int) is undefined for the type Temporary_XXXX_XXXX
//xxx("blah", 34);
// The method xxx(String, int) is undefined for the type PApplet
//PApplet.sub("ding");
String undefined =
"The method (\\S+\\(.*\\)) is undefined for the type (.*)";
parts = PApplet.match(errorMessage, undefined);
if (parts != null) {
if (parts[1].equals("framerate(int)") ||
parts[1].equals("push()")) {
handleCrustyCode(exception);
} else {
String mess = "The function " + parts[1] + " does not exist.";
exception.setMessage(mess);
}
break;
}
}
if (exception != null) {
// The stack trace just shows that this happened inside the compiler,
// which is a red herring. Don't ever show it for compiler stuff.
exception.hideStackTrace();
break;
}
Process process;
boolean compiling = true;
for(int i = 0; i < sourceNames.size(); i++) {
if (execAsynchronously(getCommandCompilerC(avrBasePath, includePaths,
(String) sourceNames.get(i), (String) objectNames.get(i))) != 0)
return false;
}
for(int i = 0; i < sourceNamesCPP.size(); i++) {
if (execAsynchronously(getCommandCompilerCPP(avrBasePath, includePaths,
(String) sourceNamesCPP.get(i), (String) objectNamesCPP.get(i))) != 0)
return false;
}
for(int i = 0; i < targetObjectNames.size(); i++) {
List commandAR = new ArrayList(baseCommandAR);
commandAR.add(targetObjectNames.get(i));
if (execAsynchronously(commandAR) != 0)
return false;
}
if (execAsynchronously(baseCommandLinker) != 0)
return false;
List commandObjcopy;
// Extract EEPROM data (from EEMEM directive) to .eep file.
commandObjcopy = new ArrayList(baseCommandObjcopy);
commandObjcopy.add(2, "ihex");
commandObjcopy.set(3, "-j");
commandObjcopy.add(".eeprom");
commandObjcopy.add("--set-section-flags=.eeprom=alloc,load");
commandObjcopy.add("--no-change-warnings");
commandObjcopy.add("--change-section-lma");
commandObjcopy.add(".eeprom=0");
commandObjcopy.add(buildPath + File.separator + primaryClassName + ".elf");
commandObjcopy.add(buildPath + File.separator + primaryClassName + ".eep");
if (execAsynchronously(commandObjcopy) != 0)
return false;
commandObjcopy = new ArrayList(baseCommandObjcopy);
commandObjcopy.add(2, "ihex");
commandObjcopy.add(".eeprom"); // remove eeprom data
commandObjcopy.add(buildPath + File.separator + primaryClassName + ".elf");
commandObjcopy.add(buildPath + File.separator + primaryClassName + ".hex");
if (execAsynchronously(commandObjcopy) != 0)
return false;
} catch (Exception e) {
String msg = e.getMessage();
if ((msg != null) && (msg.indexOf("avr-gcc: not found") != -1)) {
//System.err.println("jikes is missing");
Base.showWarning("Compiler error",
"Could not find the compiler.\n" +
"avr-gcc is missing from your PATH.", null);
return false;
} else {
e.printStackTrace();
result = -1;
}
} catch (IOException e) {
String bigSigh = "Error while compiling. (" + e.getMessage() + ")";
exception = new RunnerException(bigSigh);
e.printStackTrace();
success = false;
}
// In case there was something else.
// an error was queued up by message(), barf this back to build()
// which will barf it back to Editor. if you're having trouble
// discerning the imagery, consider how cows regurgitate their food
// to digest it, and the fact that they have five stomaches.
//
//System.out.println("throwing up " + exception);
if (exception != null) throw exception;
return success;
// if the result isn't a known, expected value it means that something
// is fairly wrong, one possibility is that jikes has crashed.
//
if (result != 0 && result != 1 ) {
//exception = new RunnerException(SUPER_BADNESS);
//editor.error(exception); // this will instead be thrown
Base.openURL(BUGS_URL);
throw new RunnerException(SUPER_BADNESS);
}
// success would mean that 'result' is set to zero
return (result == 0); // ? true : false;
}
public int execAsynchronously(List commandList)
throws RunnerException, IOException {
String[] command = new String[commandList.size()];
commandList.toArray(command);
int result = 0;
if (Preferences.getBoolean("build.verbose")) {
for(int j = 0; j < command.length; j++) {
System.out.print(command[j] + " ");
}
System.out.println();
}
Process process = Runtime.getRuntime().exec(command);
MessageSiphon in = new MessageSiphon(process.getInputStream(), this);
MessageSiphon err = new MessageSiphon(process.getErrorStream(), this);
// wait for the process to finish. if interrupted
// before waitFor returns, continue waiting
boolean compiling = true;
while (compiling) {
try {
if (in.thread != null)
in.thread.join();
if (err.thread != null)
err.thread.join();
result = process.waitFor();
//System.out.println("result is " + result);
compiling = false;
} catch (InterruptedException ignored) { }
}
if (exception != null) {
exception.hideStackTrace();
throw exception;
}
return result;
}
boolean firstErrorFound;
boolean secondErrorFound;
/**
* Fire up 'ole javac based on <a href="http://java.sun.com/j2se/1.5.0/docs/tooldocs/solaris/javac.html#proginterface">this interface</a>.
*
* @param sketch Sketch object to be compiled.
* @param buildPath Where the temporary files live and will be built from.
* @return
* @throws RunnerException Only if there's a problem. Only then.
* Part of the MessageConsumer interface, this is called
* whenever a piece (usually a line) of error message is spewed
* out from the compiler. The errors are parsed for their contents
* and line number, which is then reported back to Editor.
*/
// public boolean compileJavac(Sketch sketch,
// String buildPath) throws RunnerException {
// // This will be filled in if anyone gets angry
// RunnerException exception = null;
//
// String baseCommand[] = new String[] {
// "-source", "1.5",
// "-target", "1.5",
// "-classpath", sketch.getClassPath(),
// "-nowarn", // we're not currently interested in warnings (ignored?)
// "-d", buildPath // output the classes in the buildPath
// };
// //PApplet.println(baseCommand);
//
// // make list of code files that need to be compiled
// // (some files are skipped if they contain no class)
// String[] preprocNames = new String[sketch.getCodeCount()];
// int preprocCount = 0;
// for (int i = 0; i < sketch.getCodeCount(); i++) {
// if (sketch.getCode(i).preprocName != null) {
// preprocNames[preprocCount++] = sketch.getCode(i).preprocName;
// }
// }
// String[] command = new String[baseCommand.length + preprocCount];
// System.arraycopy(baseCommand, 0, command, 0, baseCommand.length);
// // append each of the files to the command string
// for (int i = 0; i < preprocCount; i++) {
// command[baseCommand.length + i] =
// buildPath + File.separator + preprocNames[i];
// }
// //PApplet.println(command);
//
// int result = -1; // needs to be set bad by default, in case hits IOE below
//
// try {
// // Load errors into a local StringBuffer
// final StringBuffer errorBuffer = new StringBuffer();
//
// // Create single method dummy writer class to slurp errors from javac
// Writer internalWriter = new Writer() {
// public void write(char[] buf, int off, int len) {
// errorBuffer.append(buf, off, len);
// }
//
// public void flush() { }
//
// public void close() { }
// };
// // Wrap as a PrintWriter since that's what compile() wants
// PrintWriter writer = new PrintWriter(internalWriter);
//
// result = com.sun.tools.javac.Main.compile(command, writer);
//
// // Close out the stream for good measure
// writer.flush();
// writer.close();
//
//// BufferedReader reader =
//// new BufferedReader(new StringReader(errorBuffer.toString()));
// //System.err.println(errorBuffer.toString());
//
//// String m = errorBuffer.toString();
// //ParsePosition mp = new ParsePosition(0);
//
//// while (mp.getIndex() < m.length()) { // reading messages
// String line = null;
// int lineIndex = 0;
// String[] lines = PApplet.split(errorBuffer.toString(), '\n');
// int lineCount = lines.length;
// while (lineIndex < lineCount) {
// //while ((line = reader.readLine()) != null) {
// //System.out.println("got line " + line); // debug
//
// /*
//compiler.misc.count.error=\
// {0} error
//compiler.misc.count.error.plural=\
// {0} errors
//compiler.misc.count.warn=\
// {0} warning
//compiler.misc.count.warn.plural=\
// {0} warnings
// */
// // Check to see if this is the last line.
//// if ((PApplet.match(line, "\\d+ error[s]?") != null) ||
//// (PApplet.match(line, "\\d+ warning[s]?") != null)) {
//// break;
//// }
// if (isCompilerMatch(line, "compiler.misc.count.error") ||
// isCompilerMatch(line, "compiler.misc.count.error.plural") ||
// isCompilerMatch(line, "compiler.misc.count.warn") ||
// isCompilerMatch(line, "compiler.misc.count.warn.plural")) {
// break;
// }
//
// // Hide these because people are getting confused
// // http://dev.processing.org/bugs/show_bug.cgi?id=817
// // com/sun/tools/javac/resources/compiler.properties
// //if (line.startsWith("Note: ")) {
// String compilerNote = compilerResources.getString("compiler.note.note");
// MessageFormat noteFormat = new MessageFormat(compilerNote + " {0}");
// Object[] noteFound;
// try {
// noteFound = noteFormat.parse(line);
// if (noteFound != null) {
// System.out.println("gefunden " + noteFound[0]);
//
// /*
// // if you mention serialVersionUID one more time, i'm kickin' you out
// if (line.indexOf("serialVersionUID") != -1) continue;
// // {0} uses unchecked or unsafe operations.
// // Some input files use unchecked or unsafe operations.
// if (line.indexOf("or unsafe operations") != -1) continue;
// // {0} uses or overrides a deprecated API.
// // Some input files use or override a deprecated API.
// if (line.indexOf("or override") != -1) continue;
// // Recompile with -Xlint:deprecation for details.
// // Recompile with -Xlint:unchecked for details.
// if (line.indexOf("Recompile with -Xlint:") != -1) continue;
// System.err.println(line);
// */
// continue;
// }
// } catch (ParseException e) {
// e.printStackTrace();
// }
//
// // get first line, which contains file name, line number,
// // and at least the first line of the error message
// String errorFormat = "([\\w\\d_]+.java):(\\d+):\\s*(.*)\\s*";
// String[] pieces = PApplet.match(line, errorFormat);
//
// // if it's something unexpected, die and print the mess to the console
// if (pieces == null) {
// exception = new RunnerException("Cannot parse error text: " + line);
// exception.hideStackTrace();
// // Send out the rest of the error message to the console.
// System.err.println(line);
// //while ((line = reader.readLine()) != null) {
// for (int i = lineIndex; i < lineCount; i++) {
// System.err.println(lines[i]);
// }
// break;
// }
//
// // translate the java filename and line number into a un-preprocessed
// // location inside a source file or tab in the environment.
// String dotJavaFilename = pieces[0];
// // Line numbers are 1-indexed from javac
// int dotJavaLineIndex = PApplet.parseInt(pieces[1]) - 1;
// String errorMessage = pieces[2];
//
// int codeIndex = -1;
// int codeLine = -1;
// for (int i = 0; i < sketch.getCodeCount(); i++) {
// String name = sketch.getCode(i).preprocName;
// if ((name != null) && dotJavaFilename.equals(name)) {
// codeIndex = i;
// }
// }
// //System.out.println("code index/line are " + codeIndex + " " + codeLine);
// //System.out.println("java line number " + dotJavaLineIndex + " from " + dotJavaFilename);
//
// if (codeIndex == 0) { // main class, figure out which tab
// for (int i = 1; i < sketch.getCodeCount(); i++) {
// SketchCode code = sketch.getCode(i);
//
// if (code.flavor == Sketch.PDE) {
// if (code.preprocOffset <= dotJavaLineIndex) {
// codeIndex = i;
// //System.out.println("i'm thinkin file " + i);
// }
// }
// }
// }
// //System.out.println("preproc offset is " + sketch.getCode(codeIndex).preprocOffset);
// codeLine = dotJavaLineIndex - sketch.getCode(codeIndex).preprocOffset;
// //System.out.println("code line now " + codeLine);
// exception = new RunnerException(errorMessage, codeIndex, codeLine, -1, false);
//
// // for a test case once message parsing is implemented,
// // use new Font(...) since that wasn't getting picked up properly.
//
// if (errorMessage.equals("cannot find symbol")) {
// handleCannotFindSymbol(reader, exception);
//
// } else if (errorMessage.indexOf("is already defined") != -1) {
// reader.readLine(); // repeats the line of code w/ error
// int codeColumn = caretColumn(reader.readLine());
// exception = new RunnerException(errorMessage,
// codeIndex, codeLine, codeColumn);
//
// } else if (errorMessage.startsWith("package") &&
// errorMessage.endsWith("does not exist")) {
// // Because imports are stripped out and re-added to the 0th line of
// // the preprocessed code, codeLine will always be wrong for imports.
// exception = new RunnerException("P" + errorMessage.substring(1) +
// ". You might be missing a library.");
// } else {
// exception = new RunnerException(errorMessage);
// }
// if (exception != null) {
// // The stack trace just shows that this happened inside the compiler,
// // which is a red herring. Don't ever show it for compiler stuff.
// exception.hideStackTrace();
// break;
// }
// }
// } catch (IOException e) {
// String bigSigh = "Error while compiling. (" + e.getMessage() + ")";
// exception = new RunnerException(bigSigh);
// e.printStackTrace();
// result = 1;
// }
// // In case there was something else.
// if (exception != null) throw exception;
//
// // Success means that 'result' is set to zero
// return (result == 0);
// }
//
//
// boolean isCompilerMatch(String line, String format) {
// return compilerMatch(line, format) != null;
// }
//
//
// Object[] compilerMatch(String line, String name) {
// String format = compilerResources.getString(name);
// MessageFormat mf = new MessageFormat(format);
// Object[] matches = null;
// try {
// matches = mf.parse(line);
// } catch (ParseException e) {
// e.printStackTrace();
// }
// return matches;
// }
public void message(String s) {
// This receives messages as full lines, so a newline needs
// to be added as they're printed to the console.
System.err.print(s);
// ignore cautions
if (s.indexOf("warning") != -1) return;
// boolean isCompilerMatch(String line, ParsePosition pos, String format) {
// return compilerMatch(line, pos, format) != null;
// }
//
//
// Object[] compilerMatch(String line, ParsePosition pos, String name) {
// String format = compilerResources.getString(name);
// MessageFormat mf = new MessageFormat(format);
// Object[] matches = mf.parse(line, pos);
// return matches;
// }
// jikes always uses a forward slash character as its separator,
// so replace any platform-specific separator characters before
// attemping to compare
//
//String buildPathSubst = buildPath.replace(File.separatorChar, '/') + "/";
String buildPathSubst = buildPath.replace(File.separatorChar,File.separatorChar) + File.separatorChar;
String partialTempPath = null;
int partialStartIndex = -1; //s.indexOf(partialTempPath);
int fileIndex = -1; // use this to build a better exception
// Tell-tale signs of old code copied and pasted from the web.
// Detect classes BFont, BGraphics, BImage; methods framerate, push;
// and variables LINE_LOOP and LINE_STRIP.
// static HashMap crusties = new HashMap();
// static {
// crusties.put("BFont", new Object());
// crusties.put("BGraphics", new Object());
// crusties.put("BImage", new Object());
// crusties.put("framerate", new Object());
// crusties.put("push", new Object());
// crusties.put("LINE_LOOP", new Object());
// crusties.put("LINE_STRIP", new Object());
// }
// check the main sketch file first.
partialTempPath = buildPathSubst + primaryClassName;
partialStartIndex = s.indexOf(partialTempPath);
if (partialStartIndex != -1) {
fileIndex = 0;
} else {
// wasn't there, check the other (non-pde) files in the sketch.
// iterate through the project files to see who's causing the trouble
for (int i = 0; i < sketch.getCodeCount(); i++) {
if (sketch.getCode(i).isExtension("pde")) continue;
// void handleCannotFindSymbol(BufferedReader reader,
// RunnerException rex) throws IOException {
// String symbolLine = reader.readLine();
// String locationLine = reader.readLine();
// /*String codeLine =*/ reader.readLine();
// String caretLine = reader.readLine();
// rex.setCodeColumn(caretColumn(caretLine));
//
// String[] pieces =
// PApplet.match(symbolLine, "symbol\\s*:\\s*(\\w+)\\s+(.*)");
// if (pieces != null) {
// if (pieces[0].equals("class") ||
// pieces[0].equals("variable")) {
// rex.setMessage("Cannot find a " + pieces[0] + " " +
// "named \u201C" + pieces[1] + "\u201D");
// if (crusties.get(pieces[1]) != null) {
// handleCrustyCode(rex);
// }
//
// } else if (pieces[0].equals("method")) {
// int leftParen = pieces[1].indexOf("(");
// int rightParen = pieces[1].indexOf(")");
//
// String methodName = pieces[1].substring(0, leftParen);
// String methodParams = pieces[1].substring(leftParen + 1, rightParen);
//
// String message =
// "Cannot find a function named \u201C" + methodName + "\u201D";
// if (methodParams.length() > 0) {
// if (methodParams.indexOf(',') != -1) {
// message += " with parameters ";
// } else {
// message += " with parameter ";
// }
// message += methodParams;
// }
//
// String locationClass = "location: class ";
// if (locationLine.startsWith(locationClass) &&
// // don't include the class name when it's a temp class
// locationLine.indexOf("Temporary_") == -1) {
// String className = locationLine.substring(locationClass.length());
// // If no dot exists, -1 + 1 is 0, so this will have no effect.
// className = className.substring(className.lastIndexOf('.') + 1);
// int bracket = className.indexOf('[');
// if (bracket == -1) {
// message += " in class " + className;
// } else {
// className = className.substring(0, bracket);
// message += " for an array of " + className + " objects";
// }
// }
// message += ".";
// rex.setMessage(message);
//
// // On second thought, make sure this isn't just some alpha/beta code
// if (crusties.get(methodName) != null) {
// handleCrustyCode(rex);
// }
//
// } else {
// System.out.println(symbolLine);
// }
// }
// }
partialTempPath = buildPathSubst + sketch.getCode(i).getFileName();
System.out.println(partialTempPath);
partialStartIndex = s.indexOf(partialTempPath);
if (partialStartIndex != -1) {
fileIndex = i;
System.out.println("fileIndex is " + fileIndex);
break;
}
}
//+ className + ".java";
}
// if the partial temp path appears in the error message...
//
//int partialStartIndex = s.indexOf(partialTempPath);
if (partialStartIndex != -1) {
void handleCrustyCode(RunnerException rex) {
rex.setMessage("This code needs to be updated, " +
"please read the \u201Cchanges\u201D reference.");
Base.showReference("changes.html");
}
protected int caretColumn(String caretLine) {
return caretLine.indexOf("^");
// skip past the path and parse the int after the first colon
//
String s1 = s.substring(partialStartIndex +
partialTempPath.length() + 1);
//System.out.println(s1);
int colon = s1.indexOf(':');
if (s1.indexOf("In function") != -1 || colon == -1) {
System.err.print(s1);
//firstErrorFound = true;
return;
}
int lineNumber;
try {
lineNumber = Integer.parseInt(s1.substring(0, colon));
} catch (NumberFormatException e) {
System.err.print(s1);
return;
}
// the "1" corresponds to the amount of lines written to the main code
// file by PdePreprocessor's writeHeader() routine before prototypes
if (fileIndex == 0)
lineNumber -= 1;
//System.out.println("pde / line number: " + lineNumber);
if (fileIndex == 0) { // main class, figure out which tab
for (int i = 1; i < sketch.getCodeCount(); i++) {
if (sketch.getCode(i).isExtension("pde")) {
//System.out.println("preprocOffset "+ sketch.code[i].preprocOffset);
if (sketch.getCode(i).getPreprocOffset() < lineNumber) {
fileIndex = i;
//System.out.println("i'm thinkin file " + i);
}
}
}
if (fileIndex != 0) { // if found another culprit
lineNumber -= sketch.getCode(fileIndex).getPreprocOffset();
//System.out.println("i'm sayin line " + lineNumber);
}
}
//String s2 = s1.substring(colon + 2);
int err = s1.indexOf(":");
if (err != -1) {
// if the first error has already been found, then this must be
// (at least) the second error found
if (firstErrorFound) {
secondErrorFound = true;
return;
}
// if executing at this point, this is *at least* the first error
firstErrorFound = true;
err += ":".length();
String description = s1.substring(err);
description = description.trim();
System.err.print(description);
//System.out.println("description = " + description);
//System.out.println("creating exception " + exception);
exception = new RunnerException(description, fileIndex, lineNumber-1, -1);
// NOTE!! major change here, this exception will be queued
// here to be thrown by the compile() function
//editor.error(exception);
} else {
System.err.println("i suck: " + s);
}
} else {
// this isn't the start of an error line, so don't attempt to parse
// a line number out of it.
// if the second error hasn't been discovered yet, these lines
// are probably associated with the first error message,
// which is already in the status bar, and are likely to be
// of interest to the user, so spit them to the console.
//
if (!secondErrorFound) {
System.err.println(s);
}
}
}
/////////////////////////////////////////////////////////////////////////////
static private List getCommandCompilerC(String avrBasePath, List includePaths,
String sourceName, String objectName) {
List baseCommandCompiler = new ArrayList(Arrays.asList(new String[] {
avrBasePath + "avr-gcc",
"-c", // compile, don't link
"-g", // include debugging info (so errors include line numbers)
"-Os", // optimize for size
"-w", // surpress all warnings
"-ffunction-sections", // place each function in its own section
"-fdata-sections",
"-mmcu=" + Preferences.get("boards." + Preferences.get("board") + ".build.mcu"),
"-DF_CPU=" + Preferences.get("boards." + Preferences.get("board") + ".build.f_cpu"),
}));
for (int i = 0; i < includePaths.size(); i++) {
baseCommandCompiler.add("-I" + (String) includePaths.get(i));
}
baseCommandCompiler.add(sourceName);
baseCommandCompiler.add("-o"+ objectName);
return baseCommandCompiler;
}
static private List getCommandCompilerCPP(String avrBasePath,
List includePaths, String sourceName, String objectName) {
List baseCommandCompilerCPP = new ArrayList(Arrays.asList(new String[] {
avrBasePath + "avr-g++",
"-c", // compile, don't link
"-g", // include debugging info (so errors include line numbers)
"-Os", // optimize for size
"-w", // surpress all warnings
"-fno-exceptions",
"-ffunction-sections", // place each function in its own section
"-fdata-sections",
"-mmcu=" + Preferences.get("boards." + Preferences.get("board") + ".build.mcu"),
"-DF_CPU=" + Preferences.get("boards." + Preferences.get("board") + ".build.f_cpu"),
}));
for (int i = 0; i < includePaths.size(); i++) {
baseCommandCompilerCPP.add("-I" + (String) includePaths.get(i));
}
baseCommandCompilerCPP.add(sourceName);
baseCommandCompilerCPP.add("-o"+ objectName);
return baseCommandCompilerCPP;
}
/////////////////////////////////////////////////////////////////////////////
/**
* Given a folder, return a list of the header files in that folder (but
* not the header files in its sub-folders, as those should be included from
* within the header files at the top-level).
*/
static public String[] headerListFromIncludePath(String path) {
FilenameFilter onlyHFiles = new FilenameFilter() {
public boolean accept(File dir, String name) {
return name.endsWith(".h");
}
};
return (new File(path)).list(onlyHFiles);
}
/**
* Given a folder, return a list of absolute paths to all jar or zip files
* inside that folder, separated by pathSeparatorChar.

View File

@ -0,0 +1,595 @@
/*
Library.java - Library System for Wiring
Copyright (c) 2006 Nicholas Zambetti. All right reserved.
This library 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 2.1 of the License, or (at your option) any later version.
This library 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
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
package processing.app.debug;
import processing.app.Base;
import processing.app.Preferences;
import processing.app.syntax.*;
import processing.app.debug.RunnerException;
import java.io.*;
import java.util.*;
import java.util.zip.*;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.event.*;
import processing.core.*;
/*
* Provides information about and builds a library
*/
public class Library implements MessageConsumer{
private File libFolder;
private File utilityFolder;
private LibraryManager libManager;
RunnerException exception;
static final String BUGS_URL = "https://developer.berlios.de/bugs/?group_id=3590";
static final String SUPER_BADNESS = "Compiler error, please submit this code to " + BUGS_URL;
/*
* Create a Library
*/
public Library(LibraryManager manager, File folder)
{
libFolder = folder;
libManager = manager;
utilityFolder = getUtilityFolder();
// for debug output
/*
System.out.println("library: " + getName());
System.out.println("folder: " + getFolder());
System.out.println("utility: " + utilityFolder);
System.out.println("built: " + isBuilt());
System.out.println("buildable: " + isBuildable());
System.out.println("o files: " + getObjectFiles().length);
System.out.println("c files: " + getCSourceFiles().length);
System.out.println("cpp files: " + getCPPSourceFiles().length);
*/
}
/*
* Directory of library
* @return File object of library's folder
*/
public File getFolder()
{
return libFolder;
}
/*
* The name of library
* @return String with library name, derived from folder
* note: this will be eventually taken from xml description file
*/
public String getName()
{
return libFolder.getName();
}
/*
* Tests if library is built
* @return True if library has .o files, false otherwise
*/
public boolean isBuilt()
{
if(getObjectFiles().length >= (getCSourceFiles().length + getCPPSourceFiles().length)){
return true;
}
return false;
}
/*
* Tests if library is buildable
* @return True if library has source files, false otherwise
*/
public boolean isBuildable()
{
if(0 < (getCSourceFiles().length + getCPPSourceFiles().length)){
return true;
}
return false;
}
/*
* Tests if library is unbuilt but buildable
* @return True if library has .cpp files but no .o files, false otherwise
*/
public boolean isUnbuiltBuildable()
{
if(isBuildable()){
if(!isBuilt()){
return true;
}
}
return false;
}
/*
* Scans for library "utility" folder
* @return File object of library's "utility" folder, or null
*/
private File getUtilityFolder()
{
FileFilter filter = new FileFilter() {
public boolean accept(File file) {
if(file.isDirectory()){
if((file.getName()).equalsIgnoreCase("utility")){
return true;
}
}
return false;
}
};
File[] files = libFolder.listFiles(filter);
if(files.length > 0){
return files[0];
}
return null;
}
/*
* Finds examples folder
* @return "examples" folder as file object or null
*/
private File getExamplesFolder()
{
FileFilter filter = new FileFilter() {
public boolean accept(File file) {
if(file.isDirectory()){
if((file.getName()).equalsIgnoreCase("examples")){
return true;
}
}
return false;
}
};
File[] files = libFolder.listFiles(filter);
if(files.length > 0){
return files[0];
}
return null;
}
/*
* Populates example menu or submenu with files
*/
private void populateWithExamples(File folder, JMenu menu, ActionListener listener) {
FileFilter onlyfolders = new FileFilter() {
public boolean accept(File file) {
return file.isDirectory();
}
};
File[] folders = folder.listFiles(onlyfolders);
File file;
JMenu submenu;
JMenuItem item;
for(int i = 0; i < folders.length; ++i){
file = new File(folders[i], folders[i].getName() + ".pde");
if(file.exists()){
item = new JMenuItem(folders[i].getName());
item.setActionCommand(file.getAbsolutePath());
item.addActionListener(listener);
menu.add(item);
}else{
submenu = new JMenu(folders[i].getName());
populateWithExamples(folders[i], submenu, listener);
menu.add(submenu);
}
}
}
/*
* Builds and returns an examples menu
* @return JMenu object with example files, or null if none
*/
public JMenu getExamplesMenu(ActionListener listener) {
JMenu submenu;
File examplesFolder = getExamplesFolder();
if(null != examplesFolder){
submenu = new JMenu("Library-" + getName());
populateWithExamples(examplesFolder, submenu, listener);
return submenu;
}
return null;
}
/*
* List of object files for linking
* @return Array of object files as File objects
*/
private File[] getObjectFiles(File folder)
{
FileFilter onlyObjectFiles = new FileFilter() {
public boolean accept(File file) {
return (file.getName()).endsWith(".o");
}
};
return folder.listFiles(onlyObjectFiles);
}
public File[] getObjectFiles()
{
if(null == utilityFolder){
return getObjectFiles(libFolder);
}
File[] libraryObjects = getObjectFiles(libFolder);
File[] utilityObjects = getObjectFiles(utilityFolder);
File[] objects = new File[libraryObjects.length + utilityObjects.length];
System.arraycopy(libraryObjects, 0, objects, 0, libraryObjects.length);
System.arraycopy(utilityObjects, 0, objects, libraryObjects.length, utilityObjects.length);
return objects;
}
/*
* List of header source files for inclusion
* @return Array of header source files as File objects
*/
public File[] getHeaderFiles()
{
FileFilter onlyHFiles = new FileFilter() {
public boolean accept(File file) {
return (file.getName()).endsWith(".h");
}
};
return libFolder.listFiles(onlyHFiles);
}
/*
* List of library's C source files for compiling
* @return Array of C source files as File objects
*/
private File[] getCSourceFiles(File folder)
{
FileFilter onlyCFiles = new FileFilter() {
public boolean accept(File file) {
return (file.getName()).endsWith(".c");
}
};
return folder.listFiles(onlyCFiles);
}
private File[] getCSourceFiles()
{
if(null == utilityFolder){
return getCSourceFiles(libFolder);
}
File[] librarySources = getCSourceFiles(libFolder);
File[] utilitySources = getCSourceFiles(utilityFolder);
File[] sources = new File[librarySources.length + utilitySources.length];
System.arraycopy(librarySources, 0, sources, 0, librarySources.length);
System.arraycopy(utilitySources, 0, sources, librarySources.length, utilitySources.length);
return sources;
}
/*
* List of C++ source files for compiling
* @return Array of C++ source files as File objects
*/
private File[] getCPPSourceFiles(File folder)
{
FileFilter onlyCPPFiles = new FileFilter() {
public boolean accept(File file) {
return (file.getName()).endsWith(".cpp");
}
};
return folder.listFiles(onlyCPPFiles);
}
private File[] getCPPSourceFiles()
{
if(null == utilityFolder){
return getCPPSourceFiles(libFolder);
}
File[] librarySources = getCPPSourceFiles(libFolder);
File[] utilitySources = getCPPSourceFiles(utilityFolder);
File[] sources = new File[librarySources.length + utilitySources.length];
System.arraycopy(librarySources, 0, sources, 0, librarySources.length);
System.arraycopy(utilitySources, 0, sources, librarySources.length, utilitySources.length);
return sources;
}
/*
* Attempt to build library
* @return true on successful build, false otherwise
*/
public boolean build() throws RunnerException
{
// fail if library is not buildable (contains no sources)
if(!isBuildable()){
return false;
}
String userdir = System.getProperty("user.dir") + File.separator;
String avrBasePath;
if(Base.isMacOS()) {
avrBasePath = new String("hardware/tools/avr/bin/");
}
else if(Base.isLinux()) {
avrBasePath = new String("");
}
else {
avrBasePath = new String(userdir + "hardware/tools/avr/bin/");
}
String[] baseCompileCommandC = new String[] {
avrBasePath + "avr-gcc",
"-c",
"-g",
"-Os",
"-Wall",
"-ffunction-sections", // place each function in its own section
"-fdata-sections",
"-mmcu=" + Preferences.get("boards." + Preferences.get("board") + ".build.mcu"),
"-DF_CPU=" + Preferences.get("boards." + Preferences.get("board") + ".build.f_cpu"),
"-I" + libManager.getTarget().getPath(),
"-I" + getFolder(),
};
String[] baseCompileCommandCPP = new String[] {
avrBasePath + "avr-g++",
"-c",
"-g",
"-Os",
"-Wall",
"-fno-exceptions",
"-ffunction-sections", // place each function in its own section
"-fdata-sections",
"-mmcu=" + Preferences.get("boards." + Preferences.get("board") + ".build.mcu"),
"-DF_CPU=" + Preferences.get("boards." + Preferences.get("board") + ".build.f_cpu"),
"-I" + libManager.getTarget().getPath(),
"-I" + getFolder(),
};
// use built lib directories in include paths when searching for headers
// this allows libs to use other libs easily
int extraSpots = 2; // two spots for file path and -o portions
utilityFolder = getUtilityFolder(); // refresh status of utility folder
if(null != utilityFolder){
extraSpots = 3; // an extra spot for utility folder as include
}
String[] libDirs = libManager.getFolderPaths();
String[] compileCommandC = new String[baseCompileCommandC.length + libDirs.length + extraSpots];
String[] compileCommandCPP = new String[baseCompileCommandCPP.length + libDirs.length + extraSpots];
System.arraycopy(baseCompileCommandC, 0, compileCommandC, 0, baseCompileCommandC.length);
System.arraycopy(baseCompileCommandCPP, 0, compileCommandCPP, 0, baseCompileCommandCPP.length);
for (int i = 0; i < libDirs.length; ++i) {
compileCommandC[baseCompileCommandC.length + i] = "-I" + libDirs[i];
compileCommandCPP[baseCompileCommandCPP.length + i] = "-I" + libDirs[i];
}
// add this library's "utility" folder to inclusion paths
if(null != utilityFolder){
compileCommandC[compileCommandC.length - 3] = "-I" + utilityFolder.getPath();
compileCommandCPP[compileCommandCPP.length - 3] = "-I" + utilityFolder.getPath();
}
File[] sourcesC = getCSourceFiles();
File[] sourcesCPP = getCPPSourceFiles();
// execute the compiler, and create threads to deal
// with the input and error streams
//
int result = 0;
try {
String pathSansExtension;
Process process;
boolean compiling = true;
// compile c sources
for(int i = 0; i < sourcesC.length; ++i) {
pathSansExtension = sourcesC[i].getPath();
pathSansExtension = pathSansExtension.substring(0, pathSansExtension.length() - 2); // -2 because ".c"
compileCommandC[compileCommandC.length - 2] = sourcesC[i].getPath();
compileCommandC[compileCommandC.length - 1] = "-o" + pathSansExtension + ".o";
process = Runtime.getRuntime().exec(compileCommandC);
new MessageSiphon(process.getInputStream(), this);
new MessageSiphon(process.getErrorStream(), this);
// wait for the process to finish. if interrupted
// before waitFor returns, continue waiting
//
compiling = true;
while (compiling) {
try {
result = process.waitFor();
//System.out.println("result is " + result);
compiling = false;
} catch (InterruptedException ignored) { }
}
if (exception != null) {
//exception.hideStackTrace = true;
throw exception;
}
if(result != 0){
return false;
}
}
// compile c++ sources
for(int i = 0; i < sourcesCPP.length; ++i) {
pathSansExtension = sourcesCPP[i].getPath();
pathSansExtension = pathSansExtension.substring(0, pathSansExtension.length() - 4); // -4 because ".cpp"
compileCommandCPP[compileCommandCPP.length - 2] = sourcesCPP[i].getPath();
compileCommandCPP[compileCommandCPP.length - 1] = "-o" + pathSansExtension + ".o";
process = Runtime.getRuntime().exec(compileCommandCPP);
new MessageSiphon(process.getInputStream(), this);
new MessageSiphon(process.getErrorStream(), this);
// wait for the process to finish. if interrupted
// before waitFor returns, continue waiting
//
compiling = true;
while (compiling) {
try {
result = process.waitFor();
//System.out.println("result is " + result);
compiling = false;
} catch (InterruptedException ignored) { }
}
if (exception != null) {
//exception.hideStackTrace = true;
throw exception;
}
if(result != 0){
return false;
}
}
} catch (Exception e) {
String msg = e.getMessage();
if ((msg != null) && (msg.indexOf("avr-gcc: not found") != -1)) {
Base.showWarning("Compiler error",
"Could not find the compiler.\n" +
"avr-gcc is missing from your PATH,\n" +
"see readme.txt for help.", null);
return false;
} else if ((msg != null) && (msg.indexOf("avr-g++: not found") != -1)) {
Base.showWarning("Compiler error",
"Could not find the compiler.\n" +
"avr-g++ is missing from your PATH,\n" +
"see readme.txt for help.", null);
return false;
} else {
e.printStackTrace();
result = -1;
}
}
// an error was queued up by message()
if (exception != null) {
throw exception;
}
if (result != 0 && result != 1 ) {
Base.openURL(BUGS_URL);
throw new RunnerException(SUPER_BADNESS);
}
// success would mean that 'result' is set to zero
return (result == 0); // ? true : false;
}
/**
* Part of the MessageConsumer interface, this is called
* whenever a piece (usually a line) of error message is spewed
* out from the compiler. The errors are parsed for their contents
* and line number, which is then reported back to Editor.
*/
public void message(String inString) {
// This receives messages as full lines, so a newline needs
// to be added as they're printed to the console.
// always print all compilation output for library writers!
String outString = "";
// shorten file paths so that they are friendlier
int start = 0;
int end = 0;
String substring = libFolder.getPath() + File.separator;
StringBuffer result = new StringBuffer();
while ((end = inString.indexOf(substring, start)) >= 0) {
result.append(inString.substring(start, end));
start = end + substring.length();
}
result.append(inString.substring(start));
outString = result.toString();
System.err.print(outString);
// prepare error for throwing
if (inString.indexOf("error") != -1){
exception = new RunnerException("Error building library \"" + getName() + "\"");
}
}
/**
* Handles loading of keywords file.
* It is recommended that a # sign be used for comments
* inside keywords.txt.
*/
public void addSyntaxColors(PdeKeywords keywords) {
File keywordsFile = new File(libFolder.getPath() + File.separator + "keywords.txt");
// do not bother if no keywords file to read
// should reprimand negligent library writers?!
if(!keywordsFile.exists() || !keywordsFile.canRead()){
return;
}
try{
// open file stream in the verbose java way
InputStream input = new FileInputStream(keywordsFile);
InputStreamReader isr = new InputStreamReader(input);
BufferedReader reader = new BufferedReader(isr);
String line = null;
while ((line = reader.readLine()) != null) {
// skip empty and whitespace lines
if (line.trim().length() == 0){
continue;
}
// skip lines without tabs
if (line.indexOf('\t') == -1){
continue;
}
String pieces[] = PApplet.split(line, '\t');
if (pieces.length >= 2) {
String keyword = pieces[0].trim();
String coloring = pieces[1].trim();
if (coloring.length() > 0) {
// text will be KEYWORD or LITERAL
boolean isKey = (coloring.charAt(0) == 'K');
// KEYWORD1 -> 0, KEYWORD2 -> 1, etc
int num = coloring.charAt(coloring.length() - 1) - '1';
byte id = (byte)((isKey ? Token.KEYWORD1 : Token.LITERAL1) + num);
//System.out.println("got " + (isKey ? "keyword" : "literal") + (num+1) + " for " + keyword);
// XXX: DAM: PdeKeywords.getKeywordColoring().add(keyword, id);
}
}
}
// close file stream
reader.close();
} catch (Exception e) {
Base.showError("Problem Loading Keywords",
"Could not load or interpret 'keywords.txt' in " + getName() + " library.\n" +
"This must be corrected before distributing.", e);
}
}
}

View File

@ -0,0 +1,274 @@
/*
LibraryManager.java - Library System for Wiring
Copyright (c) 2006-07 Nicholas Zambetti. All right reserved.
This library 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 2.1 of the License, or (at your option) any later version.
This library 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
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
package processing.app.debug;
import processing.app.Base;
import processing.app.Preferences;
import processing.app.syntax.*;
import processing.app.debug.RunnerException;
import java.io.*;
import java.util.*;
import java.util.zip.*;
import java.awt.event.*;
import javax.swing.*;
/*
* Provides information about and builds libraries
*/
public class LibraryManager {
private File libDir;
private List libraries = new ArrayList();
private Target target;
/*
* Create a LibraryManager.
*/
public LibraryManager() throws IOException
{
String userDir = System.getProperty("user.dir") + File.separator;
libDir = new File(Base.getHardwareFolder(), "libraries");
// target = new Target(
// System.getProperty("user.dir") + File.separator + "hardware" +
// File.separator + "cores",
// Preferences.get("boards." + Preferences.get("board") + ".build.core"));
target = new Target(Base.getHardwarePath() + File.separator + "cores",
"arduino");
refreshLibraries();
}
public Target getTarget()
{
return target;
}
/*
* Scans for libraries and refreshes internal list
*/
private void refreshLibraries()
{
FileFilter onlyDirs = new FileFilter() {
public boolean accept(File file) {
return file.isDirectory();
}
};
libraries.clear();
File[] libs = libDir.listFiles(onlyDirs);
for(int i = 0; i < libs.length; ++i){
libraries.add(new Library(this, libs[i]));
}
}
/*
* Returns a collection of all library objects
* @return A read-only collection of Library objects
*/
public Collection getAll() {
refreshLibraries();
return Collections.unmodifiableList(libraries);
}
/*
* Returns a collection of all built library objects
* @return A read-only collection of built Library objects
*/
public Collection getBuiltLibraries() {
refreshLibraries();
List builtLibraries = new ArrayList();
Library library;
ListIterator libIterator = libraries.listIterator();
while(libIterator.hasNext()){
library = (Library)libIterator.next();
if(library.isBuilt()){
builtLibraries.add(library);
}
}
return Collections.unmodifiableList(builtLibraries);
}
/*
* Returns a collection of all buildable library objects
* @return A read-only collection of built Library objects
*/
public Collection getLibrariesToBuild() {
refreshLibraries();
List buildableLibraries = new ArrayList();
Library library;
ListIterator libIterator = libraries.listIterator();
while(libIterator.hasNext()){
library = (Library)libIterator.next();
if(library.isUnbuiltBuildable()){
buildableLibraries.add(library);
}
}
return Collections.unmodifiableList(buildableLibraries);
}
/*
* Rebuilds built libraries
* @return Number of libraries built as int, -1 & exception on error
*/
public int rebuildAllBuilt() throws RunnerException {
Collection builtLibraries = getBuiltLibraries();
Library library;
Iterator libIterator = builtLibraries.iterator();
int countBuilt = 0;
while(libIterator.hasNext()){
library = (Library)libIterator.next();
//System.out.println("Building library \"" + library.getName() + "\"");
try {
if(library.build()){
++countBuilt;
}else{
return -1;
}
}catch (RunnerException re) {
throw new RunnerException(re.getMessage());
} catch (Exception ex) {
throw new RunnerException(ex.toString());
}
}
return countBuilt;
}
/*
* Gathers paths to object files
* @return Array of strings of paths to object files
*/
public String[] getObjectFiles() {
ArrayList filesArrayList = new ArrayList();
Collection builtLibraries = getBuiltLibraries();
Library library;
File[] files;
Iterator libIterator = builtLibraries.iterator();
while(libIterator.hasNext()){
library = (Library)libIterator.next();
files = library.getObjectFiles();
for(int i = 0; i < files.length; ++i){
filesArrayList.add(files[i].getPath());
}
}
String[] filesArray = new String[filesArrayList.size()];
filesArrayList.toArray(filesArray);
return filesArray;
}
/*
* Gathers filenames of header files
* @return Array of strings of filenames of header files
*/
public String[] getHeaderFiles() {
ArrayList filesArrayList = new ArrayList();
Collection builtLibraries = getBuiltLibraries();
Library library;
File[] files;
Iterator libIterator = builtLibraries.iterator();
while(libIterator.hasNext()){
library = (Library)libIterator.next();
files = library.getHeaderFiles();
for(int i = 0; i < files.length; ++i){
filesArrayList.add(files[i].getName());
}
}
String[] filesArray = new String[filesArrayList.size()];
filesArrayList.toArray(filesArray);
return filesArray;
}
/*
* Gathers paths to library folders
* @return Array of strings of paths to library folders
*/
public String[] getFolderPaths() {
ArrayList foldersArrayList = new ArrayList();
//Collection builtLibraries = getBuiltLibraries();
Collection libraries = getAll();
Library library;
//Iterator libIterator = builtLibraries.iterator();
Iterator libIterator = libraries.iterator();
while(libIterator.hasNext()){
library = (Library)libIterator.next();
foldersArrayList.add(library.getFolder().getPath());
}
String[] foldersArray = new String[foldersArrayList.size()];
foldersArrayList.toArray(foldersArray);
return foldersArray;
}
/*
* Builds unbuilt libraries
* @return Number of libraries built as int, -1 & exception on error
*/
public int buildAllUnbuilt() throws RunnerException {
Collection buildableLibraries = getLibrariesToBuild();
Library library;
Iterator libIterator = buildableLibraries.iterator();
int countBuilt = 0;
while(libIterator.hasNext()){
library = (Library)libIterator.next();
//System.out.println("Building library \"" + library.getName() + "\"");
try {
if(library.build()){
++countBuilt;
}else{
return -1;
}
}catch (RunnerException re) {
throw new RunnerException(re.getMessage());
} catch (Exception ex) {
throw new RunnerException(ex.toString());
}
}
return countBuilt;
}
/*
* Populates examples menu with library folders
*/
public void populateExamplesMenu(JMenu examplesMenu, ActionListener listener) {
Library library;
Collection libraries = getBuiltLibraries();
Iterator iterator = libraries.iterator();
JMenu libraryExamples;
while(iterator.hasNext()){
library = (Library)iterator.next();
libraryExamples = library.getExamplesMenu(listener);
if(null != libraryExamples){
examplesMenu.add(libraryExamples);
}
}
}
/*
* Add syntax coloring
*/
public void addSyntaxColoring(PdeKeywords keywords) {
Library library;
Collection libraries = getBuiltLibraries();
Iterator iterator = libraries.iterator();
while(iterator.hasNext()){
library = (Library)iterator.next();
library.addSyntaxColors(keywords);
}
}
}

View File

@ -44,7 +44,7 @@ class MessageSiphon implements Runnable {
// bubble up in time (i.e. compile errors have a weird delay)
//thread.setPriority(Thread.MIN_PRIORITY);
thread.setPriority(Thread.MAX_PRIORITY-1);
//thread.start();
thread.start();
}

View File

@ -0,0 +1,79 @@
/* -*- mode: jde; c-basic-offset: 2; indent-tabs-mode: nil -*- */
/*
Target - represents a target platform
Part of the Arduino project - http://arduino.berlios.de/
Copyright (c) 2005
David A. Mellis
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 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 Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software Foundation,
Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
$Id: Target.java 85 2006-01-12 23:24:12Z mellis $
*/
package processing.app.debug;
import java.io.*;
import java.util.*;
/**
* Represents a target platform (e.g. Wiring board, Arduino board).
*/
public class Target {
String path;
List sources = new ArrayList();
List objects = new ArrayList();
/**
* Create a Target.
* @param path the directory containing config, source, and object files for
* the target platform.
*/
public Target(String base, String target) throws IOException {
path = base + File.separator + target;
String[] files = (new File(path)).list();
if (files == null)
throw new IOException("Target platform: \"" + target + "\" not found.\n" +
"Make sure that \"build.target\" in the \n" +
"preferences file points to a subdirectory of \n" +
base);
for (int i = 0; i < files.length; i++) {
if (files[i].endsWith(".c") || files[i].endsWith(".cpp"))
sources.add(files[i]);
if (files[i].endsWith(".o"))
objects.add(files[i]);
}
}
public String getPath() { return path; }
/**
* The source files in the library for the target platform.
* @return A read-only collection of strings containing the name of each source file.
*/
public Collection getSourceFilenames() {
return Collections.unmodifiableList(sources);
}
/**
* The object files in the library for the target platform.
* @return A read-only collection of strings containing the name of each object file.
*/
public Collection getObjectFilenames() {
return Collections.unmodifiableList(objects);
}
}

View File

@ -80,12 +80,12 @@ public class Platform extends processing.app.Platform {
public File getSettingsFolder() throws Exception {
return new File(getLibraryFolder(), "Processing");
return new File(getLibraryFolder(), "Arduino");
}
public File getDefaultSketchbookFolder() throws Exception {
return new File(getDocumentsFolder(), "Processing");
return new File(getDocumentsFolder(), "Arduino");
/*
// looking for /Users/blah/Documents/Processing
try {

View File

@ -1,936 +0,0 @@
/* -*- mode: java; c-basic-offset: 2; indent-tabs-mode: nil -*- */
package processing.app.preproc;
import processing.app.*;
import processing.app.debug.RunnerException;
/* Based on original code copyright (c) 2003 Andy Tripp <atripp@comcast.net>.
* shipped under GPL with permission.
*/
//import antlr.*;
import antlr.collections.*;
//import antlr.collections.impl.*;
import java.io.*;
//import java.util.*;
/**
* PDEEmitter: A class that can take an ANTLR Java AST and produce
* reasonably formatted Java code from it. To use it, create a
* PDEEmitter object, call setOut() if you want to print to something
* other than System.out, and then call print(), passing the
* AST. Typically, the AST node that you pass would be the root of a
* tree - the ROOT_ID node that represents a Java file.
*/
@SuppressWarnings("unused")
public class PdeEmitter implements PdeTokenTypes
{
private PrintStream out = System.out;
private PrintStream debug = System.err;
//private static int ALL = -1;
private java.util.Stack stack = new java.util.Stack();
private static String[] tokenNames;
private final static int ROOT_ID = 0;
static {
setupTokenNames();
}
/*
private static Hashtable publicMethods;
private static final String publicMethodList[] = {
"setup", "draw", //"loop",
"mousePressed", "mouseReleased", "mouseClicked",
"mouseEntered", "mouseExited",
"mouseMoved", "mouseDragged",
"keyPressed", "keyReleased", "keyTyped"
};
static {
publicMethods = new Hashtable();
for (int i = 0; i < publicMethodList.length; i++) {
publicMethods.put(publicMethodList[i], new Object());
}
}
*/
// Map each AST token type to a String
private static void setupTokenNames() {
tokenNames = new String[200];
for (int i=0; i<tokenNames.length; i++) {
tokenNames[i] = "ERROR:" + i;
}
tokenNames[POST_INC]="++";
tokenNames[POST_DEC]="--";
tokenNames[UNARY_MINUS]="-";
tokenNames[UNARY_PLUS]="+";
tokenNames[STAR]="*";
tokenNames[ASSIGN]="=";
tokenNames[PLUS_ASSIGN]="+=";
tokenNames[MINUS_ASSIGN]="-=";
tokenNames[STAR_ASSIGN]="*=";
tokenNames[DIV_ASSIGN]="/=";
tokenNames[MOD_ASSIGN]="%=";
tokenNames[SR_ASSIGN]=">>=";
tokenNames[BSR_ASSIGN]=">>>=";
tokenNames[SL_ASSIGN]="<<=";
tokenNames[BAND_ASSIGN]="&=";
tokenNames[BXOR_ASSIGN]="^=";
tokenNames[BOR_ASSIGN]="|=";
tokenNames[QUESTION]="?";
tokenNames[LOR]="||";
tokenNames[LAND]="&&";
tokenNames[BOR]="|";
tokenNames[BXOR]="^";
tokenNames[BAND]="&";
tokenNames[NOT_EQUAL]="!=";
tokenNames[EQUAL]="==";
tokenNames[LT]="<";
tokenNames[GT]=">";
tokenNames[LE]="<=";
tokenNames[GE]=">=";
tokenNames[SL]="<<";
tokenNames[SR]=">>";
tokenNames[BSR]=">>>";
tokenNames[PLUS]="+";
tokenNames[MINUS]="-";
tokenNames[DIV]="/";
tokenNames[MOD]="%";
tokenNames[INC]="++";
tokenNames[DEC]="--";
tokenNames[BNOT]="~";
tokenNames[LNOT]="!";
tokenNames[FINAL]="final";
tokenNames[ABSTRACT]="abstract";
tokenNames[LITERAL_package]="package";
tokenNames[LITERAL_import]="import";
tokenNames[LITERAL_void]="void";
tokenNames[LITERAL_boolean]="boolean";
tokenNames[LITERAL_byte]="byte";
tokenNames[LITERAL_char]="char";
tokenNames[LITERAL_short]="short";
tokenNames[LITERAL_int]="int";
tokenNames[LITERAL_float]="float";
tokenNames[LITERAL_long]="long";
tokenNames[LITERAL_double]="double";
tokenNames[LITERAL_private]="private";
tokenNames[LITERAL_public]="public";
tokenNames[LITERAL_protected]="protected";
tokenNames[LITERAL_static]="static";
tokenNames[LITERAL_transient]="transient";
tokenNames[LITERAL_native]="native";
tokenNames[LITERAL_threadsafe]="threadsafe";
tokenNames[LITERAL_synchronized]="synchronized";
tokenNames[LITERAL_volatile]="volatile";
tokenNames[LITERAL_class]="class";
tokenNames[LITERAL_extends]="extends";
tokenNames[LITERAL_interface]="interface";
tokenNames[LITERAL_implements]="implements";
tokenNames[LITERAL_throws]="throws";
tokenNames[LITERAL_if]="if";
tokenNames[LITERAL_else]="else";
tokenNames[LITERAL_for]="for";
tokenNames[LITERAL_while]="while";
tokenNames[LITERAL_do]="do";
tokenNames[LITERAL_break]="break";
tokenNames[LITERAL_continue]="continue";
tokenNames[LITERAL_return]="return";
tokenNames[LITERAL_switch]="switch";
tokenNames[LITERAL_throw]="throw";
tokenNames[LITERAL_case]="case";
tokenNames[LITERAL_default]="default";
tokenNames[LITERAL_try]="try";
tokenNames[LITERAL_finally]="finally";
tokenNames[LITERAL_catch]="catch";
tokenNames[LITERAL_instanceof]="instanceof";
tokenNames[LITERAL_this]="this";
tokenNames[LITERAL_super]="super";
tokenNames[LITERAL_true]="true";
tokenNames[LITERAL_false]="false";
tokenNames[LITERAL_null]="null";
tokenNames[LITERAL_new]="new";
tokenNames[LITERAL_color]="int"; // PDE specific alias
}
/**
* Specify a PrintStream to print to. System.out is the default.
* @param out the PrintStream to print to
*/
public void setOut(PrintStream out) {
this.out = out;
}
private String name(AST ast) {
return tokenNames[ast.getType()];
}
private String name(int type) {
return tokenNames[type];
}
/**
* Find a child of the given AST that has the given type
* @returns a child AST of the given type. If it can't find a child of the
* given type, return null.
*/
private AST getChild(AST ast, int childType) {
AST child = ast.getFirstChild();
while (child != null) {
if (child.getType() == childType) {
// debug.println("getChild: found:" + name(ast));
return child;
}
child = child.getNextSibling();
}
return null;
}
/**
* Dump the list of hidden tokens linked to after the AST node passed in.
* Most hidden tokens are dumped from this function.
*/
private void dumpHiddenAfter(AST ast) {
dumpHiddenTokens(((antlr.CommonASTWithHiddenTokens)ast).getHiddenAfter());
}
/**
* Dump the list of hidden tokens linked to before the AST node passed in.
* The only time hidden tokens need to be dumped with this function is when
* dealing parts of the tree where automatic tree construction was
* turned off with the ! operator in the grammar file and the nodes were
* manually constructed in such a way that the usual tokens don't have the
* necessary hiddenAfter links.
*/
private void dumpHiddenBefore(AST ast) {
antlr.CommonHiddenStreamToken
child = null,
parent = ((antlr.CommonASTWithHiddenTokens)ast).getHiddenBefore();
// if there aren't any hidden tokens here, quietly return
//
if (parent == null) {
return;
}
// traverse back to the head of the list of tokens before this node
do {
child = parent;
parent = child.getHiddenBefore();
} while (parent != null);
// dump that list
dumpHiddenTokens(child);
}
/**
* Dump the list of hidden tokens linked to from the token passed in.
*/
private void dumpHiddenTokens(antlr.CommonHiddenStreamToken t) {
for ( ; t != null ; t=PdePreprocessor.filter.getHiddenAfter(t) ) {
out.print(t.getText());
}
}
/**
* Print the children of the given AST
* @param ast The AST to print
* @returns true iff anything was printed
*/
private boolean printChildren(AST ast) throws RunnerException {
boolean ret = false;
AST child = ast.getFirstChild();
while (child != null) {
ret = true;
print(child);
child = child.getNextSibling();
}
return ret;
}
/**
* Tells whether an AST has any children or not.
* @return true iff the AST has at least one child
*/
private boolean hasChildren(AST ast) {
return (ast.getFirstChild() != null);
}
/**
* Gets the best node in the subtree for printing. This really means
* the next node which could potentially have hiddenBefore data. It's
* usually the first printable leaf, but not always.
*
* @param includeThisNode Should this node be included in the search?
* If false, only descendants are searched.
*
* @return the first printable leaf node in an AST
*/
private AST getBestPrintableNode(AST ast, boolean includeThisNode) {
AST child;
if (includeThisNode) {
child = ast;
} else {
child = ast.getFirstChild();
}
if (child != null) {
switch (child.getType()) {
// the following node types are printing nodes that print before
// any children, but then also recurse over children. So they
// may have hiddenBefore chains that need to be printed first. Many
// statements and all unary expression types qualify. Return these
// nodes directly
case CLASS_DEF:
case LITERAL_if:
case LITERAL_for:
case LITERAL_while:
case LITERAL_do:
case LITERAL_break:
case LITERAL_continue:
case LITERAL_return:
case LITERAL_switch:
case LITERAL_try:
case LITERAL_throw:
case LITERAL_synchronized:
case LITERAL_assert:
case BNOT:
case LNOT:
case INC:
case DEC:
case UNARY_MINUS:
case UNARY_PLUS:
return child;
// Some non-terminal node types (at the moment, I only know of
// MODIFIERS, but there may be other such types), can be
// leaves in the tree but not have any children. If this is
// such a node, move on to the next sibling.
case MODIFIERS:
if (child.getFirstChild() == null ) {
return getBestPrintableNode(child.getNextSibling(), false);
}
// new jikes doesn't like fallthrough, so just duplicated here:
return getBestPrintableNode(child, false);
default:
return getBestPrintableNode(child, false);
}
}
return ast;
}
/**
* Prints a binary operator
*/
private void printBinaryOperator(AST ast) throws RunnerException {
print(ast.getFirstChild());
out.print(name(ast));
dumpHiddenAfter(ast);
print(ast.getFirstChild().getNextSibling());
}
/**
* Print the given AST. Call this function to print your PDE code.
*
* It works by making recursive calls to print children.
* So the code below is one big "switch" statement on the passed AST type.
*/
public void print (AST ast) throws RunnerException {
if (ast == null) {
return;
}
AST parent = null;
if (!stack.isEmpty()) {
parent = (AST) stack.peek();
}
stack.push(ast);
AST child1 = ast.getFirstChild();
AST child2 = null;
AST child3 = null;
if (child1 != null) {
child2 = child1.getNextSibling();
if (child2 != null) {
child3 = child2.getNextSibling();
}
}
switch(ast.getType()) {
// The top of the tree looks like this:
// ROOT_ID "Whatever.java"
// package
// imports
// class definition
case ROOT_ID:
dumpHiddenTokens(PdePreprocessor.filter.getInitialHiddenToken());
printChildren(ast);
break;
// supporting a "package" statement in a PDE program has
// a bunch of issues with it that need to dealt in the compilation
// code too, so this isn't actually tested.
case PACKAGE_DEF:
out.print("package");
dumpHiddenAfter(ast);
print(ast.getFirstChild());
break;
// IMPORT has exactly one child
case IMPORT:
out.print("import");
dumpHiddenAfter(ast);
print(ast.getFirstChild());
break;
case CLASS_DEF:
case INTERFACE_DEF:
print(getChild(ast, MODIFIERS));
if (ast.getType() == CLASS_DEF) {
out.print("class");
} else {
out.print("interface");
}
dumpHiddenBefore(getChild(ast, IDENT));
print(getChild(ast, IDENT));
print(getChild(ast, EXTENDS_CLAUSE));
print(getChild(ast, IMPLEMENTS_CLAUSE));
print(getChild(ast, OBJBLOCK));
break;
case EXTENDS_CLAUSE:
if (hasChildren(ast)) {
out.print("extends");
dumpHiddenBefore(getBestPrintableNode(ast, false));
printChildren(ast);
}
break;
case IMPLEMENTS_CLAUSE:
if (hasChildren(ast)) {
out.print("implements");
dumpHiddenBefore(getBestPrintableNode(ast, false));
printChildren(ast);
}
break;
// DOT always has exactly two children.
case DOT:
print(child1);
out.print(".");
dumpHiddenAfter(ast);
print(child2);
break;
case MODIFIERS:
case OBJBLOCK:
case CTOR_DEF:
//case METHOD_DEF:
case PARAMETERS:
case PARAMETER_DEF:
case VARIABLE_DEF:
case TYPE:
case SLIST:
case ELIST:
case ARRAY_DECLARATOR:
case TYPECAST:
case EXPR:
case ARRAY_INIT:
case FOR_INIT:
case FOR_CONDITION:
case FOR_ITERATOR:
case METHOD_CALL:
case INSTANCE_INIT:
case INDEX_OP:
case SUPER_CTOR_CALL:
case CTOR_CALL:
printChildren(ast);
break;
case METHOD_DEF:
// kids seem to be: MODIFIERS TYPE setup PARAMETERS
//AST parent = (AST) stack.peek();
AST modifiersChild = ast.getFirstChild();
AST typeChild = modifiersChild.getNextSibling();
AST methodNameChild = typeChild.getNextSibling();
AST parametersChild = methodNameChild.getNextSibling();
// to output, use print(child) on each of the four
String methodName = methodNameChild.getText();
if (methodName.equals("main")) {
PdePreprocessor.foundMain = true;
}
/*
// 1. figure out if this is setup, draw, or loop
String methodName = methodNameChild.getText();
if (publicMethods.get(methodName) != null) {
// make sure this feller is public
boolean foundPublic = false;
AST child = modifiersChild.getFirstChild();
while (child != null) {
if (child.getText().equals("public")) {
foundPublic = true;
child = null;
} else {
//out.print("." + child.getText() + ".");
child = child.getNextSibling();
}
}
if (!foundPublic) {
out.print("public ");
}
*/
// if this method doesn't have a specifier, make it public
// (useful for setup/keyPressed/etc)
boolean foundSpecifier = false;
AST child = modifiersChild.getFirstChild();
while (child != null) {
String childText = child.getText();
if (childText.equals("public") ||
childText.equals("protected") ||
childText.equals("private")) {
foundSpecifier = true;
child = null;
} else {
//out.print("." + child.getText() + ".");
child = child.getNextSibling();
}
}
if (!foundSpecifier) {
out.print("public ");
}
printChildren(ast); // everything is fine
break;
// if we have two children, it's of the form "a=0"
// if just one child, it's of the form "=0" (where the
// lhs is above this AST).
case ASSIGN:
if (child2 != null) {
print(child1);
out.print("=");
dumpHiddenAfter(ast);
print(child2);
}
else {
out.print("=");
dumpHiddenAfter(ast);
print(child1);
}
break;
// binary operators:
case PLUS:
case MINUS:
case DIV:
case MOD:
case NOT_EQUAL:
case EQUAL:
case LT:
case GT:
case LE:
case GE:
case LOR:
case LAND:
case BOR:
case BXOR:
case BAND:
case SL:
case SR:
case BSR:
case LITERAL_instanceof:
case PLUS_ASSIGN:
case MINUS_ASSIGN:
case STAR_ASSIGN:
case DIV_ASSIGN:
case MOD_ASSIGN:
case SR_ASSIGN:
case BSR_ASSIGN:
case SL_ASSIGN:
case BAND_ASSIGN:
case BXOR_ASSIGN:
case BOR_ASSIGN:
printBinaryOperator(ast);
break;
case LITERAL_for:
out.print(name(ast));
dumpHiddenAfter(ast);
printChildren(ast);
break;
case POST_INC:
case POST_DEC:
print(child1);
out.print(name(ast));
dumpHiddenAfter(ast);
break;
// unary operators:
case BNOT:
case LNOT:
case INC:
case DEC:
case UNARY_MINUS:
case UNARY_PLUS:
out.print(name(ast));
dumpHiddenAfter(ast);
print(child1);
break;
case LITERAL_new:
out.print("new");
dumpHiddenAfter(ast);
print(child1);
print(child2);
// "new String[] {...}": the stuff in {} is child3
if (child3 != null) {
print(child3);
}
break;
case LITERAL_return:
out.print("return");
dumpHiddenAfter(ast);
print(child1);
break;
case STATIC_INIT:
out.print("static");
dumpHiddenBefore(getBestPrintableNode(ast, false));
print(child1);
break;
case LITERAL_switch:
out.print("switch");
dumpHiddenAfter(ast);
printChildren(ast);
break;
case CASE_GROUP:
printChildren(ast);
break;
case LITERAL_case:
out.print("case");
dumpHiddenAfter(ast);
printChildren(ast);
break;
case LITERAL_default:
out.print("default");
dumpHiddenAfter(ast);
printChildren(ast);
break;
case NUM_INT:
case CHAR_LITERAL:
case STRING_LITERAL:
case NUM_FLOAT:
case NUM_LONG:
out.print(ast.getText());
dumpHiddenAfter(ast);
break;
case LITERAL_synchronized: // 0137 to fix bug #136
out.print(name(ast));
dumpHiddenAfter(ast);
printChildren(ast);
break;
case LITERAL_private:
case LITERAL_public:
case LITERAL_protected:
case LITERAL_static:
case LITERAL_transient:
case LITERAL_native:
case LITERAL_threadsafe:
//case LITERAL_synchronized: // 0137 to fix bug #136
case LITERAL_volatile:
case FINAL:
case ABSTRACT:
case LITERAL_package:
case LITERAL_void:
case LITERAL_boolean:
case LITERAL_byte:
case LITERAL_char:
case LITERAL_short:
case LITERAL_int:
case LITERAL_float:
case LITERAL_long:
case LITERAL_double:
case LITERAL_true:
case LITERAL_false:
case LITERAL_null:
case SEMI:
case LITERAL_this:
case LITERAL_super:
case LITERAL_continue:
case LITERAL_break:
out.print(name(ast));
dumpHiddenAfter(ast);
break;
case EMPTY_STAT:
case EMPTY_FIELD:
break;
// yuck: Distinguish between "import x.y.*" and "x = 1 * 3"
case STAR:
if (hasChildren(ast)) { // the binary mult. operator
printBinaryOperator(ast);
}
else { // the special "*" in import:
out.print("*");
dumpHiddenAfter(ast);
}
break;
case LITERAL_throws:
out.print("throws");
dumpHiddenAfter(ast);
printChildren(ast);
break;
case LITERAL_if:
out.print("if");
dumpHiddenAfter(ast);
print(child1); // the "if" condition: an EXPR
print(child2); // the "then" clause is an SLIST
if (child3 != null) {
out.print("else");
dumpHiddenBefore(getBestPrintableNode(child3, true));
print(child3); // optional "else" clause: an SLIST
}
break;
case LITERAL_while:
out.print("while");
dumpHiddenAfter(ast);
printChildren(ast);
break;
case LITERAL_do:
out.print("do");
dumpHiddenAfter(ast);
print(child1); // an SLIST
out.print("while");
dumpHiddenBefore(getBestPrintableNode(child2, false));
print(child2); // an EXPR
break;
case LITERAL_try:
out.print("try");
dumpHiddenAfter(ast);
printChildren(ast);
break;
case LITERAL_catch:
out.print("catch");
dumpHiddenAfter(ast);
printChildren(ast);
break;
// the first child is the "try" and the second is the SLIST
case LITERAL_finally:
out.print("finally");
dumpHiddenAfter(ast);
printChildren(ast);
break;
case LITERAL_throw:
out.print("throw");
dumpHiddenAfter(ast);
print(child1);
break;
// the dreaded trinary operator
case QUESTION:
print(child1);
out.print("?");
dumpHiddenAfter(ast);
print(child2);
print(child3);
break;
// pde specific or modified tokens start here
// Image -> BImage, Font -> BFont as appropriate
case IDENT:
/*
if (ast.getText().equals("Image") &&
Preferences.getBoolean("preproc.substitute_image")) { //, true)) {
out.print("BImage");
} else if (ast.getText().equals("Font") &&
Preferences.getBoolean("preproc.substitute_font")) { //, true)) {
out.print("BFont");
} else {
*/
out.print(ast.getText());
//}
dumpHiddenAfter(ast);
break;
// the color datatype is just an alias for int
case LITERAL_color:
out.print("int");
dumpHiddenAfter(ast);
break;
case WEBCOLOR_LITERAL:
if (ast.getText().length() != 6) {
System.err.println("Internal error: incorrect length of webcolor " +
"literal should have been detected sooner.");
break;
}
out.print("0xff" + ast.getText());
dumpHiddenAfter(ast);
break;
// allow for stuff like int(43.2).
case CONSTRUCTOR_CAST:
AST nonTerminalTypeNode = child1;
AST terminalTypeNode = child1.getFirstChild();
AST exprToCast = child2;
/*
// if this is a string type, add .valueOf()
if (nonTerminalTypeNode.getType() == PdeRecognizer.TYPE &&
terminalTypeNode.getText().equals("String")) {
out.print(terminalTypeNode.getText() + ".valueOf");
dumpHiddenAfter(terminalTypeNode);
print(exprToCast);
// if the expresion to be cast is a string literal, try and parse it.
//
// ideally, we'd be able to do this for all expressions with a
// string type, not just string literals. however, the parser
// doesn't currently track expression type, and for full
// functionality, we'd need to do semantic analysis to handle
// imports so that we could know the return types of method calls.
//
} else if (exprToCast.getFirstChild().getType() == STRING_LITERAL ) {
switch (terminalTypeNode.getType()) {
case PdeRecognizer.LITERAL_byte:
out.print("Byte.parseByte");
dumpHiddenAfter(terminalTypeNode);
print(exprToCast);
break;
case PdeRecognizer.LITERAL_double:
out.print("(new Double");
dumpHiddenAfter(terminalTypeNode);
out.print(exprToCast.getFirstChild().getText() + ").doubleValue()");
dumpHiddenAfter(exprToCast.getFirstChild());
break;
case PdeRecognizer.LITERAL_float:
out.print("(new Float");
dumpHiddenAfter(terminalTypeNode);
out.print(exprToCast.getFirstChild().getText() + ").floatValue()");
dumpHiddenAfter(exprToCast.getFirstChild());
break;
case PdeRecognizer.LITERAL_int:
case PdeRecognizer.LITERAL_color:
out.print("Integer.parseInt");
dumpHiddenAfter(terminalTypeNode);
print(exprToCast);
break;
case PdeRecognizer.LITERAL_long:
out.print("Long.parseLong");
break;
case PdeRecognizer.LITERAL_short:
out.print("Short.parseShort");
break;
default:
throw new RunnerException(Compiler.SUPER_BADNESS);
}
// for builtin types, use regular casting syntax
} else {
*/
// result of below is (int)(4.0
//out.print("(");
//out.print(terminalTypeNode.getText() + ")"); // typename
//dumpHiddenAfter(terminalTypeNode);
//print(exprToCast);
//}
//out.print("(");
String pooType = terminalTypeNode.getText();
out.print("PApplet.parse" +
Character.toUpperCase(pooType.charAt(0)) +
pooType.substring(1));
dumpHiddenAfter(terminalTypeNode); // the left paren
print(exprToCast);
//out.print("x)");
break;
// making floating point literals default to floats, not doubles
case NUM_DOUBLE:
out.print(ast.getText());
if (Preferences.getBoolean("preproc.substitute_floats")) { //, true) ) {
out.print("f");
}
dumpHiddenAfter(ast);
break;
default:
debug.println("Invalid type:" + ast.getType());
break;
/* The following are tokens, but I don't think JavaRecognizer
ever produces an AST with one of these types:
case COMMA:
case LITERAL_implements:
case LITERAL_class:
case LITERAL_extends:
case EOF:
case NULL_TREE_LOOKAHEAD:
case BLOCK:
case LABELED_STAT: // refuse to implement on moral grounds :)
case LITERAL_import:
case LBRACK:
case RBRACK:
case LCURLY:
case RCURLY:
case LPAREN:
case RPAREN:
case LITERAL_else: // else is a child of "if" AST
case COLON: // part of the trinary operator
case WS: // whitespace
case ESC:
case HEX_DIGIT:
case VOCAB:
case EXPONENT: // exponents and float suffixes are left in the NUM_FLOAT
case FLOAT_SUFFIX
*/
}
stack.pop();
}
}

View File

@ -1,10 +1,12 @@
/* -*- mode: java; c-basic-offset: 2; indent-tabs-mode: nil -*- */
/* -*- mode: jde; c-basic-offset: 2; indent-tabs-mode: nil -*- */
/*
PdePreprocessor - wrapper for default ANTLR-generated parser
Part of the Processing project - http://processing.org
Part of the Wiring project - http://wiring.org.co
Copyright (c) 2004-08 Ben Fry and Casey Reas
Copyright (c) 2004-05 Hernando Barragan
Processing version Copyright (c) 2004-05 Ben Fry and Casey Reas
Copyright (c) 2001-04 Massachusetts Institute of Technology
ANTLR-generated parser and several supporting classes written
@ -28,169 +30,201 @@
package processing.app.preproc;
import processing.app.*;
import processing.app.debug.Target;
import processing.core.*;
import java.io.*;
import java.util.*;
import java.util.ArrayList;
import java.util.List;
import antlr.*;
import antlr.collections.*;
import antlr.collections.impl.*;
import com.oroinc.text.regex.*;
/**
* Class that orchestrates preprocessing p5 syntax into straight Java.
* <P/>
* <B>Current Preprocessor Subsitutions:</B>
* <UL>
* <LI>any function not specified as being protected or private will
* be made 'public'. this means that <TT>void setup()</TT> becomes
* <TT>public void setup()</TT>. This is important to note when
* coding with core.jar outside of the PDE.
* <LI><TT>compiler.substitute_floats</TT> (currently "substitute_f")
* treat doubles as floats, i.e. 12.3 becomes 12.3f so that people
* don't have to add f after their numbers all the time since it's
* confusing for beginners.
* <LI><TT>compiler.enhanced_casting</TT> byte(), char(), int(), float()
* works for casting. this is basic in the current implementation, but
* should be expanded as described above. color() works similarly to int(),
* however there is also a *function* called color(r, g, b) in p5.
* <LI><TT>compiler.color_datatype</TT> 'color' is aliased to 'int'
* as a datatype to represent ARGB packed into a single int, commonly
* used in p5 for pixels[] and other color operations. this is just a
* search/replace type thing, and it can be used interchangeably with int.
* <LI><TT>compiler.web_colors</TT> (currently "inline_web_colors")
* color c = #cc0080; should unpack to 0xffcc0080 (the ff at the top is
* so that the color is opaque), which is just an int.
* </UL>
* <B>Other preprocessor functionality</B>
* <UL>
* <LI>detects what 'mode' the program is in: static (no function
* brackets at all, just assumes everything is in draw), active
* (setup plus draw or loop), and java mode (full java support).
* http://processing.org/reference/environment/
* </UL>
* <P/>
* The PDE Preprocessor is based on the Java Grammar that comes with
* ANTLR 2.7.2. Moving it forward to a new version of the grammar
* shouldn't be too difficult.
* <P/>
* Here's some info about the various files in this directory:
* <P/>
* <TT>java.g:</TT> this is the ANTLR grammar for Java 1.3/1.4 from the
* ANTLR distribution. It is in the public domain. The only change to
* this file from the original this file is the uncommenting of the
* clauses required to support assert().
* <P/>
* <TT>java.tree.g:</TT> this describes the Abstract Syntax Tree (AST)
* generated by java.g. It is only here as a reference for coders hacking
* on the preprocessor, it is not built or used at all. Note that pde.g
* overrides some of the java.g rules so that in PDE ASTs, there are a
* few minor differences. Also in the public domain.
* <P/>
* <TT>pde.g:</TT> this is the grammar and lexer for the PDE language
* itself. It subclasses the java.g grammar and lexer. There are a couple
* of overrides to java.g that I hope to convince the ANTLR folks to fold
* back into their grammar, but most of this file is highly specific to
* PDE itself.
* <TT>PdeEmitter.java:</TT> this class traverses the AST generated by
* the PDE Recognizer, and emits it as Java code, doing any necessary
* transformations along the way. It is based on JavaEmitter.java,
* available from antlr.org, written by Andy Tripp <atripp@comcast.net>,
* who has given permission for it to be distributed under the GPL.
* <P/>
* <TT>ExtendedCommonASTWithHiddenTokens.java:</TT> this adds a necessary
* initialize() method, as well as a number of methods to allow for XML
* serialization of the parse tree in a such a way that the hidden tokens
* are visible. Much of the code is taken from the original
* CommonASTWithHiddenTokens class. I hope to convince the ANTLR folks
* to fold these changes back into that class so that this file will be
* unnecessary.
* <P/>
* <TT>TokenStreamCopyingHiddenTokenFilter.java:</TT> this class provides
* TokenStreamHiddenTokenFilters with the concept of tokens which can be
* copied so that they are seen by both the hidden token stream as well
* as the parser itself. This is useful when one wants to use an
* existing parser (like the Java parser included with ANTLR) that throws
* away some tokens to create a parse tree which can be used to spit out
* a copy of the code with only minor modifications. Partially derived
* from ANTLR code. I hope to convince the ANTLR folks to fold this
* functionality back into ANTLR proper as well.
* <P/>
* <TT>whitespace_test.pde:</TT> a torture test to ensure that the
* preprocessor is correctly preserving whitespace, comments, and other
* hidden tokens correctly. See the comments in the code for details about
* how to run the test.
* <P/>
* All other files in this directory are generated at build time by ANTLR
* itself. The ANTLR manual goes into a fair amount of detail about the
* what each type of file is for.
* <P/>
*/
public class PdePreprocessor {
String[] defaultImports;
static final int JDK11 = 0;
static final int JDK13 = 1;
static final int JDK14 = 2;
// these ones have the .* at the end, since a class name might be at the end
// instead of .* which would make trouble other classes using this can lop
// off the . and anything after it to produce a package name consistently.
//static String defaultImports[][] = new String[3][];
// these ones have the .* at the end, since a class name
// might be at the end instead of .* whcih would make trouble
// other classes using this can lop of the . and anything after
// it to produce a package name consistently.
//public String extraImports[];
ArrayList<String> programImports;
// imports just from the code folder, treated differently
// than the others, since the imports are auto-generated.
ArrayList<String> codeFolderImports;
static public final int STATIC = 0; // formerly BEGINNER
static public final int ACTIVE = 1; // formerly INTERMEDIATE
static public final int JAVA = 2; // formerly ADVANCED
// static to make it easier for the antlr preproc to get at it
static public int programType;
static public boolean foundMain;
static public int programType = -1;
String indent;
PrintStream stream;
Reader programReader;
String buildPath;
String name;
// used for calling the ASTFactory to get the root node
private static final int ROOT_ID = 0;
// stores number of built user-defined function prototypes
public int prototypeCount = 0;
// stores number of included library headers written
public int headerCount = 0;
/**
* These may change in-between (if the prefs panel adds this option)
* so grab them here on construction.
*/
public PdePreprocessor() {}
/**
* Used by PdeEmitter.dumpHiddenTokens()
*/
public static TokenStreamCopyingHiddenTokenFilter filter;
static String advClassName = "";
//public static TokenStreamCopyingHiddenTokenFilter filter;
/**
* Returns the index of the first character that's not whitespace, a comment
* or a pre-processor directive.
*/
public int firstStatement(String in) {
PatternMatcherInput input = new PatternMatcherInput(in);
PatternCompiler compiler = new Perl5Compiler();
PatternMatcher matcher = new Perl5Matcher();
Pattern pattern = null;
try {
pattern = compiler.compile(
// XXX: doesn't properly handle special single-quoted characters
// whitespace
"\\s+" + "|" +
// multi-line comment
"(/\\*[^*]*(?:\\*(?!/)[^*]*)*\\*/)" + "|" +
// single-line comment
"(//.*?$)" + "|" +
// pre-processor directive
"(#(?:\\\\\\n|.)*)",
Perl5Compiler.MULTILINE_MASK);
} catch (MalformedPatternException e) {
throw new RuntimeException("Internal error in firstStatement()", e);
}
int i = 0;
while (matcher.matchesPrefix(input, pattern)) {
i = matcher.getMatch().endOffset(0);
input.setCurrentOffset(i);
}
return i;
}
/**
* Strips comments, pre-processor directives, single- and double-quoted
* strings from a string.
* @param in the String to strip
* @return the stripped String
*/
public String strip(String in) throws MalformedPatternException {
PatternCompiler compiler = new Perl5Compiler();
PatternMatcher matcher = new Perl5Matcher();
Pattern pattern = compiler.compile(
// XXX: doesn't properly handle special single-quoted characters
// single-quoted character
"('.')" + "|" +
// double-quoted string
"(\"(?:[^\"\\\\]|\\\\.)*\")" + "|" +
// multi-line comment
"(/\\*[^*]*(?:\\*(?!/)[^*]*)*\\*/)" + "|" +
// single-line comment
"(//.*?$)" + "|" +
// pre-processor directive
"(^\\s*#.*?$)",
Perl5Compiler.MULTILINE_MASK);
while (matcher.contains(in, pattern)) {
MatchResult result = matcher.getMatch();
// XXX: should preserve newlines in the result so that line numbers of
// the stripped string correspond to those in the original source.
in = in.substring(0, result.beginOffset(0)) + " " + in.substring(result.endOffset(0));
}
return in;
}
/**
* Removes the contents of all top-level curly brace pairs {}.
* @param in the String to collapse
* @return the collapsed String
*/
private String collapseBraces(String in) {
StringBuffer buffer = new StringBuffer();
int nesting = 0;
int start = 0;
// XXX: need to keep newlines inside braces so we can determine the line
// number of a prototype
for (int i = 0; i < in.length(); i++) {
if (in.charAt(i) == '{') {
if (nesting == 0) {
buffer.append(in.substring(start, i + 1)); // include the '{'
}
nesting++;
}
if (in.charAt(i) == '}') {
nesting--;
if (nesting == 0) {
start = i; // include the '}'
}
}
}
buffer.append(in.substring(start));
return buffer.toString();
}
public List prototypes(String in) throws MalformedPatternException {
in = collapseBraces(strip(in));
PatternMatcherInput input = new PatternMatcherInput(in);
PatternCompiler compiler = new Perl5Compiler();
PatternMatcher matcher = new Perl5Matcher();
// XXX: doesn't handle ... varargs
// XXX: doesn't handle function pointers
Pattern pattern = compiler.compile(
"[\\w\\[\\]\\*]+\\s+[\\[\\]\\*\\w\\s]+\\([,\\[\\]\\*\\w\\s]*\\)(?=\\s*\\{)");
List matches = new ArrayList();
while (matcher.contains(input, pattern)) {
matches.add(matcher.getMatch().group(0) + ";");
}
return matches;
}
/**
* Setup a new preprocessor.
* preprocesses a pde file and write out a java file
* @param pretty true if should also space out/indent lines
* @return the classname of the exported Java
*/
public PdePreprocessor() { }
public int writePrefix(String program, String buildPath,
String name, String codeFolderPackages[]) throws FileNotFoundException {
this.buildPath = buildPath;
this.name = name;
int tabSize = Preferences.getInteger("editor.tabs.size");
char[] indentChars = new char[tabSize];
Arrays.fill(indentChars, ' ');
indent = new String(indentChars);
// need to reset whether or not this has a main()
foundMain = false;
//public String write(String program, String buildPath, String name,
// String extraImports[]) throws java.lang.Exception {
public String write(String program, String buildPath,
String name, String codeFolderPackages[],
Target target)
throws java.lang.Exception {
// if the program ends with no CR or LF an OutOfMemoryError will happen.
// not gonna track down the bug now, so here's a hack for it:
// http://dev.processing.org/bugs/show_bug.cgi?id=5
program += "\n";
// bug filed at http://dev.processing.org/bugs/show_bug.cgi?id=5
//if ((program.length() > 0) &&
//program.charAt(program.length()-1) != '\n') {
program += "\n";
//}
// if the program ends with an unterminated multi-line comment,
// if the program ends with an unterminated multiline comment,
// an OutOfMemoryError or NullPointerException will happen.
// again, not gonna bother tracking this down, but here's a hack.
// http://dev.processing.org/bugs/show_bug.cgi?id=16
@ -234,187 +268,66 @@ public class PdePreprocessor {
program = new String(p2, 0, index);
}
}
// These may change in-between (if the prefs panel adds this option)
// so grab them here on construction.
String prefsLine = Preferences.get("preproc.imports");
defaultImports = PApplet.splitTokens(prefsLine, ", ");
//String importRegexp = "(?:^|\\s|;)(import\\s+)(\\S+)(\\s*;)";
String importRegexp = "(?:^|;)\\s*(import\\s+)(\\S+)(\\s*;)";
// if this guy has his own imports, need to remove them
// just in case it's not an advanced mode sketch
PatternMatcher matcher = new Perl5Matcher();
PatternCompiler compiler = new Perl5Compiler();
//String mess = "^\\s*(import\\s+\\S+\\s*;)";
//String mess = "^\\s*(import\\s+)(\\S+)(\\s*;)";
String mess = "^\\s*#include\\s+[<\"](\\S+)[\">]";
programImports = new ArrayList<String>();
do {
String[] pieces = PApplet.match(program, importRegexp);
// Stop the loop if we've removed all the importy lines
if (pieces == null) break;
String piece = pieces[1] + pieces[2] + pieces[3];
int len = piece.length(); // how much to trim out
programImports.add(pieces[2]); // the package name
int idx = program.indexOf(piece);
// just remove altogether?
program = program.substring(0, idx) + program.substring(idx + len);
} while (true);
codeFolderImports = new ArrayList<String>();
if (codeFolderPackages != null) {
for (String item : codeFolderPackages) {
codeFolderImports.add(item + ".*");
}
Pattern pattern = null;
try {
pattern = compiler.compile(mess);
} catch (MalformedPatternException e) {
e.printStackTrace();
return null;
}
PatternMatcherInput input = new PatternMatcherInput(program);
while (matcher.contains(input, pattern)) {
programImports.add(matcher.getMatch().group(1));
}
// do this after the program gets re-combobulated
this.programReader = new StringReader(program);
File streamFile = new File(buildPath, name + ".java");
stream = new PrintStream(new FileOutputStream(streamFile));
int importsLength = writeImports(stream);
// return the length of the imports plus the extra lines for declarations
return importsLength + 2;
}
/**
* preprocesses a pde file and write out a java file
* @return the classname of the exported Java
*/
//public String write(String program, String buildPath, String name,
// String extraImports[]) throws java.lang.Exception {
public String write() throws java.lang.Exception {
// create a lexer with the stream reader, and tell it to handle
// hidden tokens (eg whitespace, comments) since we want to pass these
// through so that the line numbers when the compiler reports errors
// match those that will be highlighted in the PDE IDE
//
PdeLexer lexer = new PdeLexer(programReader);
lexer.setTokenObjectClass("antlr.CommonHiddenStreamToken");
// create the filter for hidden tokens and specify which tokens to
// hide and which to copy to the hidden text
//
filter = new TokenStreamCopyingHiddenTokenFilter(lexer);
filter.hide(PdeRecognizer.SL_COMMENT);
filter.hide(PdeRecognizer.ML_COMMENT);
filter.hide(PdeRecognizer.WS);
filter.copy(PdeRecognizer.SEMI);
filter.copy(PdeRecognizer.LPAREN);
filter.copy(PdeRecognizer.RPAREN);
filter.copy(PdeRecognizer.LCURLY);
filter.copy(PdeRecognizer.RCURLY);
filter.copy(PdeRecognizer.COMMA);
filter.copy(PdeRecognizer.RBRACK);
filter.copy(PdeRecognizer.LBRACK);
filter.copy(PdeRecognizer.COLON);
// create a parser and set what sort of AST should be generated
//
PdeRecognizer parser = new PdeRecognizer(filter);
// use our extended AST class
//
parser.setASTNodeClass("antlr.ExtendedCommonASTWithHiddenTokens");
// start parsing at the compilationUnit non-terminal
//
parser.pdeProgram();
// set up the AST for traversal by PdeEmitter
//
ASTFactory factory = new ASTFactory();
AST parserAST = parser.getAST();
AST rootNode = factory.create(ROOT_ID, "AST ROOT");
rootNode.setFirstChild(parserAST);
// unclear if this actually works, but it's worth a shot
//
//((CommonAST)parserAST).setVerboseStringConversion(
// true, parser.getTokenNames());
// (made to use the static version because of jikes 1.22 warning)
CommonAST.setVerboseStringConversion(true, parser.getTokenNames());
// if this is an advanced program, the classname is already defined.
//
if (programType == JAVA) {
name = getFirstClassName(parserAST);
}
// if 'null' was passed in for the name, but this isn't
// a 'java' mode class, then there's a problem, so punt.
//
this.buildPath = buildPath;
List prototypes = prototypes(program);
// store # of prototypes so that line number reporting can be adjusted
prototypeCount = prototypes.size();
if (name == null) return null;
// output the code
//
PdeEmitter emitter = new PdeEmitter();
//writeHeader(stream, extraImports, name);
writeDeclaration(stream, name);
File streamFile = new File(buildPath, name + ".cpp");
PrintStream stream = new PrintStream(new FileOutputStream(streamFile));
emitter.setOut(stream);
emitter.print(rootNode);
writeFooter(stream, name);
writeHeader(stream);
//added to write the pde code to the cpp file
writeProgram(stream, program, prototypes);
writeFooter(stream, target);
stream.close();
// if desired, serialize the parse tree to an XML file. can
// be viewed usefully with Mozilla or IE
if (Preferences.getBoolean("preproc.output_parse_tree")) {
writeParseTree("parseTree.xml", parserAST);
}
return name;
}
protected void writeParseTree(String filename, AST ast) {
try {
PrintStream stream = new PrintStream(new FileOutputStream(filename));
stream.println("<?xml version=\"1.0\"?>");
stream.println("<document>");
OutputStreamWriter writer = new OutputStreamWriter(stream);
if (ast != null) {
((CommonAST) ast).xmlSerialize(writer);
// Write the pde program to the cpp file
void writeProgram(PrintStream out, String program, List prototypes) {
int prototypeInsertionPoint = firstStatement(program);
out.print(program.substring(0, prototypeInsertionPoint));
out.print("#include \"WProgram.h\"\n");
// print user defined prototypes
for (int i = 0; i < prototypes.size(); i++) {
out.print(prototypes.get(i) + "\n");
}
writer.flush();
stream.println("</document>");
writer.close();
} catch (IOException e) {
}
}
int writeImports(PrintStream out) {
out.println("import processing.core.*; ");
out.println("import processing.xml.*; ");
out.println();
int count = 3;
if (programImports.size() != 0) {
for (String item : programImports) {
out.println("import " + item + "; ");
}
out.println();
count += programImports.size() + 1;
}
if (codeFolderImports.size() != 0) {
for (String item : codeFolderImports) {
out.println("import " + item + "; ");
}
out.println();
count += codeFolderImports.size() + 1;
}
for (String item : defaultImports) {
out.println("import " + item + ".*; ");
}
out.println();
count += defaultImports.length + 1;
return count;
out.print(program.substring(prototypeInsertionPoint));
}
@ -422,70 +335,30 @@ public class PdePreprocessor {
* Write any required header material (eg imports, class decl stuff)
*
* @param out PrintStream to write it to.
* @param exporting Is this being exported from PDE?
* @param name Name of the class being created.
*/
void writeDeclaration(PrintStream out, String className) {
String indent = " ";
if (programType == JAVA) {
// Print two blank lines so that the offset doesn't change
out.println();
out.println();
} else if (programType == ACTIVE) {
// Print an extra blank line so the offset is identical to the others
out.println("public class " + className + " extends PApplet {");
out.println();
} else if (programType == STATIC) {
out.println("public class " + className + " extends PApplet {");
out.print(indent + "public void setup() {");
}
}
void writeHeader(PrintStream out) throws IOException {}
/**
* Write any necessary closing text.
*
* @param out PrintStream to write it to.
* @param out PrintStream to write it to.
*/
void writeFooter(PrintStream out, String className) {
void writeFooter(PrintStream out, Target target) throws java.lang.Exception {
// Open the file main.cxx and copy its entire contents to the bottom of the
// generated sketch .cpp file...
if (programType == STATIC) {
// close off draw() definition
out.println(indent + "noLoop();");
out.println("} ");
String mainFileName = target.getPath() + File.separator + "main.cxx";
FileReader reader = null;
reader = new FileReader(mainFileName);
LineNumberReader mainfile = new LineNumberReader(reader);
String line;
while ((line = mainfile.readLine()) != null) {
out.print(line + "\n");
}
if ((programType == STATIC) || (programType == ACTIVE)) {
if (!PdePreprocessor.foundMain) {
out.println(indent + "static public void main(String args[]) {");
out.print(indent + indent + "PApplet.main(new String[] { ");
if (Preferences.getBoolean("export.application.fullscreen")) {
out.print("\"" + PApplet.ARGS_PRESENT + "\", ");
String farbe = Preferences.get("run.present.bgcolor");
out.print("\"" + PApplet.ARGS_BGCOLOR + "=" + farbe + "\", ");
if (Preferences.getBoolean("export.application.stop")) {
farbe = Preferences.get("run.present.stop.color");
out.print("\"" + PApplet.ARGS_STOP_COLOR + "=" + farbe + "\", ");
} else {
out.print("\"" + PApplet.ARGS_HIDE_STOP + "\", ");
}
} else {
String farbe = Preferences.get("run.window.bgcolor");
out.print("\"" + PApplet.ARGS_BGCOLOR + "=" + farbe + "\", ");
}
out.println("\"" + className + "\" });");
out.println(indent + "}");
}
// close off the class definition
out.println("}");
}
mainfile.close();
}
@ -494,11 +367,13 @@ public class PdePreprocessor {
}
static String advClassName = "";
/**
* Find the first CLASS_DEF node in the tree, and return the name of the
* class in question.
*
* TODO [dmose] right now, we're using a little hack to the grammar to get
* XXXdmose right now, we're using a little hack to the grammar to get
* this info. In fact, we should be descending the AST passed in.
*/
String getFirstClassName(AST ast) {
@ -508,4 +383,5 @@ public class PdePreprocessor {
return t;
}
}

View File

@ -1,11 +0,0 @@
#!/bin/sh
rm -f *Lexer.java
rm -f *Recognizer.java
rm -f *TokenTypes.java
rm -f *TokenTypes.txt
rm -f *TreeParser.java
rm -f *TreeParserTokenTypes.java
rm -f *TreeParserTokenTypes.txt
rm -f expanded*.g

View File

@ -1,3 +0,0 @@
java -cp ../../build/macosx/work/lib/antlr.jar antlr.Tool java.g
# now build the pde stuff that extends the java classes
java -cp ../../build/macosx/work/lib/antlr.jar antlr.Tool -glib java.g pde.g

View File

@ -1,304 +0,0 @@
/* -*- mode: antlr; c-basic-offset: 4; indent-tabs-mode: nil -*- */
header {
package processing.app.preproc;
import processing.app.*;
}
class PdeRecognizer extends JavaRecognizer;
options {
importVocab = Java;
exportVocab = PdePartial;
codeGenMakeSwitchThreshold=10; // this is set high for debugging
codeGenBitsetTestThreshold=10; // this is set high for debugging
// developers may to want to set this to true for better
// debugging messages, however, doing so disables highlighting errors
// in the editor.
defaultErrorHandler = false; //true;
}
tokens {
CONSTRUCTOR_CAST; EMPTY_FIELD;
}
pdeProgram
// only java mode programs will have their own public classes or
// imports (and they must have at least one)
: ( "public" "class" | "import" ) => javaProgram
{ PdePreprocessor.programType = PdePreprocessor.JAVA; }
// the syntactic predicate here looks for any minimal (thus
// the non-greedy qualifier) number of fields, followed by
// the tokens that represent the definition of loop() or
// some other member function. java mode programs may have such
// definitions, but they won't reach this point, having already been
// selected in the previous alternative. static mode programs
// don't have member functions.
//
| ( ( options {greedy=false;}: possiblyEmptyField)* "void" IDENT LPAREN )
=> activeProgram
{ PdePreprocessor.programType = PdePreprocessor.ACTIVE; }
| staticProgram
{ PdePreprocessor.programType = PdePreprocessor.STATIC; }
;
// advanced mode is really just a normal java file
javaProgram
: compilationUnit
;
activeProgram
: (possiblyEmptyField)+
;
staticProgram
: (statement)*
;
// copy of the java.g rule with WEBCOLOR_LITERAL added
constant
: NUM_INT
| CHAR_LITERAL
| STRING_LITERAL
| NUM_FLOAT
| NUM_LONG
| NUM_DOUBLE
| webcolor_literal
;
// of the form #cc008f in PDE
webcolor_literal
: w:WEBCOLOR_LITERAL
{ Preferences.getBoolean("preproc.web_colors") &&
w.getText().length() == 6 }? // must be exactly 6 hex digits
;
// copy of the java.g builtInType rule
builtInConsCastType
: "void"
| "boolean"
| "byte"
| "char"
| "short"
| "int"
| "float"
| "long"
| "double"
;
// our types include the java types and "color". this is separated into two
// rules so that constructor casts can just use the original typelist, since
// we don't want to support the color type as a constructor cast.
//
builtInType
: builtInConsCastType
| "color" // aliased to an int in PDE
{ Preferences.getBoolean("preproc.color_datatype") }?
;
// constructor style casts.
constructorCast!
: t:consCastTypeSpec[true]
LPAREN!
e:expression
RPAREN!
// if this is a string literal, make sure the type we're trying to cast
// to is one of the supported ones
//
{ #e.getType() != STRING_LITERAL ||
( #t.getType() == LITERAL_byte ||
#t.getType() == LITERAL_double ||
#t.getType() == LITERAL_float ||
#t.getType() == LITERAL_int ||
#t.getType() == LITERAL_long ||
#t.getType() == LITERAL_short ) }?
// create the node
//
{#constructorCast = #(#[CONSTRUCTOR_CAST,"CONSTRUCTOR_CAST"], t, e);}
;
// A list of types that be used as the destination type in a constructor-style
// cast. Ideally, this would include all class types, not just "String".
// Unfortunately, it's not possible to tell whether Foo(5) is supposed to be
// a method call or a constructor cast without have a table of all valid
// types or methods, which requires semantic analysis (eg processing of import
// statements). So we accept the set of built-in types plus "String".
//
consCastTypeSpec[boolean addImagNode]
// : stringTypeSpec[addImagNode]
// | builtInConsCastTypeSpec[addImagNode]
: builtInConsCastTypeSpec[addImagNode]
// trying to remove String() cast [fry]
;
//stringTypeSpec[boolean addImagNode]
// : id:IDENT { #id.getText().equals("String") }?
// {
// if ( addImagNode ) {
// #stringTypeSpec = #(#[TYPE,"TYPE"],
// #stringTypeSpec);
// }
// }
// ;
builtInConsCastTypeSpec[boolean addImagNode]
: builtInConsCastType
{
if ( addImagNode ) {
#builtInConsCastTypeSpec = #(#[TYPE,"TYPE"],
#builtInConsCastTypeSpec);
}
}
;
// Since "color" tokens are lexed as LITERAL_color now, we need to have a rule
// that can generate a method call from an expression that starts with this
// token
//
colorMethodCall
: c:"color" {#c.setType(IDENT);} // this would default to LITERAL_color
lp:LPAREN^ {#lp.setType(METHOD_CALL);}
argList
RPAREN!
;
// copy of the java.g rule with added constructorCast and colorMethodCall
// alternatives
primaryExpression
: (consCastTypeSpec[false] LPAREN) => constructorCast
{ Preferences.getBoolean("preproc.enhanced_casting") }?
| identPrimary ( options {greedy=true;} : DOT^ "class" )?
| constant
| "true"
| "false"
| "null"
| newExpression
| "this"
| "super"
| LPAREN! assignmentExpression RPAREN!
| colorMethodCall
// look for int.class and int[].class
| builtInType
( lbt:LBRACK^ {#lbt.setType(ARRAY_DECLARATOR);} RBRACK! )*
DOT^ "class"
;
// the below variable rule hacks are needed so that it's possible for the
// emitter to correctly output variable declarations of the form "float a, b"
// from the AST. This means that our AST has a somewhat different form in
// these rules than the java one does, and this new form may have its own
// semantic issues. But it seems to fix the comma declaration issues.
//
variableDefinitions![AST mods, AST t]
: vd:variableDeclarator[getASTFactory().dupTree(mods),
getASTFactory().dupTree(t)]
{#variableDefinitions = #(#[VARIABLE_DEF,"VARIABLE_DEF"], mods,
t, vd);}
;
variableDeclarator[AST mods, AST t]
: ( id:IDENT (lb:LBRACK^ {#lb.setType(ARRAY_DECLARATOR);} RBRACK!)*
v:varInitializer (COMMA!)? )+
;
// java.g builds syntax trees with an inconsistent structure. override one of
// the rules there to fix this.
//
explicitConstructorInvocation!
: t:"this" LPAREN a1:argList RPAREN SEMI
{#explicitConstructorInvocation = #(#[CTOR_CALL, "CTOR_CALL"],
#t, #a1);}
| s:"super" LPAREN a2:argList RPAREN SEMI
{#explicitConstructorInvocation = #(#[SUPER_CTOR_CALL,
"SUPER_CTOR_CALL"],
#s, #a2);}
;
// quick-n-dirty hack to the get the advanced class name. we should
// really be getting it from the AST and not forking this rule from
// the java.g copy at all. Since this is a recursive descent parser, we get
// the last class name in the file so that we don't end up with the classname
// of an inner class. If there is more than one "outer" class in a file,
// this heuristic will fail.
//
classDefinition![AST modifiers]
: "class" i:IDENT
// it _might_ have a superclass...
sc:superClassClause
// it might implement some interfaces...
ic:implementsClause
// now parse the body of the class
cb:classBlock
{#classDefinition = #(#[CLASS_DEF,"CLASS_DEF"],
modifiers,i,sc,ic,cb);
PdePreprocessor.advClassName = i.getText();}
;
possiblyEmptyField
: field
| s:SEMI {#s.setType(EMPTY_FIELD);}
;
class PdeLexer extends JavaLexer;
options {
importVocab=PdePartial;
exportVocab=Pde;
}
// We need to preserve whitespace and commentary instead of ignoring
// like the supergrammar does. Otherwise Jikes won't be able to give
// us error messages that point to the equivalent PDE code.
// WS, SL_COMMENT, ML_COMMENT are copies of the original productions,
// but with the SKIP assigment removed.
WS : ( ' '
| '\t'
| '\f'
// handle newlines
| ( options {generateAmbigWarnings=false;}
: "\r\n" // Evil DOS
| '\r' // Macintosh
| '\n' // Unix (the right way)
)
{ newline(); }
)+
;
// Single-line comments
SL_COMMENT
: "//"
(~('\n'|'\r'))* ('\n'|'\r'('\n')?)
{newline();}
;
// multiple-line comments
ML_COMMENT
: "/*"
( /* '\r' '\n' can be matched in one alternative or by matching
'\r' in one iteration and '\n' in another. I am trying to
handle any flavor of newline that comes in, but the language
that allows both "\r\n" and "\r" and "\n" to all be valid
newline is ambiguous. Consequently, the resulting grammar
must be ambiguous. I'm shutting this warning off.
*/
options {
generateAmbigWarnings=false;
}
:
{ LA(2)!='/' }? '*'
| '\r' '\n' {newline();}
| '\r' {newline();}
| '\n' {newline();}
| ~('*'|'\n'|'\r')
)*
"*/"
;
WEBCOLOR_LITERAL
: '#'! (HEX_DIGIT)+
;

View File

@ -1,150 +0,0 @@
// this is a whitespace and other invisible token torture test for the ANTLR-based
// preprocessor. edit pde.properties and set "editor.save_build_files" to true.
// then, build this in processing. next, use
//
// diff -u --strip-trailing-cr \
// work/sketchbook/default/whitespace_test/whitespace_test.pde \
// work/lib/build/MyDemo.java
//
// to compare the files before and after preprocessing. There should not be
// any differences.
import // comment test
java.io.*;
// comment 1
public class // post-class comment
// comment2
MyDemo extends BApplet implements // foo
java.lang. // bar
Cloneable {
//argh
public // foo
String // bar
fff = /*rheet */ "stuff";
static /*a*/ {
/*foo*/
/*bar*/
six = 6;
} /* b*/
static /*a*/ final /*b*/ int six;
void setup()
{
size(200, 200);
background(255);
this . fff = /* ook */ (String)/*foo*/"yo";
rectMode(CENTER_DIAMETER); // comment 1a
noStroke();
fill(255, 204, 0);
int q = /*a*/ - /*b*/ 1;
boolean c = /*a*/ ! /*b*/ true;
}
int foo() /*a*/ throws /*b*/ java.lang.Exception /*c*/
{
int b = 7;
switch /*a*/ ( /*b*/ b /*c*/ ) {
case /*d*/ 1 /*e*/: /*f*/
int c=9;
/*g*/
break; /*h*/
default /*i*/ :
int d=9;
break;
}
try { /* qq */
loop(); /* rr */
} catch /*ss*/ (java.lang.Exception ex) /*tt*/ {
b = 8; /*tut*/
throw /*utu*/ ex;
} /*uu*/ finally /*vv*/ {
b = 9;
} /*ww*/
b /*aaa*/ = /*bbb*/ true /*ccc*/ ? /*ddd*/ 0 /*eee*/
: /* fff*/ 1 /*ggg*/;
return /*a*/ 5 /*b*/;
}
// comment 2
void loop()
{
int arr1 /* VVV */ [ /* XXX */] /*YYY*/ ;
int[] arr2 = { /*a*/ 2, 3 /*b*/ } /*c*/ ;
for /*a*/ (/*b*/ int j=0 /*c*/; /*d*/ j<2/*e*/ ; /*f*/ j++ /*g*/)
/*h*/
arr2[1] = 6;
/*foo*/
;
/*bar*/
rect(width-mouseX, height-mouseY, 50, 50);
rect(mouseX, mouseY, 50, 50);
if (/*a*/ arr2[1] == 6/*b*/) {
/*c*/
int d=7;
} /*d*/else /*e*/{
int e=8;
/*f*/
}
int f;
if (/*aa*/ arr2[1] ==6 /*bb*/ )
/*cc*/
f=8; /*dd*/
else /*ee*/
f=10; /*ff*/
while ( /*aaa*/ f < 15) /*bbb*/ {
f ++;
} /*ggg*/
do /* aaaa */ {
f++;
} /*bbbb*/ while /*cccc*/ ( /*a*/ - /*b*/ 20 > f) /*dddd*/;
f = 2 * 3 + 4;
f = ( 2 * 3 ) + 4 + /*aa*/ -/*bb*/1;
f = 2 * ( 3 + 4 ) ;
fff = /*a*/ new /*b*/ String(/*c*/"foo"/*d*/) /*e*/;
int arr3[] = /*a*/ new /*b*/ int/*c*/[/*d*/] /*e*/ {1/*f*/,2};
int arr4[][] = new /*a*/int/*b*/[1][2]/*c*/;
}
class Shoe
{
Shoe(String brand)
{
println(brand);
}
}
class NikeAir extends Shoe
{
NikeAir()
{
/*a*/ super /*b*/ ( /*c*/ "Nike" /*d*/ ) /*e*/ ;
/*aa*/ ( /*bb*/ new /*cc*/ MyDemo /*dd*/ (/*ee*/)/*ff*/)/*gg*/./*hh*/super/*ii*/(/*jj*/5/*kk*/);
}
}
}

View File

@ -68,7 +68,7 @@
<!-- In 0149, removed /System/Library/Java from the CLASSPATH because
it can cause problems if users have installed weird files there.
http://dev.processing.org/bugs/show_bug.cgi?id=1045 -->
<string>$JAVAROOT/pde.jar:$JAVAROOT/core.jar:$JAVAROOT/antlr.jar:$JAVAROOT/ecj.jar:$JAVAROOT/registry.jar:$JAVAROOT/quaqua.jar</string>
<string>$JAVAROOT/pde.jar:$JAVAROOT/core.jar:$JAVAROOT/antlr.jar:$JAVAROOT/ecj.jar:$JAVAROOT/registry.jar:$JAVAROOT/quaqua.jar:$JAVAROOT/oro.jar</string>
<key>Properties</key>
<dict>

BIN
build/macosx/dist/tools-universal.zip vendored Normal file

Binary file not shown.

View File

@ -27,16 +27,22 @@ else
cp -rX ../shared/lib "$RESOURCES/"
cp -rX ../shared/libraries "$RESOURCES/"
cp -rX ../shared/tools "$RESOURCES/"
cp -rX ../../hardware "$RESOURCES/"
cp -X ../../app/lib/antlr.jar "$RESOURCES/"
cp -X ../../app/lib/ecj.jar "$RESOURCES/"
cp -X ../../app/lib/jna.jar "$RESOURCES/"
cp -X ../../app/lib/oro.jar "$RESOURCES/"
echo Extracting examples...
unzip -q -d "$RESOURCES/" ../shared/examples.zip
echo Copying examples...
cp -r ../shared/examples "$RESOURCES/"
echo Extracting reference...
unzip -q -d "$RESOURCES/" ../shared/reference.zip
echo Extracting avr tools...
unzip -q -d "$RESOURCES/hardware" dist/tools-universal.zip
LIBRARIES=$RESOURCES/libraries/
cp -rX ../../net "$LIBRARIES"
@ -83,28 +89,6 @@ cd ../app
### -- BUILD PARSER ---------------------------------------------
#BUILD_PREPROC=true
if $BUILD_PREPROC
then
# build classes/grammar for preprocessor
echo Building antlr grammar code...
# first build the default java goop
java -cp "$RESOURCES/antlr.jar" antlr.Tool \
-o src/antlr/java \
src/antlr/java/java.g
# hack to get around path mess
cp -X src/antlr/java/JavaTokenTypes.txt src/processing/app/preproc/
# now build the pde stuff that extends the java classes
java -cp "$RESOURCES/antlr.jar" antlr.Tool \
-o src/processing/app/preproc \
-glib src/antlr/java/java.g src/processing/app/preproc/pde.g
fi
### -- BUILD PDE ------------------------------------------------
echo Building the PDE...
@ -118,16 +102,14 @@ mkdir ../build/macosx/work/classes
javac \
-Xlint:deprecation \
-source 1.5 -target 1.5 \
-classpath "$RESOURCES/core.jar:$RESOURCES/antlr.jar:$RESOURCES/ecj.jar:$RESOURCES/jna.jar" \
-classpath "$RESOURCES/core.jar:$RESOURCES/antlr.jar:$RESOURCES/ecj.jar:$RESOURCES/jna.jar:$RESOURCES/oro.jar" \
-d ../build/macosx/work/classes \
src/processing/app/*.java \
src/processing/app/debug/*.java \
src/processing/app/macosx/*.java \
src/processing/app/preproc/*.java \
src/processing/app/syntax/*.java \
src/processing/app/tools/*.java \
src/antlr/*.java \
src/antlr/java/*.java
src/processing/app/tools/*.java
cd ../build/macosx/work/classes
rm -f "$RESOURCES/pde.jar"
@ -139,110 +121,5 @@ cd ../..
#cp work/lib/*.jar work/Processing.app/Contents/Resources/Java/
### -- BUILD LIBRARIES ------------------------------------------------
PLATFORM=macosx
CLASSPATH=$RESOURCES/core.jar
JAVAC="javac -source 1.5 -target 1.5"
LIBRARIES=$RESOURCES/libraries
# move to processing/build
cd ..
# SERIAL LIBRARY
echo Building serial library...
cd ../serial
mkdir -p bin
$JAVAC \
-classpath "library/RXTXcomm.jar:$CLASSPATH" \
-d bin src/processing/serial/*.java
rm -f library/serial.jar
#find bin -name "*~" -exec rm -f {} ';'
cd bin && zip -rq ../library/serial.jar processing/serial/*.class && cd ..
mkdir -p "$LIBRARIES/serial/library/"
cp library/serial.jar "$LIBRARIES/serial/library/"
# NET LIBRARY
echo Building net library...
cd ../net
mkdir -p bin
$JAVAC \
-classpath "$CLASSPATH" \
-d bin src/processing/net/*.java
rm -f library/net.jar
#find bin -name "*~" -exec rm -f {} ';'
cd bin && zip -rq ../library/net.jar processing/net/*.class && cd ..
mkdir -p "$LIBRARIES/net/library/"
cp library/net.jar "$LIBRARIES/net/library/"
# VIDEO LIBRARY
echo Building video library...
QTJAVA=/System/Library/Java/Extensions/QTJava.zip
if test -f "${QTJAVA}"
then
echo "Found QuickTime for Java at $QTJAVA"
else
echo "QuickTime for Java must be installed before building."
exit 1;
fi
cd ../video
mkdir -p bin
$JAVAC \
-classpath "$QTJAVA:$CLASSPATH" \
-d bin src/processing/video/*.java
rm -f library/video.jar
#find bin -name "*~" -exec rm -f {} ';'
cd bin && zip -rq ../library/video.jar processing/video/*.class && cd ..
mkdir -p "$LIBRARIES/video/library/"
cp library/video.jar "$LIBRARIES/video/library/"
# OPENGL LIBRARY
echo Building OpenGL library...
cd ../opengl
mkdir -p bin
$JAVAC \
-classpath "library/jogl.jar:$CLASSPATH" \
-d bin src/processing/opengl/*.java
rm -f library/opengl.jar
#find bin -name "*~" -exec rm -f {} ';'
cd bin && zip -rq ../library/opengl.jar processing/opengl/*.class && cd ..
mkdir -p "$LIBRARIES/opengl/library/"
cp library/opengl.jar "$LIBRARIES/opengl/library/"
# PDF LIBRARY
echo Building PDF library...
cd ../pdf
mkdir -p bin
$JAVAC \
-classpath "library/itext.jar:$CLASSPATH" \
-d bin src/processing/pdf/*.java
rm -f library/pdf.jar
#find bin -name "*~" -exec rm -f {} ';'
cd bin && zip -rq ../library/pdf.jar processing/pdf/*.class && cd ..
mkdir -p "$LIBRARIES/pdf/library/"
cp library/pdf.jar "$LIBRARIES/pdf/library/"
# DXF LIBRARY
echo Building DXF library...
cd ../dxf
mkdir -p bin
$JAVAC \
-classpath "$CLASSPATH" \
-d bin src/processing/dxf/*.java
rm -f library/dxf.jar
#find bin -name "*~" -exec rm -f {} ';'
cd bin && zip -rq ../library/dxf.jar processing/dxf/*.class && cd ..
mkdir -p "$LIBRARIES/dxf/library/"
cp library/dxf.jar "$LIBRARIES/dxf/library/"
echo
echo Done.
echo Done.

Binary file not shown.

View File

@ -0,0 +1,27 @@
/*
* AnalogInput
* by DojoDave <http://www.0j0.org>
*
* Turns on and off a light emitting diode(LED) connected to digital
* pin 13. The amount of time the LED will be on and off depends on
* the value obtained by analogRead(). In the easiest case we connect
* a potentiometer to analog pin 2.
*
* http://www.arduino.cc/en/Tutorial/AnalogInput
*/
int potPin = 2; // select the input pin for the potentiometer
int ledPin = 13; // select the pin for the LED
int val = 0; // variable to store the value coming from the sensor
void setup() {
pinMode(ledPin, OUTPUT); // declare the ledPin as an OUTPUT
}
void loop() {
val = analogRead(potPin); // read the value from the sensor
digitalWrite(ledPin, HIGH); // turn the ledPin on
delay(val); // stop the program for some time
digitalWrite(ledPin, LOW); // turn the ledPin off
delay(val); // stop the program for some time
}

View File

@ -0,0 +1,49 @@
/*
* Calibration
*
* Demonstrates one techinque for calibrating sensor input. The
* sensor readings during the first five seconds of the sketch
* execution define the minimum and maximum of expected values.
*/
int sensorPin = 2;
int ledPin = 9;
int val = 0;
int sensorMin = 1023, sensorMax = 0;
void setup() {
// signal the start of the calibration period
pinMode(13, OUTPUT);
digitalWrite(13, HIGH);
// calibrate during the first five seconds
while (millis() < 5000) {
val = analogRead(sensorPin);
// record the maximum sensor value
if (val > sensorMax) {
sensorMax = val;
}
// record the minimum sensor value
if (val < sensorMin) {
sensorMin = val;
}
}
// signal the end of the calibration period
digitalWrite(13, LOW);
}
void loop() {
val = analogRead(sensorPin);
// apply the calibration to the sensor reading
val = map(val, sensorMin, sensorMax, 0, 255);
// in case the sensor value is outside the range seen during calibration
val = constrain(val, 0, 255);
analogWrite(ledPin, val);
}

View File

@ -0,0 +1,24 @@
// Fading LED
// by BARRAGAN <http://people.interaction-ivrea.it/h.barragan>
int value = 0; // variable to keep the actual value
int ledpin = 9; // light connected to digital pin 9
void setup()
{
// nothing for setup
}
void loop()
{
for(value = 0 ; value <= 255; value+=5) // fade in (from min to max)
{
analogWrite(ledpin, value); // sets the value (range from 0 to 255)
delay(30); // waits for 30 milli seconds to see the dimming effect
}
for(value = 255; value >=0; value-=5) // fade out (from max to min)
{
analogWrite(ledpin, value);
delay(30);
}
}

View File

@ -0,0 +1,43 @@
/*
* Smoothing
* David A. Mellis <dam@mellis.org>
*
* Reads repeatedly from an analog input, calculating a running average
* and printing it to the computer.
*
* http://www.arduino.cc/en/Tutorial/Smoothing
*/
// Define the number of samples to keep track of. The higher the number,
// the more the readings will be smoothed, but the slower the output will
// respond to the input. Using a #define rather than a normal variable lets
// use this value to determine the size of the readings array.
#define NUMREADINGS 10
int readings[NUMREADINGS]; // the readings from the analog input
int index = 0; // the index of the current reading
int total = 0; // the running total
int average = 0; // the average
int inputPin = 0;
void setup()
{
Serial.begin(9600); // initialize serial communication with computer
for (int i = 0; i < NUMREADINGS; i++)
readings[i] = 0; // initialize all the readings to 0
}
void loop()
{
total -= readings[index]; // subtract the last reading
readings[index] = analogRead(inputPin); // read from the sensor
total += readings[index]; // add the reading to the total
index = (index + 1); // advance to the next index
if (index >= NUMREADINGS) // if we're at the end of the array...
index = 0; // ...wrap around to the beginning
average = total / NUMREADINGS; // calculate the average
Serial.println(average); // send it to the computer (as ASCII digits)
}

View File

@ -0,0 +1,73 @@
/*
ASCII table
Prints out byte values in all possible formats:
* as raw binary values
* as ASCII-encoded decimal, hex, octal, and binary values
For more on ASCII, see http://www.asciitable.com and http://en.wikipedia.org/wiki/ASCII
The circuit: No external hardware needed.
created 2006
by Nicholas Zambetti
modified 18 Jan 2009
by Tom Igoe
<http://www.zambetti.com>
*/
void setup()
{
Serial.begin(9600);
// prints title with ending line break
Serial.println("ASCII Table ~ Character Map");
}
// first visible ASCIIcharacter '!' is number 33:
int thisByte = 33;
// you can also write ASCII characters in single quotes.
// for example. '!' is the same as 33, so you could also use this:
//int thisByte = '!';
void loop()
{
// prints value unaltered, i.e. the raw binary version of the
// byte. The serial monitor interprets all bytes as
// ASCII, so 33, the first number, will show up as '!'
Serial.print(thisByte, BYTE);
Serial.print(", dec: ");
// prints value as string as an ASCII-encoded decimal (base 10).
// Decimal is the default format for Serial.print() and Serial.println(),
// so no modifier is needed:
Serial.print(thisByte);
// But you can declare the modifier for decimal if you want to.
//this also works if you uncomment it:
// Serial.print(thisByte, DEC);
Serial.print(", hex: ");
// prints value as string in hexadecimal (base 16):
Serial.print(thisByte, HEX);
Serial.print(", oct: ");
// prints value as string in octal (base 8);
Serial.print(thisByte, OCT);
Serial.print(", bin: ");
// prints value as string in binary (base 2)
// also prints ending line break:
Serial.println(thisByte, BIN);
// if printed last visible character '~' or 126, stop:
if(thisByte == 126) { // you could also use if (thisByte == '~') {
// This loop loops forever and does nothing
while(true) {
continue;
}
}
// go on to the next character
thisByte++;
}

View File

@ -0,0 +1,360 @@
/*
Dimmer
Demonstrates the sending data from the computer to the Arduino board,
in this case to control the brightness of an LED. The data is sent
in individual bytes, each of which ranges from 0 to 255. Arduino
reads these bytes and uses them to set the brightness of the LED.
The circuit:
LED attached from digital pin 9 to ground.
Serial connection to Processing, Max/MSP, or another serial application
created 2006
by David A. Mellis
modified 14 Apr 2009
by Tom Igoe and Scott Fitzgerald
http://www.arduino.cc/en/Tutorial/Dimmer
*/
const int ledPin = 9; // the pin that the LED is attached to
void setup()
{
// initialize the serial communication:
Serial.begin(9600);
// initialize the ledPin as an output:
pinMode(ledPin, OUTPUT);
}
void loop() {
byte brightness;
// check if data has been sent from the computer:
if (Serial.available()) {
// read the most recent byte (which will be from 0 to 255):
brightness = Serial.read();
// set the brightness of the LED:
analogWrite(ledPin, brightness);
}
}
/* Processing code for this example
// Dimmer - sends bytes over a serial port
// by David A. Mellis
import processing.serial.*;
Serial port;
void setup() {
size(256, 150);
println("Available serial ports:");
println(Serial.list());
// Uses the first port in this list (number 0). Change this to
// select the port corresponding to your Arduino board. The last
// parameter (e.g. 9600) is the speed of the communication. It
// has to correspond to the value passed to Serial.begin() in your
// Arduino sketch.
port = new Serial(this, Serial.list()[0], 9600);
// If you know the name of the port used by the Arduino board, you
// can specify it directly like this.
//port = new Serial(this, "COM1", 9600);
}
void draw() {
// draw a gradient from black to white
for (int i = 0; i < 256; i++) {
stroke(i);
line(i, 0, i, 150);
}
// write the current X-position of the mouse to the serial port as
// a single byte
port.write(mouseX);
}
*/
/* Max/MSP v5 patch for this example
{
"boxes" : [ {
"box" : {
"maxclass" : "comment",
"text" : "Dimmer\n\nThis patch sends a binary number from 0 to 255 out the serial port to an Arduino connected to the port. It dims an LED attached to the Arduino.\n\ncreated 2006\nby David A. Mellis\nmodified 14 Apr 2009\nby Scott Fitzgerald and Tom Igoe",
"linecount" : 10,
"patching_rect" : [ 209.0, 55.0, 344.0, 144.0 ],
"numoutlets" : 0,
"fontsize" : 12.0,
"id" : "obj-32",
"fontname" : "Arial",
"numinlets" : 1
}
}
, {
"box" : {
"maxclass" : "comment",
"text" : "change the slider to alter the brightness of the LED",
"linecount" : 3,
"patching_rect" : [ 90.0, 235.0, 117.0, 48.0 ],
"numoutlets" : 0,
"fontsize" : 12.0,
"id" : "obj-7",
"fontname" : "Arial",
"numinlets" : 1
}
}
, {
"box" : {
"maxclass" : "number",
"patching_rect" : [ 215.0, 385.0, 50.0, 19.0 ],
"numoutlets" : 2,
"fontsize" : 10.0,
"outlettype" : [ "int", "bang" ],
"id" : "obj-6",
"fontname" : "Verdana",
"numinlets" : 1
}
}
, {
"box" : {
"maxclass" : "slider",
"patching_rect" : [ 215.0, 235.0, 20.0, 140.0 ],
"numoutlets" : 1,
"outlettype" : [ "" ],
"bgcolor" : [ 0.94902, 0.94902, 0.94902, 0.0 ],
"id" : "obj-1",
"size" : 256.0,
"numinlets" : 1
}
}
, {
"box" : {
"maxclass" : "newobj",
"text" : "select 0 1",
"patching_rect" : [ 342.0, 305.0, 62.0, 20.0 ],
"numoutlets" : 3,
"fontsize" : 12.0,
"outlettype" : [ "bang", "bang", "" ],
"id" : "obj-30",
"fontname" : "Arial",
"numinlets" : 1
}
}
, {
"box" : {
"maxclass" : "comment",
"text" : "click here to close the serial port",
"patching_rect" : [ 390.0, 396.0, 206.0, 20.0 ],
"numoutlets" : 0,
"fontsize" : 12.0,
"id" : "obj-26",
"fontname" : "Arial",
"numinlets" : 1
}
}
, {
"box" : {
"maxclass" : "comment",
"text" : "click here to open the serial port",
"patching_rect" : [ 415.0, 370.0, 206.0, 20.0 ],
"numoutlets" : 0,
"fontsize" : 12.0,
"id" : "obj-27",
"fontname" : "Arial",
"numinlets" : 1
}
}
, {
"box" : {
"maxclass" : "message",
"text" : "close",
"patching_rect" : [ 342.0, 396.0, 39.0, 18.0 ],
"numoutlets" : 1,
"fontsize" : 12.0,
"outlettype" : [ "" ],
"id" : "obj-21",
"fontname" : "Arial",
"numinlets" : 2
}
}
, {
"box" : {
"maxclass" : "message",
"text" : "port a",
"patching_rect" : [ 364.0, 370.0, 41.0, 18.0 ],
"numoutlets" : 1,
"fontsize" : 12.0,
"outlettype" : [ "" ],
"id" : "obj-19",
"fontname" : "Arial",
"numinlets" : 2
}
}
, {
"box" : {
"maxclass" : "comment",
"text" : "Click here to get a list of serial ports",
"patching_rect" : [ 435.0, 344.0, 207.0, 20.0 ],
"numoutlets" : 0,
"fontsize" : 12.0,
"id" : "obj-2",
"fontname" : "Arial",
"numinlets" : 1
}
}
, {
"box" : {
"maxclass" : "toggle",
"patching_rect" : [ 342.0, 268.0, 15.0, 15.0 ],
"numoutlets" : 1,
"outlettype" : [ "int" ],
"id" : "obj-11",
"numinlets" : 1
}
}
, {
"box" : {
"maxclass" : "message",
"text" : "print",
"patching_rect" : [ 384.0, 344.0, 36.0, 18.0 ],
"numoutlets" : 1,
"fontsize" : 12.0,
"outlettype" : [ "" ],
"id" : "obj-13",
"fontname" : "Arial",
"numinlets" : 2
}
}
, {
"box" : {
"maxclass" : "newobj",
"text" : "serial a 9600",
"patching_rect" : [ 259.0, 420.0, 84.0, 20.0 ],
"numoutlets" : 2,
"fontsize" : 12.0,
"outlettype" : [ "int", "" ],
"id" : "obj-14",
"fontname" : "Arial",
"numinlets" : 1
}
}
, {
"box" : {
"maxclass" : "comment",
"text" : "Click to start",
"patching_rect" : [ 369.0, 268.0, 117.0, 20.0 ],
"numoutlets" : 0,
"fontsize" : 12.0,
"id" : "obj-17",
"fontname" : "Arial",
"numinlets" : 1
}
}
, {
"box" : {
"maxclass" : "panel",
"patching_rect" : [ 215.0, 235.0, 21.0, 139.0 ],
"numoutlets" : 0,
"mode" : 1,
"grad1" : [ 1.0, 1.0, 1.0, 1.0 ],
"id" : "obj-8",
"grad2" : [ 0.509804, 0.509804, 0.509804, 1.0 ],
"numinlets" : 1,
"angle" : 270.0
}
}
],
"lines" : [ {
"patchline" : {
"source" : [ "obj-11", 0 ],
"destination" : [ "obj-30", 0 ],
"hidden" : 0,
"midpoints" : [ 351.0, 296.0, 351.5, 296.0 ]
}
}
, {
"patchline" : {
"source" : [ "obj-30", 1 ],
"destination" : [ "obj-19", 0 ],
"hidden" : 0,
"midpoints" : [ ]
}
}
, {
"patchline" : {
"source" : [ "obj-30", 0 ],
"destination" : [ "obj-21", 0 ],
"hidden" : 0,
"midpoints" : [ ]
}
}
, {
"patchline" : {
"source" : [ "obj-21", 0 ],
"destination" : [ "obj-14", 0 ],
"hidden" : 0,
"midpoints" : [ 351.5, 416.5, 268.5, 416.5 ]
}
}
, {
"patchline" : {
"source" : [ "obj-19", 0 ],
"destination" : [ "obj-14", 0 ],
"hidden" : 0,
"midpoints" : [ 373.5, 393.5, 268.5, 393.5 ]
}
}
, {
"patchline" : {
"source" : [ "obj-13", 0 ],
"destination" : [ "obj-14", 0 ],
"hidden" : 0,
"midpoints" : [ 393.5, 365.5, 268.5, 365.5 ]
}
}
, {
"patchline" : {
"source" : [ "obj-1", 0 ],
"destination" : [ "obj-6", 0 ],
"hidden" : 0,
"midpoints" : [ ]
}
}
, {
"patchline" : {
"source" : [ "obj-6", 0 ],
"destination" : [ "obj-14", 0 ],
"hidden" : 0,
"midpoints" : [ 224.5, 411.5, 268.5, 411.5 ]
}
}
]
}
*/

View File

@ -0,0 +1,578 @@
/*
Graph
A simple example of communication from the Arduino board to the computer:
the value of analog input 0 is sent out the serial port. We call this "serial"
communication because the connection appears to both the Arduino and the
computer as a serial port, even though it may actually use
a USB cable. Bytes are sent one after another (serially) from the Arduino
to the computer.
You can use the Arduino serial monitor to view the sent data, or it can
be read by Processing, PD, Max/MSP, or any other program capable of reading
data from a serial port. The Processing code below graphs the data received
so you can see the value of the analog input changing over time.
The circuit:
Any analog input sensor is attached to analog in pin 0.
http://www.arduino.cc/en/Tutorial/Graph
created 2006
by David A. Mellis
modified 14 Apr 2009
by Tom Igoe and Scott Fitzgerald
http://www.arduino.cc/en/Tutorial/Graph
*/
void setup() {
// initialize the serial communication:
Serial.begin(9600);
}
void loop() {
// send the value of analog input 0:
Serial.println(analogRead(0));
// wait a bit for the analog-to-digital converter
// to stabilize after the last reading:
delay(10);
}
/* Processing code for this example
// Graphing sketch
// This program takes ASCII-encoded strings
// from the serial port at 9600 baud and graphs them. It expects values in the
// range 0 to 1023, followed by a newline, or newline and carriage return
// Created 20 Apr 2005
// Updated 18 Jan 2008
// by Tom Igoe
import processing.serial.*;
Serial myPort; // The serial port
int xPos = 1; // horizontal position of the graph
void setup () {
// set the window size:
size(400, 300);
// List all the available serial ports
println(Serial.list());
// I know that the first port in the serial list on my mac
// is always my Arduino, so I open Serial.list()[0].
// Open whatever port is the one you're using.
myPort = new Serial(this, Serial.list()[0], 9600);
// don't generate a serialEvent() unless you get a newline character:
myPort.bufferUntil('\n');
// set inital background:
background(0);
}
void draw () {
// everything happens in the serialEvent()
}
void serialEvent (Serial myPort) {
// get the ASCII string:
String inString = myPort.readStringUntil('\n');
if (inString != null) {
// trim off any whitespace:
inString = trim(inString);
// convert to an int and map to the screen height:
float inByte = float(inString);
inByte = map(inByte, 0, 1023, 0, height);
// draw the line:
stroke(127,34,255);
line(xPos, height, xPos, height - inByte);
// at the edge of the screen, go back to the beginning:
if (xPos >= width) {
xPos = 0;
background(0);
}
else {
// increment the horizontal position:
xPos++;
}
}
}
*/
/* Max/MSP v5 patch for this example
{
"boxes" : [ {
"box" : {
"maxclass" : "comment",
"text" : "Graph\n\nThis patch takes a string, containing ASCII formatted number from 0 to 1023, with a carriage return and linefeed at the end. It converts the string to an integer and graphs it.\n\ncreated 2006\nby David A. Mellis\nmodified 14 Apr 2009\nby Scott Fitzgerald and Tom Igoe",
"linecount" : 10,
"patching_rect" : [ 479.0, 6.0, 344.0, 144.0 ],
"numoutlets" : 0,
"fontsize" : 12.0,
"id" : "obj-32",
"fontname" : "Arial",
"numinlets" : 1
}
}
, {
"box" : {
"maxclass" : "newobj",
"text" : "select 0 1",
"patching_rect" : [ 327.0, 80.0, 62.0, 20.0 ],
"numoutlets" : 3,
"fontsize" : 12.0,
"outlettype" : [ "bang", "bang", "" ],
"id" : "obj-30",
"fontname" : "Arial",
"numinlets" : 1
}
}
, {
"box" : {
"maxclass" : "comment",
"text" : "click here to close the serial port",
"patching_rect" : [ 412.0, 231.0, 206.0, 20.0 ],
"numoutlets" : 0,
"fontsize" : 12.0,
"id" : "obj-26",
"fontname" : "Arial",
"numinlets" : 1
}
}
, {
"box" : {
"maxclass" : "comment",
"text" : "click here to open the serial port",
"patching_rect" : [ 412.0, 205.0, 206.0, 20.0 ],
"numoutlets" : 0,
"fontsize" : 12.0,
"id" : "obj-27",
"fontname" : "Arial",
"numinlets" : 1
}
}
, {
"box" : {
"maxclass" : "message",
"text" : "close",
"patching_rect" : [ 327.0, 231.0, 39.0, 18.0 ],
"numoutlets" : 1,
"fontsize" : 12.0,
"outlettype" : [ "" ],
"id" : "obj-21",
"fontname" : "Arial",
"numinlets" : 2
}
}
, {
"box" : {
"maxclass" : "message",
"text" : "port a",
"patching_rect" : [ 349.0, 205.0, 41.0, 18.0 ],
"numoutlets" : 1,
"fontsize" : 12.0,
"outlettype" : [ "" ],
"id" : "obj-19",
"fontname" : "Arial",
"numinlets" : 2
}
}
, {
"box" : {
"maxclass" : "multislider",
"candicane7" : [ 0.878431, 0.243137, 0.145098, 1.0 ],
"patching_rect" : [ 302.0, 450.0, 246.0, 167.0 ],
"contdata" : 1,
"numoutlets" : 2,
"peakcolor" : [ 0.498039, 0.498039, 0.498039, 1.0 ],
"slidercolor" : [ 0.066667, 0.058824, 0.776471, 1.0 ],
"candicane8" : [ 0.027451, 0.447059, 0.501961, 1.0 ],
"outlettype" : [ "", "" ],
"setminmax" : [ 0.0, 1023.0 ],
"settype" : 0,
"candicane6" : [ 0.733333, 0.035294, 0.788235, 1.0 ],
"setstyle" : 3,
"bgcolor" : [ 0.231373, 0.713726, 1.0, 1.0 ],
"id" : "obj-1",
"candicane4" : [ 0.439216, 0.619608, 0.070588, 1.0 ],
"candicane5" : [ 0.584314, 0.827451, 0.431373, 1.0 ],
"candicane2" : [ 0.145098, 0.203922, 0.356863, 1.0 ],
"candicane3" : [ 0.290196, 0.411765, 0.713726, 1.0 ],
"numinlets" : 1
}
}
, {
"box" : {
"maxclass" : "comment",
"text" : "Click here to get a list of serial ports",
"patching_rect" : [ 412.0, 179.0, 207.0, 20.0 ],
"numoutlets" : 0,
"fontsize" : 12.0,
"id" : "obj-2",
"fontname" : "Arial",
"numinlets" : 1
}
}
, {
"box" : {
"maxclass" : "comment",
"text" : "Here's the number from Arduino's analog input",
"linecount" : 2,
"patching_rect" : [ 153.0, 409.0, 138.0, 34.0 ],
"numoutlets" : 0,
"fontsize" : 12.0,
"id" : "obj-3",
"fontname" : "Arial",
"numinlets" : 1
}
}
, {
"box" : {
"maxclass" : "comment",
"text" : "Convert ASCII to symbol",
"patching_rect" : [ 379.0, 378.0, 147.0, 20.0 ],
"numoutlets" : 0,
"fontsize" : 12.0,
"id" : "obj-4",
"fontname" : "Arial",
"numinlets" : 1
}
}
, {
"box" : {
"maxclass" : "comment",
"text" : "Convert integer to ASCII",
"patching_rect" : [ 379.0, 355.0, 147.0, 20.0 ],
"numoutlets" : 0,
"fontsize" : 12.0,
"id" : "obj-5",
"fontname" : "Arial",
"numinlets" : 1
}
}
, {
"box" : {
"maxclass" : "number",
"patching_rect" : [ 302.0, 414.0, 37.0, 20.0 ],
"numoutlets" : 2,
"fontsize" : 12.0,
"outlettype" : [ "int", "bang" ],
"bgcolor" : [ 0.866667, 0.866667, 0.866667, 1.0 ],
"id" : "obj-6",
"triscale" : 0.9,
"fontname" : "Arial",
"htextcolor" : [ 0.870588, 0.870588, 0.870588, 1.0 ],
"numinlets" : 1
}
}
, {
"box" : {
"maxclass" : "newobj",
"text" : "fromsymbol",
"patching_rect" : [ 302.0, 378.0, 74.0, 20.0 ],
"numoutlets" : 1,
"fontsize" : 12.0,
"outlettype" : [ "" ],
"id" : "obj-7",
"fontname" : "Arial",
"color" : [ 1.0, 0.890196, 0.090196, 1.0 ],
"numinlets" : 1
}
}
, {
"box" : {
"maxclass" : "newobj",
"text" : "itoa",
"patching_rect" : [ 302.0, 355.0, 46.0, 20.0 ],
"numoutlets" : 1,
"fontsize" : 12.0,
"outlettype" : [ "int" ],
"id" : "obj-8",
"fontname" : "Arial",
"color" : [ 1.0, 0.890196, 0.090196, 1.0 ],
"numinlets" : 3
}
}
, {
"box" : {
"maxclass" : "newobj",
"text" : "zl group 4",
"patching_rect" : [ 302.0, 332.0, 64.0, 20.0 ],
"numoutlets" : 2,
"fontsize" : 12.0,
"outlettype" : [ "", "" ],
"id" : "obj-9",
"fontname" : "Arial",
"numinlets" : 2
}
}
, {
"box" : {
"maxclass" : "newobj",
"text" : "select 10 13",
"patching_rect" : [ 244.0, 281.0, 77.0, 20.0 ],
"numoutlets" : 3,
"fontsize" : 12.0,
"outlettype" : [ "bang", "bang", "" ],
"id" : "obj-10",
"fontname" : "Arial",
"numinlets" : 1
}
}
, {
"box" : {
"maxclass" : "toggle",
"patching_rect" : [ 244.0, 43.0, 15.0, 15.0 ],
"numoutlets" : 1,
"outlettype" : [ "int" ],
"id" : "obj-11",
"numinlets" : 1
}
}
, {
"box" : {
"maxclass" : "newobj",
"text" : "qmetro 10",
"patching_rect" : [ 244.0, 80.0, 65.0, 20.0 ],
"numoutlets" : 1,
"fontsize" : 12.0,
"outlettype" : [ "bang" ],
"id" : "obj-12",
"fontname" : "Arial",
"numinlets" : 2
}
}
, {
"box" : {
"maxclass" : "message",
"text" : "print",
"patching_rect" : [ 369.0, 179.0, 36.0, 18.0 ],
"numoutlets" : 1,
"fontsize" : 12.0,
"outlettype" : [ "" ],
"id" : "obj-13",
"fontname" : "Arial",
"numinlets" : 2
}
}
, {
"box" : {
"maxclass" : "newobj",
"text" : "serial a 9600",
"patching_rect" : [ 244.0, 255.0, 84.0, 20.0 ],
"numoutlets" : 2,
"fontsize" : 12.0,
"outlettype" : [ "int", "" ],
"id" : "obj-14",
"fontname" : "Arial",
"numinlets" : 1
}
}
, {
"box" : {
"maxclass" : "comment",
"text" : "Read serial input buffer every 10 milliseconds",
"linecount" : 2,
"patching_rect" : [ 53.0, 72.0, 185.0, 34.0 ],
"numoutlets" : 0,
"fontsize" : 12.0,
"id" : "obj-15",
"fontname" : "Arial",
"numinlets" : 1
}
}
, {
"box" : {
"maxclass" : "comment",
"text" : "If you get newline (ASCII 10), send the list. If you get return (ASCII 13) do nothing. Any other value, add to the list",
"linecount" : 3,
"patching_rect" : [ 332.0, 269.0, 320.0, 48.0 ],
"numoutlets" : 0,
"fontsize" : 12.0,
"id" : "obj-16",
"fontname" : "Arial",
"numinlets" : 1
}
}
, {
"box" : {
"maxclass" : "comment",
"text" : "Click to open/close serial port and start/stop patch",
"linecount" : 2,
"patching_rect" : [ 271.0, 32.0, 199.0, 34.0 ],
"numoutlets" : 0,
"fontsize" : 12.0,
"id" : "obj-17",
"fontname" : "Arial",
"numinlets" : 1
}
}
],
"lines" : [ {
"patchline" : {
"source" : [ "obj-6", 0 ],
"destination" : [ "obj-1", 0 ],
"hidden" : 0,
"midpoints" : [ ]
}
}
, {
"patchline" : {
"source" : [ "obj-7", 0 ],
"destination" : [ "obj-6", 0 ],
"hidden" : 0,
"midpoints" : [ ]
}
}
, {
"patchline" : {
"source" : [ "obj-8", 0 ],
"destination" : [ "obj-7", 0 ],
"hidden" : 0,
"midpoints" : [ ]
}
}
, {
"patchline" : {
"source" : [ "obj-9", 0 ],
"destination" : [ "obj-8", 0 ],
"hidden" : 0,
"midpoints" : [ ]
}
}
, {
"patchline" : {
"source" : [ "obj-10", 0 ],
"destination" : [ "obj-9", 0 ],
"hidden" : 0,
"midpoints" : [ 253.5, 308.0, 311.5, 308.0 ]
}
}
, {
"patchline" : {
"source" : [ "obj-10", 2 ],
"destination" : [ "obj-9", 0 ],
"hidden" : 0,
"midpoints" : [ 311.5, 320.0, 311.5, 320.0 ]
}
}
, {
"patchline" : {
"source" : [ "obj-14", 0 ],
"destination" : [ "obj-10", 0 ],
"hidden" : 0,
"midpoints" : [ ]
}
}
, {
"patchline" : {
"source" : [ "obj-12", 0 ],
"destination" : [ "obj-14", 0 ],
"hidden" : 0,
"midpoints" : [ ]
}
}
, {
"patchline" : {
"source" : [ "obj-11", 0 ],
"destination" : [ "obj-12", 0 ],
"hidden" : 0,
"midpoints" : [ ]
}
}
, {
"patchline" : {
"source" : [ "obj-13", 0 ],
"destination" : [ "obj-14", 0 ],
"hidden" : 0,
"midpoints" : [ 378.5, 200.5, 253.5, 200.5 ]
}
}
, {
"patchline" : {
"source" : [ "obj-19", 0 ],
"destination" : [ "obj-14", 0 ],
"hidden" : 0,
"midpoints" : [ 358.5, 228.5, 253.5, 228.5 ]
}
}
, {
"patchline" : {
"source" : [ "obj-21", 0 ],
"destination" : [ "obj-14", 0 ],
"hidden" : 0,
"midpoints" : [ 336.5, 251.5, 253.5, 251.5 ]
}
}
, {
"patchline" : {
"source" : [ "obj-30", 0 ],
"destination" : [ "obj-21", 0 ],
"hidden" : 0,
"midpoints" : [ ]
}
}
, {
"patchline" : {
"source" : [ "obj-30", 1 ],
"destination" : [ "obj-19", 0 ],
"hidden" : 0,
"midpoints" : [ ]
}
}
, {
"patchline" : {
"source" : [ "obj-11", 0 ],
"destination" : [ "obj-30", 0 ],
"hidden" : 0,
"midpoints" : [ 253.0, 71.0, 336.5, 71.0 ]
}
}
]
}
*/

View File

@ -0,0 +1,707 @@
/*
Physical Pixel
An example of using the Arduino board to receive data from the
computer. In this case, the Arduino boards turns on an LED when
it receives the character 'H', and turns off the LED when it
receives the character 'L'.
The data can be sent from the Arduino serial monitor, or another
program like Processing (see code below), Flash (via a serial-net
proxy), PD, or Max/MSP.
The circuit:
* LED connected from digital pin 13 to ground
created 2006
by David A. Mellis
modified 14 Apr 2009
by Tom Igoe and Scott Fitzgerald
http://www.arduino.cc/en/Tutorial/PhysicalPixel
*/
const int ledPin = 13; // the pin that the LED is attached to
int incomingByte; // a variable to read incoming serial data into
void setup() {
// initialize serial communication:
Serial.begin(9600);
// initialize the LED pin as an output:
pinMode(ledPin, OUTPUT);
}
void loop() {
// see if there's incoming serial data:
if (Serial.available() > 0) {
// read the oldest byte in the serial buffer:
incomingByte = Serial.read();
// if it's a capital H (ASCII 72), turn on the LED:
if (incomingByte == 'H') {
digitalWrite(ledPin, HIGH);
}
// if it's an L (ASCII 76) turn off the LED:
if (incomingByte == 'L') {
digitalWrite(ledPin, LOW);
}
}
}
/* Processing code for this example
// mouseover serial
// Demonstrates how to send data to the Arduino I/O board, in order to
// turn ON a light if the mouse is over a square and turn it off
// if the mouse is not.
// created 2003-4
// based on examples by Casey Reas and Hernando Barragan
// modified 18 Jan 2009
// by Tom Igoe
import processing.serial.*;
float boxX;
float boxY;
int boxSize = 20;
boolean mouseOverBox = false;
Serial port;
void setup() {
size(200, 200);
boxX = width/2.0;
boxY = height/2.0;
rectMode(RADIUS);
// List all the available serial ports in the output pane.
// You will need to choose the port that the Arduino board is
// connected to from this list. The first port in the list is
// port #0 and the third port in the list is port #2.
println(Serial.list());
// Open the port that the Arduino board is connected to (in this case #0)
// Make sure to open the port at the same speed Arduino is using (9600bps)
port = new Serial(this, Serial.list()[0], 9600);
}
void draw()
{
background(0);
// Test if the cursor is over the box
if (mouseX > boxX-boxSize && mouseX < boxX+boxSize &&
mouseY > boxY-boxSize && mouseY < boxY+boxSize) {
mouseOverBox = true;
// draw a line around the box and change its color:
stroke(255);
fill(153);
// send an 'H' to indicate mouse is over square:
port.write('H');
}
else {
// return the box to it's inactive state:
stroke(153);
fill(153);
// send an 'L' to turn the LED off:
port.write('L');
mouseOverBox = false;
}
// Draw the box
rect(boxX, boxY, boxSize, boxSize);
}
*/
/*
{
"boxes" : [ {
"box" : {
"maxclass" : "comment",
"text" : "Physical Pixel\n\nThis patch sends an ASCII H or an ASCII L out the serial port to turn on an LED attached to an Arduino board. It can also send alternating H and L characters once every second to make the LED blink.\n\ncreated 2006\nby David A. Mellis\nmodified 14 Apr 2009\nby Scott Fitzgerald and Tom Igoe",
"linecount" : 11,
"patching_rect" : [ 14.0, 35.0, 354.0, 158.0 ],
"numoutlets" : 0,
"fontsize" : 12.0,
"id" : "obj-1",
"fontname" : "Arial",
"numinlets" : 1
}
}
, {
"box" : {
"maxclass" : "comment",
"text" : "Click to blink every second",
"patching_rect" : [ 99.0, 251.0, 161.0, 20.0 ],
"numoutlets" : 0,
"fontsize" : 12.0,
"id" : "obj-38",
"fontname" : "Arial",
"numinlets" : 1
}
}
, {
"box" : {
"maxclass" : "toggle",
"patching_rect" : [ 74.0, 251.0, 21.0, 21.0 ],
"numoutlets" : 1,
"outlettype" : [ "int" ],
"id" : "obj-39",
"numinlets" : 1
}
}
, {
"box" : {
"maxclass" : "newobj",
"text" : "p blink",
"patching_rect" : [ 74.0, 286.0, 45.0, 20.0 ],
"numoutlets" : 1,
"fontsize" : 12.0,
"outlettype" : [ "int" ],
"id" : "obj-37",
"fontname" : "Arial",
"numinlets" : 2,
"patcher" : {
"fileversion" : 1,
"rect" : [ 54.0, 94.0, 640.0, 480.0 ],
"bglocked" : 0,
"defrect" : [ 54.0, 94.0, 640.0, 480.0 ],
"openrect" : [ 0.0, 0.0, 0.0, 0.0 ],
"openinpresentation" : 0,
"default_fontsize" : 10.0,
"default_fontface" : 0,
"default_fontname" : "Verdana",
"gridonopen" : 0,
"gridsize" : [ 25.0, 25.0 ],
"gridsnaponopen" : 0,
"toolbarvisible" : 1,
"boxanimatetime" : 200,
"imprint" : 0,
"boxes" : [ {
"box" : {
"maxclass" : "newobj",
"text" : "* 1000",
"patching_rect" : [ 200.0, 150.0, 46.0, 19.0 ],
"numoutlets" : 1,
"fontsize" : 10.0,
"outlettype" : [ "int" ],
"id" : "obj-12",
"fontname" : "Verdana",
"numinlets" : 2
}
}
, {
"box" : {
"maxclass" : "inlet",
"patching_rect" : [ 200.0, 75.0, 25.0, 25.0 ],
"numoutlets" : 1,
"outlettype" : [ "" ],
"id" : "obj-11",
"numinlets" : 0,
"comment" : ""
}
}
, {
"box" : {
"maxclass" : "toggle",
"patching_rect" : [ 125.0, 250.0, 20.0, 20.0 ],
"numoutlets" : 1,
"outlettype" : [ "int" ],
"id" : "obj-10",
"numinlets" : 1
}
}
, {
"box" : {
"maxclass" : "newobj",
"text" : "metro 1000",
"patching_rect" : [ 115.0, 190.0, 69.0, 19.0 ],
"numoutlets" : 1,
"fontsize" : 10.0,
"outlettype" : [ "bang" ],
"id" : "obj-3",
"fontname" : "Verdana",
"numinlets" : 2
}
}
, {
"box" : {
"maxclass" : "outlet",
"patching_rect" : [ 125.0, 400.0, 25.0, 25.0 ],
"numoutlets" : 0,
"id" : "obj-2",
"numinlets" : 1,
"comment" : ""
}
}
, {
"box" : {
"maxclass" : "inlet",
"patching_rect" : [ 100.0, 25.0, 25.0, 25.0 ],
"numoutlets" : 1,
"outlettype" : [ "int" ],
"id" : "obj-1",
"numinlets" : 0,
"comment" : ""
}
}
],
"lines" : [ {
"patchline" : {
"source" : [ "obj-12", 0 ],
"destination" : [ "obj-3", 1 ],
"hidden" : 0,
"midpoints" : [ ]
}
}
, {
"patchline" : {
"source" : [ "obj-11", 0 ],
"destination" : [ "obj-12", 0 ],
"hidden" : 0,
"midpoints" : [ ]
}
}
, {
"patchline" : {
"source" : [ "obj-1", 0 ],
"destination" : [ "obj-3", 0 ],
"hidden" : 0,
"midpoints" : [ ]
}
}
, {
"patchline" : {
"source" : [ "obj-10", 0 ],
"destination" : [ "obj-2", 0 ],
"hidden" : 0,
"midpoints" : [ ]
}
}
, {
"patchline" : {
"source" : [ "obj-3", 0 ],
"destination" : [ "obj-10", 0 ],
"hidden" : 0,
"midpoints" : [ ]
}
}
]
}
,
"saved_object_attributes" : {
"fontface" : 0,
"fontsize" : 10.0,
"default_fontface" : 0,
"default_fontname" : "Verdana",
"default_fontsize" : 10.0,
"fontname" : "Verdana",
"globalpatchername" : ""
}
}
}
, {
"box" : {
"maxclass" : "comment",
"text" : "convert to int",
"patching_rect" : [ 154.0, 386.0, 104.0, 20.0 ],
"numoutlets" : 0,
"fontsize" : 12.0,
"id" : "obj-36",
"fontname" : "Arial",
"numinlets" : 1
}
}
, {
"box" : {
"maxclass" : "comment",
"text" : "send L if 0, H if 1",
"patching_rect" : [ 154.0, 361.0, 104.0, 20.0 ],
"numoutlets" : 0,
"fontsize" : 12.0,
"id" : "obj-35",
"fontname" : "Arial",
"numinlets" : 1
}
}
, {
"box" : {
"maxclass" : "comment",
"text" : "is it on or off?",
"patching_rect" : [ 179.0, 336.0, 95.0, 20.0 ],
"numoutlets" : 0,
"fontsize" : 12.0,
"id" : "obj-34",
"fontname" : "Arial",
"numinlets" : 1
}
}
, {
"box" : {
"maxclass" : "newobj",
"text" : "atoi",
"patching_rect" : [ 279.0, 386.0, 46.0, 20.0 ],
"numoutlets" : 1,
"fontsize" : 12.0,
"outlettype" : [ "list" ],
"id" : "obj-33",
"fontname" : "Arial",
"numinlets" : 3
}
}
, {
"box" : {
"maxclass" : "message",
"text" : "H",
"patching_rect" : [ 329.0, 361.0, 32.5, 17.0 ],
"numoutlets" : 1,
"fontsize" : 10.0,
"outlettype" : [ "" ],
"id" : "obj-32",
"fontname" : "Verdana",
"numinlets" : 2
}
}
, {
"box" : {
"maxclass" : "message",
"text" : "L",
"patching_rect" : [ 279.0, 361.0, 32.5, 17.0 ],
"numoutlets" : 1,
"fontsize" : 10.0,
"outlettype" : [ "" ],
"id" : "obj-31",
"fontname" : "Verdana",
"numinlets" : 2
}
}
, {
"box" : {
"maxclass" : "newobj",
"text" : "select 0 1",
"patching_rect" : [ 279.0, 336.0, 62.0, 20.0 ],
"numoutlets" : 3,
"fontsize" : 12.0,
"outlettype" : [ "bang", "bang", "" ],
"id" : "obj-25",
"fontname" : "Arial",
"numinlets" : 1
}
}
, {
"box" : {
"maxclass" : "comment",
"text" : "Click to turn the LED on and off",
"linecount" : 2,
"patching_rect" : [ 130.0, 205.0, 143.0, 34.0 ],
"numoutlets" : 0,
"fontsize" : 12.0,
"id" : "obj-24",
"fontname" : "Arial",
"numinlets" : 1
}
}
, {
"box" : {
"maxclass" : "toggle",
"patching_rect" : [ 279.0, 211.0, 24.0, 24.0 ],
"numoutlets" : 1,
"outlettype" : [ "int" ],
"id" : "obj-23",
"numinlets" : 1
}
}
, {
"box" : {
"maxclass" : "newobj",
"text" : "select 0 1",
"patching_rect" : [ 381.0, 331.0, 62.0, 20.0 ],
"numoutlets" : 3,
"fontsize" : 12.0,
"outlettype" : [ "bang", "bang", "" ],
"id" : "obj-30",
"fontname" : "Arial",
"numinlets" : 1
}
}
, {
"box" : {
"maxclass" : "comment",
"text" : "click here to close the serial port",
"patching_rect" : [ 429.0, 422.0, 206.0, 20.0 ],
"numoutlets" : 0,
"fontsize" : 12.0,
"id" : "obj-26",
"fontname" : "Arial",
"numinlets" : 1
}
}
, {
"box" : {
"maxclass" : "comment",
"text" : "click here to open the serial port",
"patching_rect" : [ 454.0, 396.0, 206.0, 20.0 ],
"numoutlets" : 0,
"fontsize" : 12.0,
"id" : "obj-27",
"fontname" : "Arial",
"numinlets" : 1
}
}
, {
"box" : {
"maxclass" : "message",
"text" : "close",
"patching_rect" : [ 381.0, 422.0, 39.0, 18.0 ],
"numoutlets" : 1,
"fontsize" : 12.0,
"outlettype" : [ "" ],
"id" : "obj-21",
"fontname" : "Arial",
"numinlets" : 2
}
}
, {
"box" : {
"maxclass" : "message",
"text" : "port a",
"patching_rect" : [ 403.0, 396.0, 41.0, 18.0 ],
"numoutlets" : 1,
"fontsize" : 12.0,
"outlettype" : [ "" ],
"id" : "obj-19",
"fontname" : "Arial",
"numinlets" : 2
}
}
, {
"box" : {
"maxclass" : "comment",
"text" : "Click here to get a list of serial ports",
"patching_rect" : [ 474.0, 370.0, 207.0, 20.0 ],
"numoutlets" : 0,
"fontsize" : 12.0,
"id" : "obj-2",
"fontname" : "Arial",
"numinlets" : 1
}
}
, {
"box" : {
"maxclass" : "toggle",
"patching_rect" : [ 381.0, 181.0, 21.0, 21.0 ],
"numoutlets" : 1,
"outlettype" : [ "int" ],
"id" : "obj-11",
"numinlets" : 1
}
}
, {
"box" : {
"maxclass" : "message",
"text" : "print",
"patching_rect" : [ 423.0, 370.0, 36.0, 18.0 ],
"numoutlets" : 1,
"fontsize" : 12.0,
"outlettype" : [ "" ],
"id" : "obj-13",
"fontname" : "Arial",
"numinlets" : 2
}
}
, {
"box" : {
"maxclass" : "newobj",
"text" : "serial a 9600",
"patching_rect" : [ 279.0, 461.0, 84.0, 20.0 ],
"numoutlets" : 2,
"fontsize" : 12.0,
"outlettype" : [ "int", "" ],
"id" : "obj-14",
"fontname" : "Arial",
"numinlets" : 1
}
}
, {
"box" : {
"maxclass" : "comment",
"text" : "Click to start",
"patching_rect" : [ 408.0, 181.0, 117.0, 20.0 ],
"numoutlets" : 0,
"fontsize" : 12.0,
"id" : "obj-17",
"fontname" : "Arial",
"numinlets" : 1
}
}
],
"lines" : [ {
"patchline" : {
"source" : [ "obj-39", 0 ],
"destination" : [ "obj-37", 0 ],
"hidden" : 0,
"midpoints" : [ ]
}
}
, {
"patchline" : {
"source" : [ "obj-37", 0 ],
"destination" : [ "obj-25", 0 ],
"hidden" : 0,
"midpoints" : [ 83.5, 320.5, 288.5, 320.5 ]
}
}
, {
"patchline" : {
"source" : [ "obj-33", 0 ],
"destination" : [ "obj-14", 0 ],
"hidden" : 0,
"midpoints" : [ ]
}
}
, {
"patchline" : {
"source" : [ "obj-32", 0 ],
"destination" : [ "obj-33", 0 ],
"hidden" : 0,
"midpoints" : [ 338.5, 381.5, 288.5, 381.5 ]
}
}
, {
"patchline" : {
"source" : [ "obj-31", 0 ],
"destination" : [ "obj-33", 0 ],
"hidden" : 0,
"midpoints" : [ ]
}
}
, {
"patchline" : {
"source" : [ "obj-25", 0 ],
"destination" : [ "obj-31", 0 ],
"hidden" : 0,
"midpoints" : [ ]
}
}
, {
"patchline" : {
"source" : [ "obj-25", 1 ],
"destination" : [ "obj-32", 0 ],
"hidden" : 0,
"midpoints" : [ 310.0, 358.0, 338.5, 358.0 ]
}
}
, {
"patchline" : {
"source" : [ "obj-23", 0 ],
"destination" : [ "obj-25", 0 ],
"hidden" : 0,
"midpoints" : [ ]
}
}
, {
"patchline" : {
"source" : [ "obj-13", 0 ],
"destination" : [ "obj-14", 0 ],
"hidden" : 0,
"midpoints" : [ 432.5, 389.0, 367.0, 389.0, 367.0, 411.0, 288.5, 411.0 ]
}
}
, {
"patchline" : {
"source" : [ "obj-19", 0 ],
"destination" : [ "obj-14", 0 ],
"hidden" : 0,
"midpoints" : [ 412.5, 417.0, 288.5, 417.0 ]
}
}
, {
"patchline" : {
"source" : [ "obj-21", 0 ],
"destination" : [ "obj-14", 0 ],
"hidden" : 0,
"midpoints" : [ 390.5, 450.0, 288.5, 450.0 ]
}
}
, {
"patchline" : {
"source" : [ "obj-30", 0 ],
"destination" : [ "obj-21", 0 ],
"hidden" : 0,
"midpoints" : [ ]
}
}
, {
"patchline" : {
"source" : [ "obj-30", 1 ],
"destination" : [ "obj-19", 0 ],
"hidden" : 0,
"midpoints" : [ ]
}
}
, {
"patchline" : {
"source" : [ "obj-11", 0 ],
"destination" : [ "obj-30", 0 ],
"hidden" : 0,
"midpoints" : [ 390.5, 322.0, 390.5, 322.0 ]
}
}
]
}
*/

View File

@ -0,0 +1,1193 @@
/*
Serial Call and Response
Language: Wiring/Arduino
This program sends an ASCII A (byte of value 65) on startup
and repeats that until it gets some data in.
Then it waits for a byte in the serial port, and
sends three sensor values whenever it gets a byte in.
Thanks to Greg Shakar and Scott Fitzgerald for the improvements
The circuit:
* potentiometers attached to analog inputs 0 and 1
* pushbutton attached to digital I/O 2
http://www.arduino.cc/en/Tutorial/SerialCallResponse
Created 26 Sept. 2005
by Tom Igoe
Modified 14 April 2009
by Tom Igoe and Scott Fitzgerald
*/
int firstSensor = 0; // first analog sensor
int secondSensor = 0; // second analog sensor
int thirdSensor = 0; // digital sensor
int inByte = 0; // incoming serial byte
void setup()
{
// start serial port at 9600 bps:
Serial.begin(9600);
pinMode(2, INPUT); // digital sensor is on digital pin 2
establishContact(); // send a byte to establish contact until receiver responds
}
void loop()
{
// if we get a valid byte, read analog ins:
if (Serial.available() > 0) {
// get incoming byte:
inByte = Serial.read();
// read first analog input, divide by 4 to make the range 0-255:
firstSensor = analogRead(0)/4;
// delay 10ms to let the ADC recover:
delay(10);
// read second analog input, divide by 4 to make the range 0-255:
secondSensor = analogRead(1)/4;
// read switch, map it to 0 or 255L
thirdSensor = map(digitalRead(2), 0, 1, 0, 255);
// send sensor values:
Serial.print(firstSensor, BYTE);
Serial.print(secondSensor, BYTE);
Serial.print(thirdSensor, BYTE);
}
}
void establishContact() {
while (Serial.available() <= 0) {
Serial.print('A', BYTE); // send a capital A
delay(300);
}
}
/*
Processing sketch to run with this example:
import processing.serial.*;
int bgcolor; // Background color
int fgcolor; // Fill color
Serial myPort; // The serial port
int[] serialInArray = new int[3]; // Where we'll put what we receive
int serialCount = 0; // A count of how many bytes we receive
int xpos, ypos; // Starting position of the ball
boolean firstContact = false; // Whether we've heard from the microcontroller
void setup() {
size(256, 256); // Stage size
noStroke(); // No border on the next thing drawn
// Set the starting position of the ball (middle of the stage)
xpos = width/2;
ypos = height/2;
// Print a list of the serial ports, for debugging purposes:
println(Serial.list());
// I know that the first port in the serial list on my mac
// is always my FTDI adaptor, so I open Serial.list()[0].
// On Windows machines, this generally opens COM1.
// Open whatever port is the one you're using.
String portName = Serial.list()[0];
myPort = new Serial(this, portName, 9600);
}
void draw() {
background(bgcolor);
fill(fgcolor);
// Draw the shape
ellipse(xpos, ypos, 20, 20);
}
void serialEvent(Serial myPort) {
// read a byte from the serial port:
int inByte = myPort.read();
// if this is the first byte received, and it's an A,
// clear the serial buffer and note that you've
// had first contact from the microcontroller.
// Otherwise, add the incoming byte to the array:
if (firstContact == false) {
if (inByte == 'A') {
myPort.clear(); // clear the serial port buffer
firstContact = true; // you've had first contact from the microcontroller
myPort.write('A'); // ask for more
}
}
else {
// Add the latest byte from the serial port to array:
serialInArray[serialCount] = inByte;
serialCount++;
// If we have 3 bytes:
if (serialCount > 2 ) {
xpos = serialInArray[0];
ypos = serialInArray[1];
fgcolor = serialInArray[2];
// print the values (for debugging purposes only):
println(xpos + "\t" + ypos + "\t" + fgcolor);
// Send a capital A to request new sensor readings:
myPort.write('A');
// Reset serialCount:
serialCount = 0;
}
}
}
*/
/*
Max/MSP version 5 patch to run with this example:
{
"boxes" : [ {
"box" : {
"maxclass" : "message",
"text" : "65",
"patching_rect" : [ 339.0, 466.0, 32.5, 18.0 ],
"numoutlets" : 1,
"fontsize" : 12.0,
"outlettype" : [ "" ],
"id" : "obj-9",
"fontname" : "Arial",
"numinlets" : 2
}
}
, {
"box" : {
"maxclass" : "newobj",
"text" : "sel 1",
"patching_rect" : [ 339.0, 437.0, 36.0, 20.0 ],
"numoutlets" : 2,
"fontsize" : 12.0,
"outlettype" : [ "bang", "" ],
"id" : "obj-6",
"fontname" : "Arial",
"numinlets" : 2
}
}
, {
"box" : {
"maxclass" : "comment",
"text" : "Serial Call-Response \n\nSends a byte out the serial port, and reads 3 bytes in. Sets foregound color, xpos, and ypos of a circle using the values returned from the serial port. \n\nNote: This patch assumes that the device on the other end of the serial port is going to send a single byte of value 65 (ASCII A) on startup. The sketch waits for that byte, then sends an ASCII A whenever it wants more data. \n\ncreated 14 Apr 2009\nby Scott Fitzgerald and Tom Igoe",
"linecount" : 11,
"patching_rect" : [ 404.0, 52.0, 464.0, 158.0 ],
"numoutlets" : 0,
"fontsize" : 12.0,
"id" : "obj-5",
"fontname" : "Arial",
"numinlets" : 1
}
}
, {
"box" : {
"maxclass" : "comment",
"text" : "trigger (or [t]) forces right-left conventions. All the drawing and processing will happen before Max requests new values. When this trigger fires, it sends an ASCII A to ask Arduino for new values.",
"linecount" : 3,
"patching_rect" : [ 239.0, 505.0, 425.0, 48.0 ],
"numoutlets" : 0,
"fontsize" : 12.0,
"id" : "obj-65",
"fontname" : "Arial",
"numinlets" : 1
}
}
, {
"box" : {
"maxclass" : "comment",
"text" : "reinitializes the gates when turned on and off",
"linecount" : 2,
"patching_rect" : [ 170.0, 370.0, 135.0, 34.0 ],
"numoutlets" : 0,
"fontsize" : 12.0,
"id" : "obj-64",
"fontname" : "Arial",
"numinlets" : 1
}
}
, {
"box" : {
"maxclass" : "comment",
"text" : "checks for the ascii value of \"A\" to begin cominucation. After initial communication is made, this block shuts down.",
"linecount" : 3,
"patching_rect" : [ 460.0, 355.0, 233.0, 48.0 ],
"numoutlets" : 0,
"fontsize" : 12.0,
"id" : "obj-63",
"fontname" : "Arial",
"numinlets" : 1
}
}
, {
"box" : {
"maxclass" : "newobj",
"text" : "p \"draw the circle\"",
"patching_rect" : [ 217.0, 645.0, 269.0, 19.0 ],
"numoutlets" : 1,
"fontsize" : 10.0,
"outlettype" : [ "" ],
"id" : "obj-62",
"fontname" : "Verdana",
"numinlets" : 3,
"patcher" : {
"fileversion" : 1,
"rect" : [ 54.0, 94.0, 640.0, 480.0 ],
"bglocked" : 0,
"defrect" : [ 54.0, 94.0, 640.0, 480.0 ],
"openrect" : [ 0.0, 0.0, 0.0, 0.0 ],
"openinpresentation" : 0,
"default_fontsize" : 10.0,
"default_fontface" : 0,
"default_fontname" : "Verdana",
"gridonopen" : 0,
"gridsize" : [ 25.0, 25.0 ],
"gridsnaponopen" : 0,
"toolbarvisible" : 1,
"boxanimatetime" : 200,
"imprint" : 0,
"boxes" : [ {
"box" : {
"maxclass" : "message",
"text" : "frgb 255 255 255",
"patching_rect" : [ 375.0, 150.0, 98.0, 18.0 ],
"numoutlets" : 1,
"fontsize" : 11.595187,
"outlettype" : [ "" ],
"id" : "obj-47",
"fontname" : "Arial",
"numinlets" : 2
}
}
, {
"box" : {
"maxclass" : "message",
"text" : "frgb 0 0 0",
"patching_rect" : [ 275.0, 125.0, 59.0, 18.0 ],
"numoutlets" : 1,
"fontsize" : 11.595187,
"outlettype" : [ "" ],
"id" : "obj-46",
"fontname" : "Arial",
"numinlets" : 2
}
}
, {
"box" : {
"maxclass" : "newobj",
"text" : "sel 255 0",
"patching_rect" : [ 300.0, 100.0, 66.0, 21.0 ],
"numoutlets" : 3,
"fontsize" : 12.0,
"outlettype" : [ "bang", "bang", "" ],
"id" : "obj-45",
"fontname" : "Verdana",
"numinlets" : 1
}
}
, {
"box" : {
"maxclass" : "newobj",
"text" : "pack 0 0 0 0",
"patching_rect" : [ 50.0, 125.0, 180.0, 21.0 ],
"numoutlets" : 1,
"fontsize" : 12.0,
"outlettype" : [ "" ],
"id" : "obj-43",
"fontname" : "Verdana",
"numinlets" : 4
}
}
, {
"box" : {
"maxclass" : "newobj",
"text" : "+ 10",
"patching_rect" : [ 200.0, 100.0, 40.0, 21.0 ],
"numoutlets" : 1,
"fontsize" : 12.0,
"outlettype" : [ "int" ],
"id" : "obj-42",
"fontname" : "Verdana",
"numinlets" : 2
}
}
, {
"box" : {
"maxclass" : "newobj",
"text" : "+ 10",
"patching_rect" : [ 75.0, 100.0, 40.0, 21.0 ],
"numoutlets" : 1,
"fontsize" : 12.0,
"outlettype" : [ "int" ],
"id" : "obj-41",
"fontname" : "Verdana",
"numinlets" : 2
}
}
, {
"box" : {
"maxclass" : "message",
"text" : "clear, paintoval $1 $2 $3 $4",
"patching_rect" : [ 50.0, 150.0, 152.0, 18.0 ],
"numoutlets" : 1,
"fontsize" : 11.595187,
"outlettype" : [ "" ],
"id" : "obj-40",
"fontname" : "Arial",
"numinlets" : 2
}
}
, {
"box" : {
"maxclass" : "inlet",
"patching_rect" : [ 57.5, 40.0, 25.0, 25.0 ],
"numoutlets" : 1,
"outlettype" : [ "int" ],
"id" : "obj-58",
"numinlets" : 0,
"comment" : ""
}
}
, {
"box" : {
"maxclass" : "inlet",
"patching_rect" : [ 120.0, 40.0, 25.0, 25.0 ],
"numoutlets" : 1,
"outlettype" : [ "int" ],
"id" : "obj-59",
"numinlets" : 0,
"comment" : ""
}
}
, {
"box" : {
"maxclass" : "inlet",
"patching_rect" : [ 300.0, 40.0, 25.0, 25.0 ],
"numoutlets" : 1,
"outlettype" : [ "int" ],
"id" : "obj-60",
"numinlets" : 0,
"comment" : ""
}
}
, {
"box" : {
"maxclass" : "outlet",
"patching_rect" : [ 228.333344, 228.0, 25.0, 25.0 ],
"numoutlets" : 0,
"id" : "obj-61",
"numinlets" : 1,
"comment" : ""
}
}
],
"lines" : [ {
"patchline" : {
"source" : [ "obj-47", 0 ],
"destination" : [ "obj-61", 0 ],
"hidden" : 0,
"midpoints" : [ ]
}
}
, {
"patchline" : {
"source" : [ "obj-46", 0 ],
"destination" : [ "obj-61", 0 ],
"hidden" : 0,
"midpoints" : [ ]
}
}
, {
"patchline" : {
"source" : [ "obj-40", 0 ],
"destination" : [ "obj-61", 0 ],
"hidden" : 0,
"midpoints" : [ ]
}
}
, {
"patchline" : {
"source" : [ "obj-60", 0 ],
"destination" : [ "obj-45", 0 ],
"hidden" : 0,
"midpoints" : [ ]
}
}
, {
"patchline" : {
"source" : [ "obj-59", 0 ],
"destination" : [ "obj-42", 0 ],
"hidden" : 0,
"midpoints" : [ ]
}
}
, {
"patchline" : {
"source" : [ "obj-59", 0 ],
"destination" : [ "obj-43", 1 ],
"hidden" : 0,
"midpoints" : [ ]
}
}
, {
"patchline" : {
"source" : [ "obj-58", 0 ],
"destination" : [ "obj-41", 0 ],
"hidden" : 0,
"midpoints" : [ ]
}
}
, {
"patchline" : {
"source" : [ "obj-58", 0 ],
"destination" : [ "obj-43", 0 ],
"hidden" : 0,
"midpoints" : [ ]
}
}
, {
"patchline" : {
"source" : [ "obj-42", 0 ],
"destination" : [ "obj-43", 3 ],
"hidden" : 0,
"midpoints" : [ ]
}
}
, {
"patchline" : {
"source" : [ "obj-41", 0 ],
"destination" : [ "obj-43", 2 ],
"hidden" : 0,
"midpoints" : [ ]
}
}
, {
"patchline" : {
"source" : [ "obj-45", 1 ],
"destination" : [ "obj-47", 0 ],
"hidden" : 0,
"midpoints" : [ ]
}
}
, {
"patchline" : {
"source" : [ "obj-45", 0 ],
"destination" : [ "obj-46", 0 ],
"hidden" : 0,
"midpoints" : [ ]
}
}
, {
"patchline" : {
"source" : [ "obj-43", 0 ],
"destination" : [ "obj-40", 0 ],
"hidden" : 0,
"midpoints" : [ ]
}
}
]
}
,
"saved_object_attributes" : {
"fontface" : 0,
"fontsize" : 10.0,
"default_fontface" : 0,
"default_fontname" : "Verdana",
"default_fontsize" : 10.0,
"fontname" : "Verdana",
"globalpatchername" : ""
}
}
}
, {
"box" : {
"maxclass" : "newobj",
"text" : "0",
"patching_rect" : [ 310.0, 378.0, 32.5, 20.0 ],
"numoutlets" : 1,
"fontsize" : 12.0,
"outlettype" : [ "int" ],
"id" : "obj-57",
"fontname" : "Arial",
"numinlets" : 2
}
}
, {
"box" : {
"maxclass" : "newobj",
"text" : "!- 1",
"patching_rect" : [ 385.0, 436.0, 32.5, 20.0 ],
"numoutlets" : 1,
"fontsize" : 12.0,
"outlettype" : [ "int" ],
"id" : "obj-55",
"fontname" : "Arial",
"numinlets" : 2
}
}
, {
"box" : {
"maxclass" : "newobj",
"text" : "gate 1 1",
"patching_rect" : [ 385.0, 355.0, 54.0, 20.0 ],
"numoutlets" : 1,
"fontsize" : 12.0,
"outlettype" : [ "" ],
"id" : "obj-54",
"fontname" : "Arial",
"numinlets" : 2
}
}
, {
"box" : {
"maxclass" : "toggle",
"patching_rect" : [ 385.0, 405.0, 20.0, 20.0 ],
"numoutlets" : 1,
"outlettype" : [ "int" ],
"id" : "obj-53",
"numinlets" : 1
}
}
, {
"box" : {
"maxclass" : "newobj",
"text" : "gate 1 0",
"patching_rect" : [ 194.0, 455.0, 54.0, 20.0 ],
"numoutlets" : 1,
"fontsize" : 12.0,
"outlettype" : [ "" ],
"id" : "obj-50",
"fontname" : "Arial",
"numinlets" : 2
}
}
, {
"box" : {
"maxclass" : "newobj",
"text" : "sel 65",
"patching_rect" : [ 385.0, 380.0, 43.0, 20.0 ],
"numoutlets" : 2,
"fontsize" : 12.0,
"outlettype" : [ "bang", "" ],
"id" : "obj-48",
"fontname" : "Arial",
"numinlets" : 2
}
}
, {
"box" : {
"maxclass" : "lcd",
"patching_rect" : [ 217.0, 695.0, 256.0, 256.0 ],
"numoutlets" : 4,
"outlettype" : [ "list", "list", "int", "" ],
"id" : "obj-39",
"numinlets" : 1
}
}
, {
"box" : {
"maxclass" : "newobj",
"text" : "t 65 l",
"patching_rect" : [ 194.0, 504.0, 42.0, 21.0 ],
"numoutlets" : 2,
"fontsize" : 12.0,
"outlettype" : [ "int", "" ],
"id" : "obj-35",
"fontname" : "Verdana",
"numinlets" : 1
}
}
, {
"box" : {
"maxclass" : "comment",
"text" : "val3",
"patching_rect" : [ 535.0, 604.0, 37.0, 21.0 ],
"numoutlets" : 0,
"fontsize" : 12.0,
"id" : "obj-1",
"fontname" : "Verdana",
"numinlets" : 1
}
}
, {
"box" : {
"maxclass" : "number",
"patching_rect" : [ 467.0, 604.0, 56.0, 21.0 ],
"numoutlets" : 2,
"fontsize" : 12.0,
"outlettype" : [ "int", "bang" ],
"id" : "obj-3",
"fontname" : "Verdana",
"numinlets" : 1
}
}
, {
"box" : {
"maxclass" : "comment",
"text" : "val2",
"patching_rect" : [ 410.0, 605.0, 37.0, 21.0 ],
"numoutlets" : 0,
"fontsize" : 12.0,
"id" : "obj-18",
"fontname" : "Verdana",
"numinlets" : 1
}
}
, {
"box" : {
"maxclass" : "comment",
"text" : "val1",
"patching_rect" : [ 282.0, 605.0, 37.0, 21.0 ],
"numoutlets" : 0,
"fontsize" : 12.0,
"id" : "obj-20",
"fontname" : "Verdana",
"numinlets" : 1
}
}
, {
"box" : {
"maxclass" : "number",
"patching_rect" : [ 342.0, 605.0, 56.0, 21.0 ],
"numoutlets" : 2,
"fontsize" : 12.0,
"outlettype" : [ "int", "bang" ],
"id" : "obj-22",
"fontname" : "Verdana",
"numinlets" : 1
}
}
, {
"box" : {
"maxclass" : "number",
"patching_rect" : [ 217.0, 605.0, 55.0, 21.0 ],
"numoutlets" : 2,
"fontsize" : 12.0,
"outlettype" : [ "int", "bang" ],
"id" : "obj-23",
"fontname" : "Verdana",
"numinlets" : 1
}
}
, {
"box" : {
"maxclass" : "newobj",
"text" : "unpack 0 0 0",
"patching_rect" : [ 217.0, 570.0, 269.0, 21.0 ],
"numoutlets" : 3,
"fontsize" : 12.0,
"outlettype" : [ "int", "int", "int" ],
"id" : "obj-29",
"fontname" : "Verdana",
"numinlets" : 1
}
}
, {
"box" : {
"maxclass" : "newobj",
"text" : "zl group 3",
"patching_rect" : [ 194.0, 480.0, 71.0, 21.0 ],
"numoutlets" : 2,
"fontsize" : 12.0,
"outlettype" : [ "", "" ],
"id" : "obj-31",
"fontname" : "Verdana",
"numinlets" : 2
}
}
, {
"box" : {
"maxclass" : "newobj",
"text" : "select 0 1",
"patching_rect" : [ 312.0, 200.0, 62.0, 20.0 ],
"numoutlets" : 3,
"fontsize" : 12.0,
"outlettype" : [ "bang", "bang", "" ],
"id" : "obj-30",
"fontname" : "Arial",
"numinlets" : 1
}
}
, {
"box" : {
"maxclass" : "comment",
"text" : "click here to close the serial port",
"patching_rect" : [ 360.0, 291.0, 206.0, 20.0 ],
"numoutlets" : 0,
"fontsize" : 12.0,
"id" : "obj-26",
"fontname" : "Arial",
"numinlets" : 1
}
}
, {
"box" : {
"maxclass" : "comment",
"text" : "click here to open the serial port",
"patching_rect" : [ 385.0, 265.0, 206.0, 20.0 ],
"numoutlets" : 0,
"fontsize" : 12.0,
"id" : "obj-27",
"fontname" : "Arial",
"numinlets" : 1
}
}
, {
"box" : {
"maxclass" : "message",
"text" : "close",
"patching_rect" : [ 312.0, 291.0, 39.0, 18.0 ],
"numoutlets" : 1,
"fontsize" : 12.0,
"outlettype" : [ "" ],
"id" : "obj-21",
"fontname" : "Arial",
"numinlets" : 2
}
}
, {
"box" : {
"maxclass" : "message",
"text" : "port a",
"patching_rect" : [ 334.0, 265.0, 41.0, 18.0 ],
"numoutlets" : 1,
"fontsize" : 12.0,
"outlettype" : [ "" ],
"id" : "obj-19",
"fontname" : "Arial",
"numinlets" : 2
}
}
, {
"box" : {
"maxclass" : "comment",
"text" : "Click here to get a list of serial ports",
"patching_rect" : [ 405.0, 239.0, 207.0, 20.0 ],
"numoutlets" : 0,
"fontsize" : 12.0,
"id" : "obj-2",
"fontname" : "Arial",
"numinlets" : 1
}
}
, {
"box" : {
"maxclass" : "toggle",
"patching_rect" : [ 229.0, 155.0, 22.0, 22.0 ],
"numoutlets" : 1,
"outlettype" : [ "int" ],
"id" : "obj-11",
"numinlets" : 1
}
}
, {
"box" : {
"maxclass" : "newobj",
"text" : "qmetro 10",
"patching_rect" : [ 229.0, 200.0, 65.0, 20.0 ],
"numoutlets" : 1,
"fontsize" : 12.0,
"outlettype" : [ "bang" ],
"id" : "obj-12",
"fontname" : "Arial",
"numinlets" : 2
}
}
, {
"box" : {
"maxclass" : "message",
"text" : "print",
"patching_rect" : [ 354.0, 239.0, 36.0, 18.0 ],
"numoutlets" : 1,
"fontsize" : 12.0,
"outlettype" : [ "" ],
"id" : "obj-13",
"fontname" : "Arial",
"numinlets" : 2
}
}
, {
"box" : {
"maxclass" : "newobj",
"text" : "serial a 9600",
"patching_rect" : [ 229.0, 315.0, 84.0, 20.0 ],
"numoutlets" : 2,
"fontsize" : 12.0,
"outlettype" : [ "int", "" ],
"id" : "obj-14",
"fontname" : "Arial",
"numinlets" : 1
}
}
, {
"box" : {
"maxclass" : "comment",
"text" : "Read serial input buffer every 10 milliseconds",
"linecount" : 2,
"patching_rect" : [ 13.0, 192.0, 210.0, 34.0 ],
"numoutlets" : 0,
"fontsize" : 12.0,
"id" : "obj-15",
"fontname" : "Arial",
"numinlets" : 1
}
}
, {
"box" : {
"maxclass" : "comment",
"text" : "Click to start",
"patching_rect" : [ 256.0, 163.0, 117.0, 20.0 ],
"numoutlets" : 0,
"fontsize" : 12.0,
"id" : "obj-17",
"fontname" : "Arial",
"numinlets" : 1
}
}
],
"lines" : [ {
"patchline" : {
"source" : [ "obj-12", 0 ],
"destination" : [ "obj-14", 0 ],
"hidden" : 0,
"midpoints" : [ ]
}
}
, {
"patchline" : {
"source" : [ "obj-11", 0 ],
"destination" : [ "obj-12", 0 ],
"hidden" : 0,
"midpoints" : [ ]
}
}
, {
"patchline" : {
"source" : [ "obj-13", 0 ],
"destination" : [ "obj-14", 0 ],
"hidden" : 0,
"midpoints" : [ 363.5, 260.5, 238.5, 260.5 ]
}
}
, {
"patchline" : {
"source" : [ "obj-19", 0 ],
"destination" : [ "obj-14", 0 ],
"hidden" : 0,
"midpoints" : [ 343.5, 288.5, 238.5, 288.5 ]
}
}
, {
"patchline" : {
"source" : [ "obj-21", 0 ],
"destination" : [ "obj-14", 0 ],
"hidden" : 0,
"midpoints" : [ 321.5, 311.5, 238.5, 311.5 ]
}
}
, {
"patchline" : {
"source" : [ "obj-30", 0 ],
"destination" : [ "obj-21", 0 ],
"hidden" : 0,
"midpoints" : [ ]
}
}
, {
"patchline" : {
"source" : [ "obj-30", 1 ],
"destination" : [ "obj-19", 0 ],
"hidden" : 0,
"midpoints" : [ ]
}
}
, {
"patchline" : {
"source" : [ "obj-11", 0 ],
"destination" : [ "obj-30", 0 ],
"hidden" : 0,
"midpoints" : [ 238.5, 191.0, 321.5, 191.0 ]
}
}
, {
"patchline" : {
"source" : [ "obj-29", 2 ],
"destination" : [ "obj-3", 0 ],
"hidden" : 0,
"midpoints" : [ ]
}
}
, {
"patchline" : {
"source" : [ "obj-29", 0 ],
"destination" : [ "obj-23", 0 ],
"hidden" : 0,
"midpoints" : [ ]
}
}
, {
"patchline" : {
"source" : [ "obj-29", 1 ],
"destination" : [ "obj-22", 0 ],
"hidden" : 0,
"midpoints" : [ ]
}
}
, {
"patchline" : {
"source" : [ "obj-14", 0 ],
"destination" : [ "obj-50", 1 ],
"hidden" : 0,
"midpoints" : [ ]
}
}
, {
"patchline" : {
"source" : [ "obj-50", 0 ],
"destination" : [ "obj-31", 0 ],
"hidden" : 0,
"midpoints" : [ ]
}
}
, {
"patchline" : {
"source" : [ "obj-48", 0 ],
"destination" : [ "obj-53", 0 ],
"hidden" : 0,
"midpoints" : [ ]
}
}
, {
"patchline" : {
"source" : [ "obj-53", 0 ],
"destination" : [ "obj-50", 0 ],
"hidden" : 0,
"midpoints" : [ 394.5, 426.0, 203.5, 426.0 ]
}
}
, {
"patchline" : {
"source" : [ "obj-14", 0 ],
"destination" : [ "obj-54", 1 ],
"hidden" : 0,
"midpoints" : [ 238.5, 342.0, 429.5, 342.0 ]
}
}
, {
"patchline" : {
"source" : [ "obj-54", 0 ],
"destination" : [ "obj-48", 0 ],
"hidden" : 0,
"midpoints" : [ ]
}
}
, {
"patchline" : {
"source" : [ "obj-62", 0 ],
"destination" : [ "obj-39", 0 ],
"hidden" : 0,
"midpoints" : [ ]
}
}
, {
"patchline" : {
"source" : [ "obj-3", 0 ],
"destination" : [ "obj-62", 2 ],
"hidden" : 0,
"midpoints" : [ ]
}
}
, {
"patchline" : {
"source" : [ "obj-22", 0 ],
"destination" : [ "obj-62", 1 ],
"hidden" : 0,
"midpoints" : [ ]
}
}
, {
"patchline" : {
"source" : [ "obj-23", 0 ],
"destination" : [ "obj-62", 0 ],
"hidden" : 0,
"midpoints" : [ ]
}
}
, {
"patchline" : {
"source" : [ "obj-53", 0 ],
"destination" : [ "obj-55", 0 ],
"hidden" : 0,
"midpoints" : [ ]
}
}
, {
"patchline" : {
"source" : [ "obj-55", 0 ],
"destination" : [ "obj-54", 0 ],
"hidden" : 0,
"midpoints" : [ 394.5, 459.0, 453.0, 459.0, 453.0, 351.0, 394.5, 351.0 ]
}
}
, {
"patchline" : {
"source" : [ "obj-30", 0 ],
"destination" : [ "obj-57", 0 ],
"hidden" : 0,
"midpoints" : [ ]
}
}
, {
"patchline" : {
"source" : [ "obj-57", 0 ],
"destination" : [ "obj-53", 0 ],
"hidden" : 0,
"midpoints" : [ 319.5, 401.0, 394.5, 401.0 ]
}
}
, {
"patchline" : {
"source" : [ "obj-35", 0 ],
"destination" : [ "obj-14", 0 ],
"hidden" : 0,
"midpoints" : [ 203.5, 542.0, 167.0, 542.0, 167.0, 300.0, 238.5, 300.0 ]
}
}
, {
"patchline" : {
"source" : [ "obj-35", 1 ],
"destination" : [ "obj-29", 0 ],
"hidden" : 0,
"midpoints" : [ ]
}
}
, {
"patchline" : {
"source" : [ "obj-31", 0 ],
"destination" : [ "obj-35", 0 ],
"hidden" : 0,
"midpoints" : [ ]
}
}
, {
"patchline" : {
"source" : [ "obj-6", 0 ],
"destination" : [ "obj-9", 0 ],
"hidden" : 0,
"midpoints" : [ ]
}
}
, {
"patchline" : {
"source" : [ "obj-53", 0 ],
"destination" : [ "obj-6", 0 ],
"hidden" : 0,
"midpoints" : [ 394.5, 431.5, 348.5, 431.5 ]
}
}
, {
"patchline" : {
"source" : [ "obj-9", 0 ],
"destination" : [ "obj-14", 0 ],
"hidden" : 0,
"midpoints" : [ ]
}
}
]
}
*/

View File

@ -0,0 +1,1267 @@
/*
Serial Call and Response in ASCII
Language: Wiring/Arduino
This program sends an ASCII A (byte of value 65) on startup
and repeats that until it gets some data in.
Then it waits for a byte in the serial port, and
sends three ASCII-encoded, comma-separated sensor values,
truncated by a linefeed and carriage return,
whenever it gets a byte in.
Thanks to Greg Shakar and Scott Fitzgerald for the improvements
The circuit:
* potentiometers attached to analog inputs 0 and 1
* pushbutton attached to digital I/O 2
http://www.arduino.cc/en/Tutorial/SerialCallResponseASCII
Created 26 Sept. 2005
by Tom Igoe
Modified 14 April 2009
by Tom Igoe and Scott Fitzgerald
*/
int firstSensor = 0; // first analog sensor
int secondSensor = 0; // second analog sensor
int thirdSensor = 0; // digital sensor
int inByte = 0; // incoming serial byte
void setup()
{
// start serial port at 9600 bps:
Serial.begin(9600);
pinMode(2, INPUT); // digital sensor is on digital pin 2
establishContact(); // send a byte to establish contact until receiver responds
}
void loop()
{
// if we get a valid byte, read analog ins:
if (Serial.available() > 0) {
// get incoming byte:
inByte = Serial.read();
// read first analog input, divide by 4 to make the range 0-255:
firstSensor = analogRead(0)/4;
// delay 10ms to let the ADC recover:
delay(10);
// read second analog input, divide by 4 to make the range 0-255:
secondSensor = analogRead(1)/4;
// read switch, map it to 0 or 255L
thirdSensor = map(digitalRead(2), 0, 1, 0, 255);
// send sensor values:
Serial.print(firstSensor, DEC);
Serial.print(",");
Serial.print(secondSensor, DEC);
Serial.print(",");
Serial.println(thirdSensor, DEC);
}
}
void establishContact() {
while (Serial.available() <= 0) {
Serial.println("0,0,0"); // send an initial string
delay(300);
}
}
/*
Processing code to run with this example:
import processing.serial.*; // import the Processing serial library
Serial myPort; // The serial port
float bgcolor; // Background color
float fgcolor; // Fill color
float xpos, ypos; // Starting position of the ball
void setup() {
size(640,480);
// List all the available serial ports
println(Serial.list());
// I know that the first port in the serial list on my mac
// is always my Arduino module, so I open Serial.list()[0].
// Change the 0 to the appropriate number of the serial port
// that your microcontroller is attached to.
myPort = new Serial(this, Serial.list()[0], 9600);
// read bytes into a buffer until you get a linefeed (ASCII 10):
myPort.bufferUntil('\n');
// draw with smooth edges:
smooth();
}
void draw() {
background(bgcolor);
fill(fgcolor);
// Draw the shape
ellipse(xpos, ypos, 20, 20);
}
// serialEvent method is run automatically by the Processing applet
// whenever the buffer reaches the byte value set in the bufferUntil()
// method in the setup():
void serialEvent(Serial myPort) {
// read the serial buffer:
String myString = myPort.readStringUntil('\n');
// if you got any bytes other than the linefeed:
myString = trim(myString);
// split the string at the commas
// and convert the sections into integers:
int sensors[] = int(split(myString, ','));
// print out the values you got:
for (int sensorNum = 0; sensorNum < sensors.length; sensorNum++) {
print("Sensor " + sensorNum + ": " + sensors[sensorNum] + "\t");
}
// add a linefeed after all the sensor values are printed:
println();
if (sensors.length > 1) {
xpos = map(sensors[0], 0,1023,0,width);
ypos = map(sensors[1], 0,1023,0,height);
fgcolor = sensors[2];
}
// send a byte to ask for more data:
myPort.write("A");
}
*/
/*
{
"boxes" : [ {
"box" : {
"maxclass" : "newobj",
"text" : "fromsymbol",
"patching_rect" : [ 265.0, 585.0, 74.0, 20.0 ],
"numoutlets" : 1,
"fontsize" : 12.0,
"outlettype" : [ "" ],
"id" : "obj-7",
"fontname" : "Arial",
"color" : [ 1.0, 0.890196, 0.090196, 1.0 ],
"numinlets" : 1
}
}
, {
"box" : {
"maxclass" : "newobj",
"text" : "itoa",
"patching_rect" : [ 265.0, 562.0, 46.0, 20.0 ],
"numoutlets" : 1,
"fontsize" : 12.0,
"outlettype" : [ "int" ],
"id" : "obj-8",
"fontname" : "Arial",
"color" : [ 1.0, 0.890196, 0.090196, 1.0 ],
"numinlets" : 3
}
}
, {
"box" : {
"maxclass" : "newobj",
"text" : "zl group",
"patching_rect" : [ 265.0, 539.0, 53.0, 20.0 ],
"numoutlets" : 2,
"fontsize" : 12.0,
"outlettype" : [ "", "" ],
"id" : "obj-4",
"fontname" : "Arial",
"numinlets" : 2
}
}
, {
"box" : {
"maxclass" : "newobj",
"text" : "select 10 13",
"patching_rect" : [ 209.0, 501.0, 75.0, 20.0 ],
"numoutlets" : 3,
"fontsize" : 12.0,
"outlettype" : [ "bang", "bang", "" ],
"id" : "obj-10",
"fontname" : "Arial",
"numinlets" : 1
}
}
, {
"box" : {
"maxclass" : "message",
"text" : "65",
"patching_rect" : [ 354.0, 481.0, 32.5, 18.0 ],
"numoutlets" : 1,
"fontsize" : 12.0,
"outlettype" : [ "" ],
"id" : "obj-9",
"fontname" : "Arial",
"numinlets" : 2
}
}
, {
"box" : {
"maxclass" : "newobj",
"text" : "sel 1",
"patching_rect" : [ 354.0, 452.0, 36.0, 20.0 ],
"numoutlets" : 2,
"fontsize" : 12.0,
"outlettype" : [ "bang", "" ],
"id" : "obj-6",
"fontname" : "Arial",
"numinlets" : 2
}
}
, {
"box" : {
"maxclass" : "comment",
"text" : "Serial Call-Response ASCII \n\nSends a byte out the serial port, and reads 3 ASCII enoded, comma separated in, truncated by a linefeed. It then sets foregound color, xpos, and ypos of a circle using the values returned from the serial port. \n\nNote: This patch assumes that the device on the other end of the serial port is going to send a single byte of value 65 (ASCII A) on startup. The sketch waits for that byte, then sends an ASCII A whenever it wants more data. \n\ncreated 14 Apr 2009\nby Scott Fitzgerald and Tom Igoe",
"linecount" : 12,
"patching_rect" : [ 401.0, 67.0, 540.0, 172.0 ],
"numoutlets" : 0,
"fontsize" : 12.0,
"id" : "obj-5",
"fontname" : "Arial",
"numinlets" : 1
}
}
, {
"box" : {
"maxclass" : "comment",
"text" : "trigger (or [t]) forces right-left conventions. All the drawing and processing will happen before Max requests new values. When this trigger fires, it sends an ASCII A to ask Arduino for new values.",
"linecount" : 3,
"patching_rect" : [ 254.0, 625.0, 425.0, 48.0 ],
"numoutlets" : 0,
"fontsize" : 12.0,
"id" : "obj-65",
"fontname" : "Arial",
"numinlets" : 1
}
}
, {
"box" : {
"maxclass" : "comment",
"text" : "reinitializes the gates when turned on and off",
"linecount" : 2,
"patching_rect" : [ 185.0, 385.0, 135.0, 34.0 ],
"numoutlets" : 0,
"fontsize" : 12.0,
"id" : "obj-64",
"fontname" : "Arial",
"numinlets" : 1
}
}
, {
"box" : {
"maxclass" : "comment",
"text" : "checks for the ascii value of newline to begin communication. After initial communication is made, this block shuts down.",
"linecount" : 3,
"patching_rect" : [ 475.0, 370.0, 252.0, 48.0 ],
"numoutlets" : 0,
"fontsize" : 12.0,
"id" : "obj-63",
"fontname" : "Arial",
"numinlets" : 1
}
}
, {
"box" : {
"maxclass" : "newobj",
"text" : "p \"draw the circle\"",
"patching_rect" : [ 232.0, 765.0, 269.0, 19.0 ],
"numoutlets" : 1,
"fontsize" : 10.0,
"outlettype" : [ "" ],
"id" : "obj-62",
"fontname" : "Verdana",
"numinlets" : 3,
"patcher" : {
"fileversion" : 1,
"rect" : [ 54.0, 94.0, 640.0, 480.0 ],
"bglocked" : 0,
"defrect" : [ 54.0, 94.0, 640.0, 480.0 ],
"openrect" : [ 0.0, 0.0, 0.0, 0.0 ],
"openinpresentation" : 0,
"default_fontsize" : 10.0,
"default_fontface" : 0,
"default_fontname" : "Verdana",
"gridonopen" : 0,
"gridsize" : [ 25.0, 25.0 ],
"gridsnaponopen" : 0,
"toolbarvisible" : 1,
"boxanimatetime" : 200,
"imprint" : 0,
"boxes" : [ {
"box" : {
"maxclass" : "message",
"text" : "frgb 255 255 255",
"patching_rect" : [ 375.0, 150.0, 98.0, 18.0 ],
"numoutlets" : 1,
"fontsize" : 11.595187,
"outlettype" : [ "" ],
"id" : "obj-47",
"fontname" : "Arial",
"numinlets" : 2
}
}
, {
"box" : {
"maxclass" : "message",
"text" : "frgb 0 0 0",
"patching_rect" : [ 275.0, 125.0, 59.0, 18.0 ],
"numoutlets" : 1,
"fontsize" : 11.595187,
"outlettype" : [ "" ],
"id" : "obj-46",
"fontname" : "Arial",
"numinlets" : 2
}
}
, {
"box" : {
"maxclass" : "newobj",
"text" : "sel 255 0",
"patching_rect" : [ 300.0, 100.0, 66.0, 21.0 ],
"numoutlets" : 3,
"fontsize" : 12.0,
"outlettype" : [ "bang", "bang", "" ],
"id" : "obj-45",
"fontname" : "Verdana",
"numinlets" : 1
}
}
, {
"box" : {
"maxclass" : "newobj",
"text" : "pack 0 0 0 0",
"patching_rect" : [ 50.0, 125.0, 180.0, 21.0 ],
"numoutlets" : 1,
"fontsize" : 12.0,
"outlettype" : [ "" ],
"id" : "obj-43",
"fontname" : "Verdana",
"numinlets" : 4
}
}
, {
"box" : {
"maxclass" : "newobj",
"text" : "+ 10",
"patching_rect" : [ 200.0, 100.0, 40.0, 21.0 ],
"numoutlets" : 1,
"fontsize" : 12.0,
"outlettype" : [ "int" ],
"id" : "obj-42",
"fontname" : "Verdana",
"numinlets" : 2
}
}
, {
"box" : {
"maxclass" : "newobj",
"text" : "+ 10",
"patching_rect" : [ 75.0, 100.0, 40.0, 21.0 ],
"numoutlets" : 1,
"fontsize" : 12.0,
"outlettype" : [ "int" ],
"id" : "obj-41",
"fontname" : "Verdana",
"numinlets" : 2
}
}
, {
"box" : {
"maxclass" : "message",
"text" : "clear, paintoval $1 $2 $3 $4",
"patching_rect" : [ 50.0, 150.0, 152.0, 18.0 ],
"numoutlets" : 1,
"fontsize" : 11.595187,
"outlettype" : [ "" ],
"id" : "obj-40",
"fontname" : "Arial",
"numinlets" : 2
}
}
, {
"box" : {
"maxclass" : "inlet",
"patching_rect" : [ 57.5, 40.0, 25.0, 25.0 ],
"numoutlets" : 1,
"outlettype" : [ "int" ],
"id" : "obj-58",
"numinlets" : 0,
"comment" : ""
}
}
, {
"box" : {
"maxclass" : "inlet",
"patching_rect" : [ 120.0, 40.0, 25.0, 25.0 ],
"numoutlets" : 1,
"outlettype" : [ "int" ],
"id" : "obj-59",
"numinlets" : 0,
"comment" : ""
}
}
, {
"box" : {
"maxclass" : "inlet",
"patching_rect" : [ 300.0, 40.0, 25.0, 25.0 ],
"numoutlets" : 1,
"outlettype" : [ "int" ],
"id" : "obj-60",
"numinlets" : 0,
"comment" : ""
}
}
, {
"box" : {
"maxclass" : "outlet",
"patching_rect" : [ 228.333344, 228.0, 25.0, 25.0 ],
"numoutlets" : 0,
"id" : "obj-61",
"numinlets" : 1,
"comment" : ""
}
}
],
"lines" : [ {
"patchline" : {
"source" : [ "obj-43", 0 ],
"destination" : [ "obj-40", 0 ],
"hidden" : 0,
"midpoints" : [ ]
}
}
, {
"patchline" : {
"source" : [ "obj-45", 0 ],
"destination" : [ "obj-46", 0 ],
"hidden" : 0,
"midpoints" : [ ]
}
}
, {
"patchline" : {
"source" : [ "obj-45", 1 ],
"destination" : [ "obj-47", 0 ],
"hidden" : 0,
"midpoints" : [ ]
}
}
, {
"patchline" : {
"source" : [ "obj-41", 0 ],
"destination" : [ "obj-43", 2 ],
"hidden" : 0,
"midpoints" : [ ]
}
}
, {
"patchline" : {
"source" : [ "obj-42", 0 ],
"destination" : [ "obj-43", 3 ],
"hidden" : 0,
"midpoints" : [ ]
}
}
, {
"patchline" : {
"source" : [ "obj-58", 0 ],
"destination" : [ "obj-43", 0 ],
"hidden" : 0,
"midpoints" : [ ]
}
}
, {
"patchline" : {
"source" : [ "obj-58", 0 ],
"destination" : [ "obj-41", 0 ],
"hidden" : 0,
"midpoints" : [ ]
}
}
, {
"patchline" : {
"source" : [ "obj-59", 0 ],
"destination" : [ "obj-43", 1 ],
"hidden" : 0,
"midpoints" : [ ]
}
}
, {
"patchline" : {
"source" : [ "obj-59", 0 ],
"destination" : [ "obj-42", 0 ],
"hidden" : 0,
"midpoints" : [ ]
}
}
, {
"patchline" : {
"source" : [ "obj-60", 0 ],
"destination" : [ "obj-45", 0 ],
"hidden" : 0,
"midpoints" : [ ]
}
}
, {
"patchline" : {
"source" : [ "obj-40", 0 ],
"destination" : [ "obj-61", 0 ],
"hidden" : 0,
"midpoints" : [ ]
}
}
, {
"patchline" : {
"source" : [ "obj-46", 0 ],
"destination" : [ "obj-61", 0 ],
"hidden" : 0,
"midpoints" : [ ]
}
}
, {
"patchline" : {
"source" : [ "obj-47", 0 ],
"destination" : [ "obj-61", 0 ],
"hidden" : 0,
"midpoints" : [ ]
}
}
]
}
,
"saved_object_attributes" : {
"fontface" : 0,
"fontsize" : 10.0,
"default_fontface" : 0,
"default_fontname" : "Verdana",
"default_fontsize" : 10.0,
"fontname" : "Verdana",
"globalpatchername" : ""
}
}
}
, {
"box" : {
"maxclass" : "newobj",
"text" : "0",
"patching_rect" : [ 325.0, 393.0, 32.5, 20.0 ],
"numoutlets" : 1,
"fontsize" : 12.0,
"outlettype" : [ "int" ],
"id" : "obj-57",
"fontname" : "Arial",
"numinlets" : 2
}
}
, {
"box" : {
"maxclass" : "newobj",
"text" : "!- 1",
"patching_rect" : [ 400.0, 451.0, 32.5, 20.0 ],
"numoutlets" : 1,
"fontsize" : 12.0,
"outlettype" : [ "int" ],
"id" : "obj-55",
"fontname" : "Arial",
"numinlets" : 2
}
}
, {
"box" : {
"maxclass" : "newobj",
"text" : "gate 1 1",
"patching_rect" : [ 400.0, 370.0, 54.0, 20.0 ],
"numoutlets" : 1,
"fontsize" : 12.0,
"outlettype" : [ "" ],
"id" : "obj-54",
"fontname" : "Arial",
"numinlets" : 2
}
}
, {
"box" : {
"maxclass" : "toggle",
"patching_rect" : [ 400.0, 420.0, 20.0, 20.0 ],
"numoutlets" : 1,
"outlettype" : [ "int" ],
"id" : "obj-53",
"numinlets" : 1
}
}
, {
"box" : {
"maxclass" : "newobj",
"text" : "gate 1 0",
"patching_rect" : [ 209.0, 470.0, 54.0, 20.0 ],
"numoutlets" : 1,
"fontsize" : 12.0,
"outlettype" : [ "" ],
"id" : "obj-50",
"fontname" : "Arial",
"numinlets" : 2
}
}
, {
"box" : {
"maxclass" : "newobj",
"text" : "sel 10",
"patching_rect" : [ 400.0, 393.0, 43.0, 20.0 ],
"numoutlets" : 2,
"fontsize" : 12.0,
"outlettype" : [ "bang", "" ],
"id" : "obj-48",
"fontname" : "Arial",
"numinlets" : 2
}
}
, {
"box" : {
"maxclass" : "lcd",
"patching_rect" : [ 232.0, 815.0, 256.0, 256.0 ],
"numoutlets" : 4,
"outlettype" : [ "list", "list", "int", "" ],
"id" : "obj-39",
"numinlets" : 1
}
}
, {
"box" : {
"maxclass" : "newobj",
"text" : "t 65 l",
"patching_rect" : [ 209.0, 624.0, 42.0, 21.0 ],
"numoutlets" : 2,
"fontsize" : 12.0,
"outlettype" : [ "int", "" ],
"id" : "obj-35",
"fontname" : "Verdana",
"numinlets" : 1
}
}
, {
"box" : {
"maxclass" : "comment",
"text" : "val3",
"patching_rect" : [ 553.0, 725.0, 37.0, 21.0 ],
"numoutlets" : 0,
"fontsize" : 12.0,
"id" : "obj-1",
"fontname" : "Verdana",
"numinlets" : 1
}
}
, {
"box" : {
"maxclass" : "number",
"patching_rect" : [ 482.0, 725.0, 56.0, 21.0 ],
"numoutlets" : 2,
"fontsize" : 12.0,
"outlettype" : [ "int", "bang" ],
"id" : "obj-3",
"fontname" : "Verdana",
"numinlets" : 1
}
}
, {
"box" : {
"maxclass" : "comment",
"text" : "val2",
"patching_rect" : [ 425.0, 725.0, 37.0, 21.0 ],
"numoutlets" : 0,
"fontsize" : 12.0,
"id" : "obj-18",
"fontname" : "Verdana",
"numinlets" : 1
}
}
, {
"box" : {
"maxclass" : "comment",
"text" : "val1",
"patching_rect" : [ 297.0, 725.0, 37.0, 21.0 ],
"numoutlets" : 0,
"fontsize" : 12.0,
"id" : "obj-20",
"fontname" : "Verdana",
"numinlets" : 1
}
}
, {
"box" : {
"maxclass" : "number",
"patching_rect" : [ 357.0, 725.0, 56.0, 21.0 ],
"numoutlets" : 2,
"fontsize" : 12.0,
"outlettype" : [ "int", "bang" ],
"id" : "obj-22",
"fontname" : "Verdana",
"numinlets" : 1
}
}
, {
"box" : {
"maxclass" : "number",
"patching_rect" : [ 232.0, 725.0, 55.0, 21.0 ],
"numoutlets" : 2,
"fontsize" : 12.0,
"outlettype" : [ "int", "bang" ],
"id" : "obj-23",
"fontname" : "Verdana",
"numinlets" : 1
}
}
, {
"box" : {
"maxclass" : "newobj",
"text" : "unpack 0 0 0 0 0",
"patching_rect" : [ 232.0, 690.0, 269.0, 21.0 ],
"numoutlets" : 5,
"fontsize" : 12.0,
"outlettype" : [ "int", "int", "int", "int", "int" ],
"id" : "obj-29",
"fontname" : "Verdana",
"numinlets" : 1
}
}
, {
"box" : {
"maxclass" : "newobj",
"text" : "select 0 1",
"patching_rect" : [ 327.0, 215.0, 62.0, 20.0 ],
"numoutlets" : 3,
"fontsize" : 12.0,
"outlettype" : [ "bang", "bang", "" ],
"id" : "obj-30",
"fontname" : "Arial",
"numinlets" : 1
}
}
, {
"box" : {
"maxclass" : "comment",
"text" : "click here to close the serial port",
"patching_rect" : [ 375.0, 306.0, 206.0, 20.0 ],
"numoutlets" : 0,
"fontsize" : 12.0,
"id" : "obj-26",
"fontname" : "Arial",
"numinlets" : 1
}
}
, {
"box" : {
"maxclass" : "comment",
"text" : "click here to open the serial port",
"patching_rect" : [ 400.0, 280.0, 206.0, 20.0 ],
"numoutlets" : 0,
"fontsize" : 12.0,
"id" : "obj-27",
"fontname" : "Arial",
"numinlets" : 1
}
}
, {
"box" : {
"maxclass" : "message",
"text" : "close",
"patching_rect" : [ 327.0, 306.0, 39.0, 18.0 ],
"numoutlets" : 1,
"fontsize" : 12.0,
"outlettype" : [ "" ],
"id" : "obj-21",
"fontname" : "Arial",
"numinlets" : 2
}
}
, {
"box" : {
"maxclass" : "message",
"text" : "port a",
"patching_rect" : [ 349.0, 280.0, 41.0, 18.0 ],
"numoutlets" : 1,
"fontsize" : 12.0,
"outlettype" : [ "" ],
"id" : "obj-19",
"fontname" : "Arial",
"numinlets" : 2
}
}
, {
"box" : {
"maxclass" : "comment",
"text" : "Click here to get a list of serial ports",
"patching_rect" : [ 420.0, 254.0, 207.0, 20.0 ],
"numoutlets" : 0,
"fontsize" : 12.0,
"id" : "obj-2",
"fontname" : "Arial",
"numinlets" : 1
}
}
, {
"box" : {
"maxclass" : "toggle",
"patching_rect" : [ 244.0, 170.0, 22.0, 22.0 ],
"numoutlets" : 1,
"outlettype" : [ "int" ],
"id" : "obj-11",
"numinlets" : 1
}
}
, {
"box" : {
"maxclass" : "newobj",
"text" : "qmetro 10",
"patching_rect" : [ 244.0, 215.0, 65.0, 20.0 ],
"numoutlets" : 1,
"fontsize" : 12.0,
"outlettype" : [ "bang" ],
"id" : "obj-12",
"fontname" : "Arial",
"numinlets" : 2
}
}
, {
"box" : {
"maxclass" : "message",
"text" : "print",
"patching_rect" : [ 369.0, 254.0, 36.0, 18.0 ],
"numoutlets" : 1,
"fontsize" : 12.0,
"outlettype" : [ "" ],
"id" : "obj-13",
"fontname" : "Arial",
"numinlets" : 2
}
}
, {
"box" : {
"maxclass" : "newobj",
"text" : "serial a 9600",
"patching_rect" : [ 244.0, 330.0, 84.0, 20.0 ],
"numoutlets" : 2,
"fontsize" : 12.0,
"outlettype" : [ "int", "" ],
"id" : "obj-14",
"fontname" : "Arial",
"numinlets" : 1
}
}
, {
"box" : {
"maxclass" : "comment",
"text" : "Read serial input buffer every 10 milliseconds",
"linecount" : 2,
"patching_rect" : [ 28.0, 207.0, 210.0, 34.0 ],
"numoutlets" : 0,
"fontsize" : 12.0,
"id" : "obj-15",
"fontname" : "Arial",
"numinlets" : 1
}
}
, {
"box" : {
"maxclass" : "comment",
"text" : "Click to start",
"patching_rect" : [ 271.0, 178.0, 117.0, 20.0 ],
"numoutlets" : 0,
"fontsize" : 12.0,
"id" : "obj-17",
"fontname" : "Arial",
"numinlets" : 1
}
}
],
"lines" : [ {
"patchline" : {
"source" : [ "obj-54", 0 ],
"destination" : [ "obj-48", 0 ],
"hidden" : 0,
"midpoints" : [ ]
}
}
, {
"patchline" : {
"source" : [ "obj-48", 0 ],
"destination" : [ "obj-53", 0 ],
"hidden" : 0,
"midpoints" : [ ]
}
}
, {
"patchline" : {
"source" : [ "obj-9", 0 ],
"destination" : [ "obj-14", 0 ],
"hidden" : 0,
"midpoints" : [ ]
}
}
, {
"patchline" : {
"source" : [ "obj-53", 0 ],
"destination" : [ "obj-6", 0 ],
"hidden" : 0,
"midpoints" : [ 409.5, 446.5, 363.5, 446.5 ]
}
}
, {
"patchline" : {
"source" : [ "obj-6", 0 ],
"destination" : [ "obj-9", 0 ],
"hidden" : 0,
"midpoints" : [ ]
}
}
, {
"patchline" : {
"source" : [ "obj-35", 0 ],
"destination" : [ "obj-14", 0 ],
"hidden" : 0,
"midpoints" : [ 218.5, 656.0, 182.0, 656.0, 182.0, 315.0, 253.5, 315.0 ]
}
}
, {
"patchline" : {
"source" : [ "obj-57", 0 ],
"destination" : [ "obj-53", 0 ],
"hidden" : 0,
"midpoints" : [ 334.5, 416.0, 409.5, 416.0 ]
}
}
, {
"patchline" : {
"source" : [ "obj-30", 0 ],
"destination" : [ "obj-57", 0 ],
"hidden" : 0,
"midpoints" : [ ]
}
}
, {
"patchline" : {
"source" : [ "obj-55", 0 ],
"destination" : [ "obj-54", 0 ],
"hidden" : 0,
"midpoints" : [ 409.5, 474.0, 468.0, 474.0, 468.0, 366.0, 409.5, 366.0 ]
}
}
, {
"patchline" : {
"source" : [ "obj-53", 0 ],
"destination" : [ "obj-55", 0 ],
"hidden" : 0,
"midpoints" : [ ]
}
}
, {
"patchline" : {
"source" : [ "obj-23", 0 ],
"destination" : [ "obj-62", 0 ],
"hidden" : 0,
"midpoints" : [ ]
}
}
, {
"patchline" : {
"source" : [ "obj-22", 0 ],
"destination" : [ "obj-62", 1 ],
"hidden" : 0,
"midpoints" : [ ]
}
}
, {
"patchline" : {
"source" : [ "obj-3", 0 ],
"destination" : [ "obj-62", 2 ],
"hidden" : 0,
"midpoints" : [ ]
}
}
, {
"patchline" : {
"source" : [ "obj-62", 0 ],
"destination" : [ "obj-39", 0 ],
"hidden" : 0,
"midpoints" : [ ]
}
}
, {
"patchline" : {
"source" : [ "obj-14", 0 ],
"destination" : [ "obj-54", 1 ],
"hidden" : 0,
"midpoints" : [ 253.5, 357.0, 444.5, 357.0 ]
}
}
, {
"patchline" : {
"source" : [ "obj-53", 0 ],
"destination" : [ "obj-50", 0 ],
"hidden" : 0,
"midpoints" : [ 409.5, 441.0, 218.5, 441.0 ]
}
}
, {
"patchline" : {
"source" : [ "obj-14", 0 ],
"destination" : [ "obj-50", 1 ],
"hidden" : 0,
"midpoints" : [ ]
}
}
, {
"patchline" : {
"source" : [ "obj-11", 0 ],
"destination" : [ "obj-30", 0 ],
"hidden" : 0,
"midpoints" : [ 253.5, 206.0, 336.5, 206.0 ]
}
}
, {
"patchline" : {
"source" : [ "obj-30", 1 ],
"destination" : [ "obj-19", 0 ],
"hidden" : 0,
"midpoints" : [ ]
}
}
, {
"patchline" : {
"source" : [ "obj-30", 0 ],
"destination" : [ "obj-21", 0 ],
"hidden" : 0,
"midpoints" : [ ]
}
}
, {
"patchline" : {
"source" : [ "obj-21", 0 ],
"destination" : [ "obj-14", 0 ],
"hidden" : 0,
"midpoints" : [ 336.5, 326.5, 253.5, 326.5 ]
}
}
, {
"patchline" : {
"source" : [ "obj-19", 0 ],
"destination" : [ "obj-14", 0 ],
"hidden" : 0,
"midpoints" : [ 358.5, 303.5, 253.5, 303.5 ]
}
}
, {
"patchline" : {
"source" : [ "obj-13", 0 ],
"destination" : [ "obj-14", 0 ],
"hidden" : 0,
"midpoints" : [ 378.5, 275.5, 253.5, 275.5 ]
}
}
, {
"patchline" : {
"source" : [ "obj-11", 0 ],
"destination" : [ "obj-12", 0 ],
"hidden" : 0,
"midpoints" : [ ]
}
}
, {
"patchline" : {
"source" : [ "obj-12", 0 ],
"destination" : [ "obj-14", 0 ],
"hidden" : 0,
"midpoints" : [ ]
}
}
, {
"patchline" : {
"source" : [ "obj-10", 2 ],
"destination" : [ "obj-4", 0 ],
"hidden" : 0,
"midpoints" : [ 274.5, 542.0, 274.5, 542.0 ]
}
}
, {
"patchline" : {
"source" : [ "obj-10", 0 ],
"destination" : [ "obj-4", 0 ],
"hidden" : 0,
"midpoints" : [ 218.5, 529.5, 274.5, 529.5 ]
}
}
, {
"patchline" : {
"source" : [ "obj-4", 0 ],
"destination" : [ "obj-8", 0 ],
"hidden" : 0,
"midpoints" : [ ]
}
}
, {
"patchline" : {
"source" : [ "obj-8", 0 ],
"destination" : [ "obj-7", 0 ],
"hidden" : 0,
"midpoints" : [ ]
}
}
, {
"patchline" : {
"source" : [ "obj-7", 0 ],
"destination" : [ "obj-35", 0 ],
"hidden" : 0,
"midpoints" : [ 274.5, 614.0, 218.5, 614.0 ]
}
}
, {
"patchline" : {
"source" : [ "obj-50", 0 ],
"destination" : [ "obj-10", 0 ],
"hidden" : 0,
"midpoints" : [ ]
}
}
, {
"patchline" : {
"source" : [ "obj-29", 0 ],
"destination" : [ "obj-23", 0 ],
"hidden" : 0,
"midpoints" : [ ]
}
}
, {
"patchline" : {
"source" : [ "obj-35", 1 ],
"destination" : [ "obj-29", 0 ],
"hidden" : 0,
"midpoints" : [ ]
}
}
, {
"patchline" : {
"source" : [ "obj-29", 4 ],
"destination" : [ "obj-3", 0 ],
"hidden" : 0,
"midpoints" : [ ]
}
}
, {
"patchline" : {
"source" : [ "obj-29", 2 ],
"destination" : [ "obj-22", 0 ],
"hidden" : 0,
"midpoints" : [ ]
}
}
]
}
*/

View File

@ -0,0 +1,697 @@
/*
This example reads three analog sensors (potentiometers are easiest)
and sends their values serially. The Processing and Max/MSP programs at the bottom
take those three values and use them to change the background color of the screen.
The circuit:
* potentiometers attached to analog inputs 0, 1, and 2
http://www.arduino.cc/en/Tutorial/VirtualColorMixer
created 2 Dec 2006
by David A. Mellis
modified 14 Apr 2009
by Tom Igoe and Scott Fitzgerald
*/
const int redPin = 0; // sensor to control red color
const int greenPin = 1; // sensor to control green color
const int bluePin = 2; // sensor to control blue color
void setup()
{
Serial.begin(9600);
}
void loop()
{
Serial.print(analogRead(redPin));
Serial.print(",");
Serial.print(analogRead(greenPin));
Serial.print(",");
Serial.println(analogRead(bluePin));
}
/* Processing code for this example
import processing.serial.*;
float redValue = 0; // red value
float greenValue = 0; // green value
float blueValue = 0; // blue value
Serial myPort;
void setup() {
size(200, 200);
// List all the available serial ports
println(Serial.list());
// I know that the first port in the serial list on my mac
// is always my Arduino, so I open Serial.list()[0].
// Open whatever port is the one you're using.
myPort = new Serial(this, Serial.list()[0], 9600);
// don't generate a serialEvent() unless you get a newline character:
myPort.bufferUntil('\n');
}
void draw() {
// set the background color with the color values:
background(redValue, greenValue, blueValue);
}
void serialEvent(Serial myPort) {
// get the ASCII string:
String inString = myPort.readStringUntil('\n');
if (inString != null) {
// trim off any whitespace:
inString = trim(inString);
// split the string on the commas and convert the
// resulting substrings into an integer array:
float[] colors = float(split(inString, ","));
// if the array has at least three elements, you know
// you got the whole thing. Put the numbers in the
// color variables:
if (colors.length >=3) {
// map them to the range 0-255:
redValue = map(colors[0], 0, 1023, 0, 255);
greenValue = map(colors[1], 0, 1023, 0, 255);
blueValue = map(colors[2], 0, 1023, 0, 255);
}
}
}
*/
/* Max/MSP patch for this example
{
"boxes" : [ {
"box" : {
"maxclass" : "newobj",
"text" : "/ 4",
"patching_rect" : [ 448.0, 502.0, 32.5, 20.0 ],
"numoutlets" : 1,
"fontsize" : 12.0,
"outlettype" : [ "int" ],
"id" : "obj-25",
"fontname" : "Arial",
"numinlets" : 2
}
}
, {
"box" : {
"maxclass" : "newobj",
"text" : "/ 4",
"patching_rect" : [ 398.0, 502.0, 32.5, 20.0 ],
"numoutlets" : 1,
"fontsize" : 12.0,
"outlettype" : [ "int" ],
"id" : "obj-24",
"fontname" : "Arial",
"numinlets" : 2
}
}
, {
"box" : {
"maxclass" : "newobj",
"text" : "/ 4",
"patching_rect" : [ 348.0, 502.0, 32.5, 20.0 ],
"numoutlets" : 1,
"fontsize" : 12.0,
"outlettype" : [ "int" ],
"id" : "obj-23",
"fontname" : "Arial",
"numinlets" : 2
}
}
, {
"box" : {
"maxclass" : "comment",
"text" : "Virtual color mixer\n\nThis patch takes a string, containing three comma-separated ASCII formatted numbers from 0 to 1023, with a carriage return and linefeed at the end. It converts the string to three integers and uses them to set the background color.\n\n created 2 Dec 2006\n by David A. Mellis\nmodified 14 Apr 2009\nby Scott Fitzgerald and Tom Igoe",
"linecount" : 11,
"patching_rect" : [ 524.0, 51.0, 398.0, 158.0 ],
"numoutlets" : 0,
"fontsize" : 12.0,
"id" : "obj-32",
"fontname" : "Arial",
"numinlets" : 1
}
}
, {
"box" : {
"maxclass" : "newobj",
"text" : "select 0 1",
"patching_rect" : [ 372.0, 125.0, 62.0, 20.0 ],
"numoutlets" : 3,
"fontsize" : 12.0,
"outlettype" : [ "bang", "bang", "" ],
"id" : "obj-30",
"fontname" : "Arial",
"numinlets" : 1
}
}
, {
"box" : {
"maxclass" : "comment",
"text" : "click here to close the serial port",
"patching_rect" : [ 457.0, 276.0, 206.0, 20.0 ],
"numoutlets" : 0,
"fontsize" : 12.0,
"id" : "obj-26",
"fontname" : "Arial",
"numinlets" : 1
}
}
, {
"box" : {
"maxclass" : "comment",
"text" : "click here to open the serial port",
"patching_rect" : [ 457.0, 250.0, 206.0, 20.0 ],
"numoutlets" : 0,
"fontsize" : 12.0,
"id" : "obj-27",
"fontname" : "Arial",
"numinlets" : 1
}
}
, {
"box" : {
"maxclass" : "message",
"text" : "close",
"patching_rect" : [ 372.0, 276.0, 39.0, 18.0 ],
"numoutlets" : 1,
"fontsize" : 12.0,
"outlettype" : [ "" ],
"id" : "obj-21",
"fontname" : "Arial",
"numinlets" : 2
}
}
, {
"box" : {
"maxclass" : "message",
"text" : "port a",
"patching_rect" : [ 394.0, 250.0, 41.0, 18.0 ],
"numoutlets" : 1,
"fontsize" : 12.0,
"outlettype" : [ "" ],
"id" : "obj-19",
"fontname" : "Arial",
"numinlets" : 2
}
}
, {
"box" : {
"maxclass" : "comment",
"text" : "Click here to get a list of serial ports",
"patching_rect" : [ 457.0, 224.0, 207.0, 20.0 ],
"numoutlets" : 0,
"fontsize" : 12.0,
"id" : "obj-2",
"fontname" : "Arial",
"numinlets" : 1
}
}
, {
"box" : {
"maxclass" : "comment",
"text" : "Convert ASCII to symbol",
"patching_rect" : [ 424.0, 423.0, 147.0, 20.0 ],
"numoutlets" : 0,
"fontsize" : 12.0,
"id" : "obj-4",
"fontname" : "Arial",
"numinlets" : 1
}
}
, {
"box" : {
"maxclass" : "comment",
"text" : "Convert integer to ASCII",
"patching_rect" : [ 424.0, 400.0, 147.0, 20.0 ],
"numoutlets" : 0,
"fontsize" : 12.0,
"id" : "obj-5",
"fontname" : "Arial",
"numinlets" : 1
}
}
, {
"box" : {
"maxclass" : "newobj",
"text" : "fromsymbol",
"patching_rect" : [ 347.0, 423.0, 74.0, 20.0 ],
"numoutlets" : 1,
"fontsize" : 12.0,
"outlettype" : [ "" ],
"id" : "obj-7",
"fontname" : "Arial",
"color" : [ 1.0, 0.890196, 0.090196, 1.0 ],
"numinlets" : 1
}
}
, {
"box" : {
"maxclass" : "newobj",
"text" : "itoa",
"patching_rect" : [ 347.0, 400.0, 46.0, 20.0 ],
"numoutlets" : 1,
"fontsize" : 12.0,
"outlettype" : [ "int" ],
"id" : "obj-8",
"fontname" : "Arial",
"color" : [ 1.0, 0.890196, 0.090196, 1.0 ],
"numinlets" : 3
}
}
, {
"box" : {
"maxclass" : "newobj",
"text" : "zl group",
"patching_rect" : [ 347.0, 377.0, 53.0, 20.0 ],
"numoutlets" : 2,
"fontsize" : 12.0,
"outlettype" : [ "", "" ],
"id" : "obj-9",
"fontname" : "Arial",
"numinlets" : 2
}
}
, {
"box" : {
"maxclass" : "newobj",
"text" : "select 10 13",
"patching_rect" : [ 289.0, 326.0, 77.0, 20.0 ],
"numoutlets" : 3,
"fontsize" : 12.0,
"outlettype" : [ "bang", "bang", "" ],
"id" : "obj-10",
"fontname" : "Arial",
"numinlets" : 1
}
}
, {
"box" : {
"maxclass" : "toggle",
"patching_rect" : [ 289.0, 88.0, 15.0, 15.0 ],
"numoutlets" : 1,
"outlettype" : [ "int" ],
"id" : "obj-11",
"numinlets" : 1
}
}
, {
"box" : {
"maxclass" : "newobj",
"text" : "qmetro 10",
"patching_rect" : [ 289.0, 125.0, 65.0, 20.0 ],
"numoutlets" : 1,
"fontsize" : 12.0,
"outlettype" : [ "bang" ],
"id" : "obj-12",
"fontname" : "Arial",
"numinlets" : 2
}
}
, {
"box" : {
"maxclass" : "message",
"text" : "print",
"patching_rect" : [ 414.0, 224.0, 36.0, 18.0 ],
"numoutlets" : 1,
"fontsize" : 12.0,
"outlettype" : [ "" ],
"id" : "obj-13",
"fontname" : "Arial",
"numinlets" : 2
}
}
, {
"box" : {
"maxclass" : "newobj",
"text" : "serial a 9600",
"patching_rect" : [ 289.0, 300.0, 84.0, 20.0 ],
"numoutlets" : 2,
"fontsize" : 12.0,
"outlettype" : [ "int", "" ],
"id" : "obj-14",
"fontname" : "Arial",
"numinlets" : 1
}
}
, {
"box" : {
"maxclass" : "comment",
"text" : "Read serial input buffer every 10 milliseconds",
"linecount" : 2,
"patching_rect" : [ 98.0, 117.0, 185.0, 34.0 ],
"numoutlets" : 0,
"fontsize" : 12.0,
"id" : "obj-15",
"fontname" : "Arial",
"numinlets" : 1
}
}
, {
"box" : {
"maxclass" : "comment",
"text" : "If you get newline (ASCII 10), send the list. If you get return (ASCII 13) do nothing. Any other value, add to the list",
"linecount" : 3,
"patching_rect" : [ 377.0, 314.0, 320.0, 48.0 ],
"numoutlets" : 0,
"fontsize" : 12.0,
"id" : "obj-16",
"fontname" : "Arial",
"numinlets" : 1
}
}
, {
"box" : {
"maxclass" : "comment",
"text" : "Click to open/close serial port and start/stop patch",
"linecount" : 2,
"patching_rect" : [ 316.0, 77.0, 199.0, 34.0 ],
"numoutlets" : 0,
"fontsize" : 12.0,
"id" : "obj-17",
"fontname" : "Arial",
"numinlets" : 1
}
}
, {
"box" : {
"maxclass" : "newobj",
"text" : "bgcolor 0 0 0",
"patching_rect" : [ 348.0, 585.0, 169.0, 19.0 ],
"numoutlets" : 0,
"fontsize" : 10.0,
"id" : "obj-6",
"fontname" : "Verdana",
"numinlets" : 4
}
}
, {
"box" : {
"maxclass" : "newobj",
"text" : "unpack 0 0 0 0 0",
"patching_rect" : [ 347.0, 470.0, 119.0, 19.0 ],
"numoutlets" : 5,
"fontsize" : 10.0,
"outlettype" : [ "int", "int", "int", "int", "int" ],
"id" : "obj-20",
"fontname" : "Verdana",
"numinlets" : 1
}
}
, {
"box" : {
"maxclass" : "number",
"patching_rect" : [ 448.0, 535.0, 50.0, 19.0 ],
"numoutlets" : 2,
"fontsize" : 10.0,
"outlettype" : [ "int", "bang" ],
"id" : "obj-18",
"fontname" : "Verdana",
"numinlets" : 1
}
}
, {
"box" : {
"maxclass" : "number",
"patching_rect" : [ 398.0, 535.0, 50.0, 19.0 ],
"numoutlets" : 2,
"fontsize" : 10.0,
"outlettype" : [ "int", "bang" ],
"id" : "obj-1",
"fontname" : "Verdana",
"numinlets" : 1
}
}
, {
"box" : {
"maxclass" : "number",
"patching_rect" : [ 348.0, 535.0, 50.0, 19.0 ],
"numoutlets" : 2,
"fontsize" : 10.0,
"outlettype" : [ "int", "bang" ],
"id" : "obj-22",
"fontname" : "Verdana",
"numinlets" : 1
}
}
, {
"box" : {
"maxclass" : "comment",
"text" : "Here's the numbers from Arduino's analog input",
"linecount" : 3,
"patching_rect" : [ 198.0, 484.0, 138.0, 48.0 ],
"numoutlets" : 0,
"fontsize" : 12.0,
"id" : "obj-3",
"fontname" : "Arial",
"numinlets" : 1
}
}
],
"lines" : [ {
"patchline" : {
"source" : [ "obj-18", 0 ],
"destination" : [ "obj-6", 2 ],
"hidden" : 0,
"midpoints" : [ ]
}
}
, {
"patchline" : {
"source" : [ "obj-1", 0 ],
"destination" : [ "obj-6", 1 ],
"hidden" : 0,
"midpoints" : [ ]
}
}
, {
"patchline" : {
"source" : [ "obj-22", 0 ],
"destination" : [ "obj-6", 0 ],
"hidden" : 0,
"midpoints" : [ ]
}
}
, {
"patchline" : {
"source" : [ "obj-25", 0 ],
"destination" : [ "obj-18", 0 ],
"hidden" : 0,
"midpoints" : [ ]
}
}
, {
"patchline" : {
"source" : [ "obj-20", 4 ],
"destination" : [ "obj-25", 0 ],
"hidden" : 0,
"midpoints" : [ ]
}
}
, {
"patchline" : {
"source" : [ "obj-20", 2 ],
"destination" : [ "obj-24", 0 ],
"hidden" : 0,
"midpoints" : [ ]
}
}
, {
"patchline" : {
"source" : [ "obj-24", 0 ],
"destination" : [ "obj-1", 0 ],
"hidden" : 0,
"midpoints" : [ ]
}
}
, {
"patchline" : {
"source" : [ "obj-23", 0 ],
"destination" : [ "obj-22", 0 ],
"hidden" : 0,
"midpoints" : [ ]
}
}
, {
"patchline" : {
"source" : [ "obj-20", 0 ],
"destination" : [ "obj-23", 0 ],
"hidden" : 0,
"midpoints" : [ ]
}
}
, {
"patchline" : {
"source" : [ "obj-8", 0 ],
"destination" : [ "obj-7", 0 ],
"hidden" : 0,
"midpoints" : [ ]
}
}
, {
"patchline" : {
"source" : [ "obj-14", 0 ],
"destination" : [ "obj-10", 0 ],
"hidden" : 0,
"midpoints" : [ ]
}
}
, {
"patchline" : {
"source" : [ "obj-12", 0 ],
"destination" : [ "obj-14", 0 ],
"hidden" : 0,
"midpoints" : [ ]
}
}
, {
"patchline" : {
"source" : [ "obj-11", 0 ],
"destination" : [ "obj-12", 0 ],
"hidden" : 0,
"midpoints" : [ ]
}
}
, {
"patchline" : {
"source" : [ "obj-13", 0 ],
"destination" : [ "obj-14", 0 ],
"hidden" : 0,
"midpoints" : [ 423.5, 245.5, 298.5, 245.5 ]
}
}
, {
"patchline" : {
"source" : [ "obj-19", 0 ],
"destination" : [ "obj-14", 0 ],
"hidden" : 0,
"midpoints" : [ 403.5, 273.5, 298.5, 273.5 ]
}
}
, {
"patchline" : {
"source" : [ "obj-21", 0 ],
"destination" : [ "obj-14", 0 ],
"hidden" : 0,
"midpoints" : [ 381.5, 296.5, 298.5, 296.5 ]
}
}
, {
"patchline" : {
"source" : [ "obj-30", 0 ],
"destination" : [ "obj-21", 0 ],
"hidden" : 0,
"midpoints" : [ ]
}
}
, {
"patchline" : {
"source" : [ "obj-30", 1 ],
"destination" : [ "obj-19", 0 ],
"hidden" : 0,
"midpoints" : [ ]
}
}
, {
"patchline" : {
"source" : [ "obj-11", 0 ],
"destination" : [ "obj-30", 0 ],
"hidden" : 0,
"midpoints" : [ 298.0, 116.0, 381.5, 116.0 ]
}
}
, {
"patchline" : {
"source" : [ "obj-7", 0 ],
"destination" : [ "obj-20", 0 ],
"hidden" : 0,
"midpoints" : [ ]
}
}
, {
"patchline" : {
"source" : [ "obj-9", 0 ],
"destination" : [ "obj-8", 0 ],
"hidden" : 0,
"midpoints" : [ ]
}
}
, {
"patchline" : {
"source" : [ "obj-10", 0 ],
"destination" : [ "obj-9", 0 ],
"hidden" : 0,
"midpoints" : [ 298.5, 353.0, 356.5, 353.0 ]
}
}
, {
"patchline" : {
"source" : [ "obj-10", 2 ],
"destination" : [ "obj-9", 0 ],
"hidden" : 0,
"midpoints" : [ 356.5, 365.0, 356.5, 365.0 ]
}
}
]
}
*/

View File

@ -0,0 +1,25 @@
/*
* Blink
*
* The basic Arduino example. Turns on an LED on for one second,
* then off for one second, and so on... We use pin 13 because,
* depending on your Arduino board, it has either a built-in LED
* or a built-in resistor so that you need only an LED.
*
* http://www.arduino.cc/en/Tutorial/Blink
*/
int ledPin = 13; // LED connected to digital pin 13
void setup() // run once, when the sketch starts
{
pinMode(ledPin, OUTPUT); // sets the digital pin as output
}
void loop() // run over and over again
{
digitalWrite(ledPin, HIGH); // sets the LED on
delay(1000); // waits for a second
digitalWrite(ledPin, LOW); // sets the LED off
delay(1000); // waits for a second
}

View File

@ -0,0 +1,38 @@
/* Blink without Delay
*
* Turns on and off a light emitting diode(LED) connected to a digital
* pin, without using the delay() function. This means that other code
* can run at the same time without being interrupted by the LED code.
*
* http://www.arduino.cc/en/Tutorial/BlinkWithoutDelay
*/
int ledPin = 13; // LED connected to digital pin 13
int value = LOW; // previous value of the LED
long previousMillis = 0; // will store last time LED was updated
long interval = 1000; // interval at which to blink (milliseconds)
void setup()
{
pinMode(ledPin, OUTPUT); // sets the digital pin as output
}
void loop()
{
// here is where you'd put code that needs to be running all the time.
// check to see if it's time to blink the LED; that is, is the difference
// between the current time and last time we blinked the LED bigger than
// the interval at which we want to blink the LED.
if (millis() - previousMillis > interval) {
previousMillis = millis(); // remember the last time we blinked the LED
// if the LED is off turn it on and vice-versa.
if (value == LOW)
value = HIGH;
else
value = LOW;
digitalWrite(ledPin, value);
}
}

View File

@ -0,0 +1,27 @@
/*
* Button
* by DojoDave <http://www.0j0.org>
*
* Turns on and off a light emitting diode(LED) connected to digital
* pin 13, when pressing a pushbutton attached to pin 7.
*
* http://www.arduino.cc/en/Tutorial/Button
*/
int ledPin = 13; // choose the pin for the LED
int inputPin = 2; // choose the input pin (for a pushbutton)
int val = 0; // variable for reading the pin status
void setup() {
pinMode(ledPin, OUTPUT); // declare LED as output
pinMode(inputPin, INPUT); // declare pushbutton as input
}
void loop(){
val = digitalRead(inputPin); // read input value
if (val == HIGH) { // check if the input is HIGH
digitalWrite(ledPin, LOW); // turn LED OFF
} else {
digitalWrite(ledPin, HIGH); // turn LED ON
}
}

View File

@ -0,0 +1,52 @@
/* Debounce
*
* Each time the input pin goes from LOW to HIGH (e.g. because of a push-button
* press), the output pin is toggled from LOW to HIGH or HIGH to LOW. There's
* a minimum delay between toggles to debounce the circuit (i.e. to ignore
* noise).
*
* David A. Mellis
* 21 November 2006
*
* http://www.arduino.cc/en/Tutorial/Debounce
*/
int inPin = 7; // the number of the input pin
int outPin = 13; // the number of the output pin
int state = HIGH; // the current state of the output pin
int reading; // the current reading from the input pin
int previous = LOW; // the previous reading from the input pin
// the follow variables are long's because the time, measured in miliseconds,
// will quickly become a bigger number than can be stored in an int.
long time = 0; // the last time the output pin was toggled
long debounce = 200; // the debounce time, increase if the output flickers
void setup()
{
pinMode(inPin, INPUT);
pinMode(outPin, OUTPUT);
}
void loop()
{
reading = digitalRead(inPin);
// if we just pressed the button (i.e. the input went from LOW to HIGH),
// and we've waited long enough since the last press to ignore any noise...
if (reading == HIGH && previous == LOW && millis() - time > debounce) {
// ... invert the output
if (state == HIGH)
state = LOW;
else
state = HIGH;
// ... and remember when the last button press was
time = millis();
}
digitalWrite(outPin, state);
previous = reading;
}

View File

@ -0,0 +1,37 @@
/*
* Loop
* by David A. Mellis
*
* Lights multiple LEDs in sequence, then in reverse. Demonstrates
* the use of a for() loop and arrays.
*
* http://www.arduino.cc/en/Tutorial/Loop
*/
int timer = 100; // The higher the number, the slower the timing.
int pins[] = { 2, 3, 4, 5, 6, 7 }; // an array of pin numbers
int num_pins = 6; // the number of pins (i.e. the length of the array)
void setup()
{
int i;
for (i = 0; i < num_pins; i++) // the array elements are numbered from 0 to num_pins - 1
pinMode(pins[i], OUTPUT); // set each pin as an output
}
void loop()
{
int i;
for (i = 0; i < num_pins; i++) { // loop through each pin...
digitalWrite(pins[i], HIGH); // turning it on,
delay(timer); // pausing,
digitalWrite(pins[i], LOW); // and turning it off.
}
for (i = num_pins - 1; i >= 0; i--) {
digitalWrite(pins[i], HIGH);
delay(timer);
digitalWrite(pins[i], LOW);
}
}

View File

@ -0,0 +1,71 @@
/* Melody
* (cleft) 2005 D. Cuartielles for K3
*
* This example uses a piezo speaker to play melodies. It sends
* a square wave of the appropriate frequency to the piezo, generating
* the corresponding tone.
*
* The calculation of the tones is made following the mathematical
* operation:
*
* timeHigh = period / 2 = 1 / (2 * toneFrequency)
*
* where the different tones are described as in the table:
*
* note frequency period timeHigh
* c 261 Hz 3830 1915
* d 294 Hz 3400 1700
* e 329 Hz 3038 1519
* f 349 Hz 2864 1432
* g 392 Hz 2550 1275
* a 440 Hz 2272 1136
* b 493 Hz 2028 1014
* C 523 Hz 1912 956
*
* http://www.arduino.cc/en/Tutorial/Melody
*/
int speakerPin = 9;
int length = 15; // the number of notes
char notes[] = "ccggaagffeeddc "; // a space represents a rest
int beats[] = { 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 2, 4 };
int tempo = 300;
void playTone(int tone, int duration) {
for (long i = 0; i < duration * 1000L; i += tone * 2) {
digitalWrite(speakerPin, HIGH);
delayMicroseconds(tone);
digitalWrite(speakerPin, LOW);
delayMicroseconds(tone);
}
}
void playNote(char note, int duration) {
char names[] = { 'c', 'd', 'e', 'f', 'g', 'a', 'b', 'C' };
int tones[] = { 1915, 1700, 1519, 1432, 1275, 1136, 1014, 956 };
// play the tone corresponding to the note name
for (int i = 0; i < 8; i++) {
if (names[i] == note) {
playTone(tones[i], duration);
}
}
}
void setup() {
pinMode(speakerPin, OUTPUT);
}
void loop() {
for (int i = 0; i < length; i++) {
if (notes[i] == ' ') {
delay(beats[i] * tempo); // rest
} else {
playNote(notes[i], beats[i] * tempo);
}
// pause between notes
delay(tempo / 2);
}
}

View File

@ -0,0 +1,47 @@
// ADXL3xx
//
// Reads an Analog Devices ADXL3xx accelerometer and communicates the
// acceleration to the computer. The pins used are designed to be easily
// compatible with the breakout boards from Sparkfun, available from:
// http://www.sparkfun.com/commerce/categories.php?c=80
//
// http://www.arduino.cc/en/Tutorial/ADXL3xx
// Breakout Board Pinout
// 0: self test
// 1: z-axis
// 2: y-axis
// 3: x-axis
// 4: ground
// 5: vcc
int groundpin = 18; // analog input pin 4
int powerpin = 19; // analog input pin 5
int xpin = 3; // x-axis of the accelerometer
int ypin = 2; // y-axis
int zpin = 1; // z-axis (only on 3-axis models)
void setup()
{
Serial.begin(9600);
// Provide ground and power by using the analog inputs as normal
// digital pins. This makes it possible to directly connect the
// breakout board to the Arduino. If you use the normal 5V and
// GND pins on the Arduino, you can remove these lines.
pinMode(groundpin, OUTPUT);
pinMode(powerpin, OUTPUT);
digitalWrite(groundpin, LOW);
digitalWrite(powerpin, HIGH);
}
void loop()
{
Serial.print(analogRead(xpin));
Serial.print(" ");
Serial.print(analogRead(ypin));
Serial.print(" ");
Serial.print(analogRead(zpin));
Serial.println();
delay(1000);
}

View File

@ -0,0 +1,34 @@
/* Knock Sensor
* by DojoDave <http://www.0j0.org>
*
* Program using a Piezo element as if it was a knock sensor.
*
* We have to basically listen to an analog pin and detect
* if the signal goes over a certain threshold. It writes
* "knock" to the serial port if the Threshold is crossed,
* and toggles the LED on pin 13.
*
* http://www.arduino.cc/en/Tutorial/Knock
*/
int ledPin = 13; // led connected to control pin 13
int knockSensor = 0; // the knock sensor will be plugged at analog pin 0
byte val = 0; // variable to store the value read from the sensor pin
int statePin = LOW; // variable used to store the last LED status, to toggle the light
int THRESHOLD = 100; // threshold value to decide when the detected sound is a knock or not
void setup() {
pinMode(ledPin, OUTPUT); // declare the ledPin as as OUTPUT
Serial.begin(9600); // use the serial port
}
void loop() {
val = analogRead(knockSensor); // read the sensor and store it in the variable "val"
if (val >= THRESHOLD) {
statePin = !statePin; // toggle the status of the ledPin (this trick doesn't use time cycles)
digitalWrite(ledPin, statePin); // turn the led on or off
Serial.println("Knock!"); // send the string "Knock!" back to the computer, followed by newline
}
delay(100); // we have to make a delay to avoid overloading the serial port
}

View File

@ -0,0 +1,43 @@
/*
* Memsic2125
*
* Read the Memsic 2125 two-axis accelerometer. Converts the
* pulses output by the 2125 into milli-g's (1/1000 of earth's
* gravity) and prints them over the serial connection to the
* computer.
*
* http://www.arduino.cc/en/Tutorial/Memsic2125
*/
int xpin = 2;
int ypin = 3;
void setup()
{
Serial.begin(9600);
pinMode(xpin, INPUT);
pinMode(ypin, INPUT);
}
void loop()
{
int pulseX, pulseY;
int accX, accY;
// read pulse from x- and y-axes
pulseX = pulseIn(xpin,HIGH);
pulseY = pulseIn(ypin,HIGH);
// convert the pulse width into acceleration
// accX and accY are in milli-g's: earth's gravity is 1000.
accX = ((pulseX / 10) - 500) * 8;
accY = ((pulseY / 10) - 500) * 8;
// print the acceleration
Serial.print(accX);
Serial.print(" ");
Serial.print(accY);
Serial.println();
delay(100);
}

View File

@ -0,0 +1,56 @@
int pingPin = 7;
void setup()
{
Serial.begin(9600);
}
void loop()
{
long duration, inches, cm;
// The PING))) is triggered by a HIGH pulse of 2 or more microseconds.
// We give a short LOW pulse beforehand to ensure a clean HIGH pulse.
pinMode(pingPin, OUTPUT);
digitalWrite(pingPin, LOW);
delayMicroseconds(2);
digitalWrite(pingPin, HIGH);
delayMicroseconds(5);
digitalWrite(pingPin, LOW);
// The same pin is used to read the signal from the PING))): a HIGH
// pulse whose duration is the time (in microseconds) from the sending
// of the ping to the reception of its echo off of an object.
pinMode(pingPin, INPUT);
duration = pulseIn(pingPin, HIGH);
// convert the time into a distance
inches = microsecondsToInches(duration);
cm = microsecondsToCentimeters(duration);
Serial.print(inches);
Serial.print("in, ");
Serial.print(cm);
Serial.print("cm");
Serial.println();
delay(100);
}
long microsecondsToInches(long microseconds)
{
// According to Parallax's datasheet for the PING))), there are
// 73.746 microseconds per inch (i.e. sound travels at 1130 feet per
// second). This gives the distance travelled by the ping, outbound
// and return, so we divide by 2 to get the distance of the obstacle.
// See: http://www.parallax.com/dl/docs/prod/acc/28015-PING-v1.3.pdf
return microseconds / 74 / 2;
}
long microsecondsToCentimeters(long microseconds)
{
// The speed of sound is 340 m/s or 29 microseconds per centimeter.
// The ping travels out and back, so to find the distance of the
// object we take half of the distance travelled.
return microseconds / 29 / 2;
}

BIN
build/shared/reference.zip Executable file → Normal file

Binary file not shown.

240
hardware/boards.txt Normal file
View File

@ -0,0 +1,240 @@
##############################################################
atmega328.name=Arduino Duemilanove w/ ATmega328
atmega328.upload.protocol=stk500
atmega328.upload.maximum_size=30720
atmega328.upload.speed=57600
atmega328.bootloader.low_fuses=0xFF
atmega328.bootloader.high_fuses=0xDA
atmega328.bootloader.extended_fuses=0x05
atmega328.bootloader.path=atmega
atmega328.bootloader.file=ATmegaBOOT_168_atmega328.hex
atmega328.bootloader.unlock_bits=0x3F
atmega328.bootloader.lock_bits=0x0F
atmega328.build.mcu=atmega328p
atmega328.build.f_cpu=16000000L
atmega328.build.core=arduino
##############################################################
diecimila.name=Arduino Diecimila or Duemilanove w/ ATmega168
diecimila.upload.protocol=stk500
diecimila.upload.maximum_size=14336
diecimila.upload.speed=19200
diecimila.bootloader.low_fuses=0xff
diecimila.bootloader.high_fuses=0xdd
diecimila.bootloader.extended_fuses=0x00
diecimila.bootloader.path=atmega
diecimila.bootloader.file=ATmegaBOOT_168_diecimila.hex
diecimila.bootloader.unlock_bits=0x3F
diecimila.bootloader.lock_bits=0x0F
diecimila.build.mcu=atmega168
diecimila.build.f_cpu=16000000L
diecimila.build.core=arduino
##############################################################
mega.name=Arduino Mega
mega.upload.protocol=stk500
mega.upload.maximum_size=126976
mega.upload.speed=57600
mega.bootloader.low_fuses=0xFF
mega.bootloader.high_fuses=0xDA
mega.bootloader.extended_fuses=0xF5
mega.bootloader.path=atmega
mega.bootloader.file=ATmegaBOOT_168_atmega1280.hex
mega.bootloader.unlock_bits=0x3F
mega.bootloader.lock_bits=0x0F
mega.build.mcu=atmega1280
mega.build.f_cpu=16000000L
mega.build.core=arduino
##############################################################
mini.name=Arduino Mini
mini.upload.protocol=stk500
mini.upload.maximum_size=14336
mini.upload.speed=19200
mini.bootloader.low_fuses=0xff
mini.bootloader.high_fuses=0xdd
mini.bootloader.extended_fuses=0x00
mini.bootloader.path=atmega
mini.bootloader.file=ATmegaBOOT_168_ng.hex
mini.bootloader.unlock_bits=0x3F
mini.bootloader.lock_bits=0x0F
mini.build.mcu=atmega168
mini.build.f_cpu=16000000L
mini.build.core=arduino
##############################################################
nano.name=Arduino Nano
nano.upload.protocol=stk500
nano.upload.maximum_size=14336
nano.upload.speed=19200
nano.bootloader.low_fuses=0xff
nano.bootloader.high_fuses=0xdd
nano.bootloader.extended_fuses=0x00
nano.bootloader.path=atmega
nano.bootloader.file=ATmegaBOOT_168_diecimila.hex
nano.bootloader.unlock_bits=0x3F
nano.bootloader.lock_bits=0x0F
nano.build.mcu=atmega168
nano.build.f_cpu=16000000L
nano.build.core=arduino
##############################################################
bt.name=Arduino BT
bt.upload.protocol=stk500
bt.upload.maximum_size=14336
bt.upload.speed=19200
bt.upload.disable_flushing=true
bt.bootloader.low_fuses=0xff
bt.bootloader.high_fuses=0xdd
bt.bootloader.extended_fuses=0x00
bt.bootloader.path=bt
bt.bootloader.file=ATmegaBOOT_168.hex
bt.bootloader.unlock_bits=0x3F
bt.bootloader.lock_bits=0x0F
bt.build.mcu=atmega168
bt.build.f_cpu=16000000L
bt.build.core=arduino
##############################################################
lilypad328.name=LilyPad Arduino w/ ATmega328
lilypad328.upload.protocol=stk500
lilypad328.upload.maximum_size=30720
lilypad328.upload.speed=57600
lilypad328.bootloader.low_fuses=0xFF
lilypad328.bootloader.high_fuses=0xDA
lilypad328.bootloader.extended_fuses=0x05
lilypad328.bootloader.path=atmega
lilypad328.bootloader.file=ATmegaBOOT_168_atmega328_pro_8MHz.hex
lilypad328.bootloader.unlock_bits=0x3F
lilypad328.bootloader.lock_bits=0x0F
lilypad328.build.mcu=atmega328p
lilypad328.build.f_cpu=8000000L
lilypad328.build.core=arduino
##############################################################
lilypad.name=LilyPad Arduino w/ ATmega168
lilypad.upload.protocol=stk500
lilypad.upload.maximum_size=14336
lilypad.upload.speed=19200
lilypad.bootloader.low_fuses=0xe2
lilypad.bootloader.high_fuses=0xdd
lilypad.bootloader.extended_fuses=0x00
lilypad.bootloader.path=lilypad
lilypad.bootloader.file=LilyPadBOOT_168.hex
lilypad.bootloader.unlock_bits=0x3F
lilypad.bootloader.lock_bits=0x0F
lilypad.build.mcu=atmega168
lilypad.build.f_cpu=8000000L
lilypad.build.core=arduino
##############################################################
pro328.name=Arduino Pro or Pro Mini (3.3V, 8 MHz) w/ ATmega328
pro328.upload.protocol=stk500
pro328.upload.maximum_size=30720
pro328.upload.speed=57600
pro328.bootloader.low_fuses=0xFF
pro328.bootloader.high_fuses=0xDA
pro328.bootloader.extended_fuses=0x05
pro328.bootloader.path=atmega
pro328.bootloader.file=ATmegaBOOT_168_atmega328_pro_8MHz.hex
pro328.bootloader.unlock_bits=0x3F
pro328.bootloader.lock_bits=0x0F
pro328.build.mcu=atmega328p
pro328.build.f_cpu=8000000L
pro328.build.core=arduino
##############################################################
pro.name=Arduino Pro or Pro Mini (3.3V, 8 MHz) w/ ATmega168
pro.upload.protocol=stk500
pro.upload.maximum_size=14336
pro.upload.speed=19200
pro.bootloader.low_fuses=0xc6
pro.bootloader.high_fuses=0xdd
pro.bootloader.extended_fuses=0x00
pro.bootloader.path=atmega
pro.bootloader.file=ATmegaBOOT_168_pro_8MHz.hex
pro.bootloader.unlock_bits=0x3F
pro.bootloader.lock_bits=0x0F
pro.build.mcu=atmega168
pro.build.f_cpu=8000000L
pro.build.core=arduino
##############################################################
atmega168.name=Arduino NG or older w/ ATmega168
atmega168.upload.protocol=stk500
atmega168.upload.maximum_size=14336
atmega168.upload.speed=19200
atmega168.bootloader.low_fuses=0xff
atmega168.bootloader.high_fuses=0xdd
atmega168.bootloader.extended_fuses=0x00
atmega168.bootloader.path=atmega
atmega168.bootloader.file=ATmegaBOOT_168_ng.hex
atmega168.bootloader.unlock_bits=0x3F
atmega168.bootloader.lock_bits=0x0F
atmega168.build.mcu=atmega168
atmega168.build.f_cpu=16000000L
atmega168.build.core=arduino
##############################################################
atmega8.name=Arduino NG or older w/ ATmega8
atmega8.upload.protocol=stk500
atmega8.upload.maximum_size=7168
atmega8.upload.speed=19200
atmega8.bootloader.low_fuses=0xdf
atmega8.bootloader.high_fuses=0xca
atmega8.bootloader.path=atmega8
atmega8.bootloader.file=ATmegaBOOT.hex
atmega8.bootloader.unlock_bits=0x3F
atmega8.bootloader.lock_bits=0x0F
atmega8.build.mcu=atmega8
atmega8.build.f_cpu=16000000L
atmega8.build.core=arduino

View File

@ -0,0 +1,1054 @@
/**********************************************************/
/* Serial Bootloader for Atmel megaAVR Controllers */
/* */
/* tested with ATmega8, ATmega128 and ATmega168 */
/* should work with other mega's, see code for details */
/* */
/* ATmegaBOOT.c */
/* */
/* */
/* 20090308: integrated Mega changes into main bootloader */
/* source by D. Mellis */
/* 20080930: hacked for Arduino Mega (with the 1280 */
/* processor, backwards compatible) */
/* by D. Cuartielles */
/* 20070626: hacked for Arduino Diecimila (which auto- */
/* resets when a USB connection is made to it) */
/* by D. Mellis */
/* 20060802: hacked for Arduino by D. Cuartielles */
/* based on a previous hack by D. Mellis */
/* and D. Cuartielles */
/* */
/* Monitor and debug functions were added to the original */
/* code by Dr. Erik Lins, chip45.com. (See below) */
/* */
/* Thanks to Karl Pitrich for fixing a bootloader pin */
/* problem and more informative LED blinking! */
/* */
/* For the latest version see: */
/* http://www.chip45.com/ */
/* */
/* ------------------------------------------------------ */
/* */
/* based on stk500boot.c */
/* Copyright (c) 2003, Jason P. Kyle */
/* All rights reserved. */
/* see avr1.org for original file and information */
/* */
/* This program is free software; you can redistribute it */
/* and/or modify it under the terms of the GNU General */
/* Public License as published by the Free Software */
/* Foundation; either version 2 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 Public */
/* License for more details. */
/* */
/* You should have received a copy of the GNU General */
/* Public License along with this program; if not, write */
/* to the Free Software Foundation, Inc., */
/* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
/* */
/* Licence can be viewed at */
/* http://www.fsf.org/licenses/gpl.txt */
/* */
/* Target = Atmel AVR m128,m64,m32,m16,m8,m162,m163,m169, */
/* m8515,m8535. ATmega161 has a very small boot block so */
/* isn't supported. */
/* */
/* Tested with m168 */
/**********************************************************/
/* $Id$ */
/* some includes */
#include <inttypes.h>
#include <avr/io.h>
#include <avr/pgmspace.h>
#include <avr/interrupt.h>
#include <avr/wdt.h>
#include <util/delay.h>
/* the current avr-libc eeprom functions do not support the ATmega168 */
/* own eeprom write/read functions are used instead */
#if !defined(__AVR_ATmega168__) || !defined(__AVR_ATmega328P__)
#include <avr/eeprom.h>
#endif
/* Use the F_CPU defined in Makefile */
/* 20060803: hacked by DojoCorp */
/* 20070626: hacked by David A. Mellis to decrease waiting time for auto-reset */
/* set the waiting time for the bootloader */
/* get this from the Makefile instead */
/* #define MAX_TIME_COUNT (F_CPU>>4) */
/* 20070707: hacked by David A. Mellis - after this many errors give up and launch application */
#define MAX_ERROR_COUNT 5
/* set the UART baud rate */
/* 20060803: hacked by DojoCorp */
//#define BAUD_RATE 115200
#ifndef BAUD_RATE
#define BAUD_RATE 19200
#endif
/* SW_MAJOR and MINOR needs to be updated from time to time to avoid warning message from AVR Studio */
/* never allow AVR Studio to do an update !!!! */
#define HW_VER 0x02
#define SW_MAJOR 0x01
#define SW_MINOR 0x10
/* Adjust to suit whatever pin your hardware uses to enter the bootloader */
/* ATmega128 has two UARTS so two pins are used to enter bootloader and select UART */
/* ATmega1280 has four UARTS, but for Arduino Mega, we will only use RXD0 to get code */
/* BL0... means UART0, BL1... means UART1 */
#ifdef __AVR_ATmega128__
#define BL_DDR DDRF
#define BL_PORT PORTF
#define BL_PIN PINF
#define BL0 PINF7
#define BL1 PINF6
#elif defined __AVR_ATmega1280__
/* we just don't do anything for the MEGA and enter bootloader on reset anyway*/
#else
/* other ATmegas have only one UART, so only one pin is defined to enter bootloader */
#define BL_DDR DDRD
#define BL_PORT PORTD
#define BL_PIN PIND
#define BL PIND6
#endif
/* onboard LED is used to indicate, that the bootloader was entered (3x flashing) */
/* if monitor functions are included, LED goes on after monitor was entered */
#if defined __AVR_ATmega128__ || defined __AVR_ATmega1280__
/* Onboard LED is connected to pin PB7 (e.g. Crumb128, PROBOmega128, Savvy128, Arduino Mega) */
#define LED_DDR DDRB
#define LED_PORT PORTB
#define LED_PIN PINB
#define LED PINB7
#else
/* Onboard LED is connected to pin PB5 in Arduino NG, Diecimila, and Duomilanuove */
/* other boards like e.g. Crumb8, Crumb168 are using PB2 */
#define LED_DDR DDRB
#define LED_PORT PORTB
#define LED_PIN PINB
#define LED PINB5
#endif
/* monitor functions will only be compiled when using ATmega128, due to bootblock size constraints */
#if defined(__AVR_ATmega128__) || defined(__AVR_ATmega1280__)
#define MONITOR 1
#endif
/* define various device id's */
/* manufacturer byte is always the same */
#define SIG1 0x1E // Yep, Atmel is the only manufacturer of AVR micros. Single source :(
#if defined __AVR_ATmega1280__
#define SIG2 0x97
#define SIG3 0x03
#define PAGE_SIZE 0x80U //128 words
#elif defined __AVR_ATmega1281__
#define SIG2 0x97
#define SIG3 0x04
#define PAGE_SIZE 0x80U //128 words
#elif defined __AVR_ATmega128__
#define SIG2 0x97
#define SIG3 0x02
#define PAGE_SIZE 0x80U //128 words
#elif defined __AVR_ATmega64__
#define SIG2 0x96
#define SIG3 0x02
#define PAGE_SIZE 0x80U //128 words
#elif defined __AVR_ATmega32__
#define SIG2 0x95
#define SIG3 0x02
#define PAGE_SIZE 0x40U //64 words
#elif defined __AVR_ATmega16__
#define SIG2 0x94
#define SIG3 0x03
#define PAGE_SIZE 0x40U //64 words
#elif defined __AVR_ATmega8__
#define SIG2 0x93
#define SIG3 0x07
#define PAGE_SIZE 0x20U //32 words
#elif defined __AVR_ATmega88__
#define SIG2 0x93
#define SIG3 0x0a
#define PAGE_SIZE 0x20U //32 words
#elif defined __AVR_ATmega168__
#define SIG2 0x94
#define SIG3 0x06
#define PAGE_SIZE 0x40U //64 words
#elif defined __AVR_ATmega328P__
#define SIG2 0x95
#define SIG3 0x0F
#define PAGE_SIZE 0x40U //64 words
#elif defined __AVR_ATmega162__
#define SIG2 0x94
#define SIG3 0x04
#define PAGE_SIZE 0x40U //64 words
#elif defined __AVR_ATmega163__
#define SIG2 0x94
#define SIG3 0x02
#define PAGE_SIZE 0x40U //64 words
#elif defined __AVR_ATmega169__
#define SIG2 0x94
#define SIG3 0x05
#define PAGE_SIZE 0x40U //64 words
#elif defined __AVR_ATmega8515__
#define SIG2 0x93
#define SIG3 0x06
#define PAGE_SIZE 0x20U //32 words
#elif defined __AVR_ATmega8535__
#define SIG2 0x93
#define SIG3 0x08
#define PAGE_SIZE 0x20U //32 words
#endif
/* function prototypes */
void putch(char);
char getch(void);
void getNch(uint8_t);
void byte_response(uint8_t);
void nothing_response(void);
char gethex(void);
void puthex(char);
void flash_led(uint8_t);
/* some variables */
union address_union {
uint16_t word;
uint8_t byte[2];
} address;
union length_union {
uint16_t word;
uint8_t byte[2];
} length;
struct flags_struct {
unsigned eeprom : 1;
unsigned rampz : 1;
} flags;
uint8_t buff[256];
uint8_t address_high;
uint8_t pagesz=0x80;
uint8_t i;
uint8_t bootuart = 0;
uint8_t error_count = 0;
void (*app_start)(void) = 0x0000;
/* main program starts here */
int main(void)
{
uint8_t ch,ch2;
uint16_t w;
#ifdef WATCHDOG_MODS
ch = MCUSR;
MCUSR = 0;
WDTCSR |= _BV(WDCE) | _BV(WDE);
WDTCSR = 0;
// Check if the WDT was used to reset, in which case we dont bootload and skip straight to the code. woot.
if (! (ch & _BV(EXTRF))) // if its a not an external reset...
app_start(); // skip bootloader
#else
asm volatile("nop\n\t");
#endif
/* set pin direction for bootloader pin and enable pullup */
/* for ATmega128, two pins need to be initialized */
#ifdef __AVR_ATmega128__
BL_DDR &= ~_BV(BL0);
BL_DDR &= ~_BV(BL1);
BL_PORT |= _BV(BL0);
BL_PORT |= _BV(BL1);
#else
/* We run the bootloader regardless of the state of this pin. Thus, don't
put it in a different state than the other pins. --DAM, 070709
This also applies to Arduino Mega -- DC, 080930
BL_DDR &= ~_BV(BL);
BL_PORT |= _BV(BL);
*/
#endif
#ifdef __AVR_ATmega128__
/* check which UART should be used for booting */
if(bit_is_clear(BL_PIN, BL0)) {
bootuart = 1;
}
else if(bit_is_clear(BL_PIN, BL1)) {
bootuart = 2;
}
#endif
#if defined __AVR_ATmega1280__
/* the mega1280 chip has four serial ports ... we could eventually use any of them, or not? */
/* however, we don't wanna confuse people, to avoid making a mess, we will stick to RXD0, TXD0 */
bootuart = 1;
#endif
/* check if flash is programmed already, if not start bootloader anyway */
if(pgm_read_byte_near(0x0000) != 0xFF) {
#ifdef __AVR_ATmega128__
/* no UART was selected, start application */
if(!bootuart) {
app_start();
}
#else
/* check if bootloader pin is set low */
/* we don't start this part neither for the m8, nor m168 */
//if(bit_is_set(BL_PIN, BL)) {
// app_start();
// }
#endif
}
#ifdef __AVR_ATmega128__
/* no bootuart was selected, default to uart 0 */
if(!bootuart) {
bootuart = 1;
}
#endif
/* initialize UART(s) depending on CPU defined */
#if defined(__AVR_ATmega128__) || defined(__AVR_ATmega1280__)
if(bootuart == 1) {
UBRR0L = (uint8_t)(F_CPU/(BAUD_RATE*16L)-1);
UBRR0H = (F_CPU/(BAUD_RATE*16L)-1) >> 8;
UCSR0A = 0x00;
UCSR0C = 0x06;
UCSR0B = _BV(TXEN0)|_BV(RXEN0);
}
if(bootuart == 2) {
UBRR1L = (uint8_t)(F_CPU/(BAUD_RATE*16L)-1);
UBRR1H = (F_CPU/(BAUD_RATE*16L)-1) >> 8;
UCSR1A = 0x00;
UCSR1C = 0x06;
UCSR1B = _BV(TXEN1)|_BV(RXEN1);
}
#elif defined __AVR_ATmega163__
UBRR = (uint8_t)(F_CPU/(BAUD_RATE*16L)-1);
UBRRHI = (F_CPU/(BAUD_RATE*16L)-1) >> 8;
UCSRA = 0x00;
UCSRB = _BV(TXEN)|_BV(RXEN);
#elif defined(__AVR_ATmega168__) || defined(__AVR_ATmega328P__)
#ifdef DOUBLE_SPEED
UCSR0A = (1<<U2X0); //Double speed mode USART0
UBRR0L = (uint8_t)(F_CPU/(BAUD_RATE*8L)-1);
UBRR0H = (F_CPU/(BAUD_RATE*8L)-1) >> 8;
#else
UBRR0L = (uint8_t)(F_CPU/(BAUD_RATE*16L)-1);
UBRR0H = (F_CPU/(BAUD_RATE*16L)-1) >> 8;
#endif
UCSR0B = (1<<RXEN0) | (1<<TXEN0);
UCSR0C = (1<<UCSZ00) | (1<<UCSZ01);
/* Enable internal pull-up resistor on pin D0 (RX), in order
to supress line noise that prevents the bootloader from
timing out (DAM: 20070509) */
DDRD &= ~_BV(PIND0);
PORTD |= _BV(PIND0);
#elif defined __AVR_ATmega8__
/* m8 */
UBRRH = (((F_CPU/BAUD_RATE)/16)-1)>>8; // set baud rate
UBRRL = (((F_CPU/BAUD_RATE)/16)-1);
UCSRB = (1<<RXEN)|(1<<TXEN); // enable Rx & Tx
UCSRC = (1<<URSEL)|(1<<UCSZ1)|(1<<UCSZ0); // config USART; 8N1
#else
/* m16,m32,m169,m8515,m8535 */
UBRRL = (uint8_t)(F_CPU/(BAUD_RATE*16L)-1);
UBRRH = (F_CPU/(BAUD_RATE*16L)-1) >> 8;
UCSRA = 0x00;
UCSRC = 0x06;
UCSRB = _BV(TXEN)|_BV(RXEN);
#endif
#if defined __AVR_ATmega1280__
/* Enable internal pull-up resistor on pin D0 (RX), in order
to supress line noise that prevents the bootloader from
timing out (DAM: 20070509) */
/* feature added to the Arduino Mega --DC: 080930 */
DDRE &= ~_BV(PINE0);
PORTE |= _BV(PINE0);
#endif
/* set LED pin as output */
LED_DDR |= _BV(LED);
/* flash onboard LED to signal entering of bootloader */
#if defined(__AVR_ATmega128__) || defined(__AVR_ATmega1280__)
// 4x for UART0, 5x for UART1
flash_led(NUM_LED_FLASHES + bootuart);
#else
flash_led(NUM_LED_FLASHES);
#endif
/* 20050803: by DojoCorp, this is one of the parts provoking the
system to stop listening, cancelled from the original */
//putch('\0');
/* forever loop */
for (;;) {
/* get character from UART */
ch = getch();
/* A bunch of if...else if... gives smaller code than switch...case ! */
/* Hello is anyone home ? */
if(ch=='0') {
nothing_response();
}
/* Request programmer ID */
/* Not using PROGMEM string due to boot block in m128 being beyond 64kB boundry */
/* Would need to selectively manipulate RAMPZ, and it's only 9 characters anyway so who cares. */
else if(ch=='1') {
if (getch() == ' ') {
putch(0x14);
putch('A');
putch('V');
putch('R');
putch(' ');
putch('I');
putch('S');
putch('P');
putch(0x10);
} else {
if (++error_count == MAX_ERROR_COUNT)
app_start();
}
}
/* AVR ISP/STK500 board commands DON'T CARE so default nothing_response */
else if(ch=='@') {
ch2 = getch();
if (ch2>0x85) getch();
nothing_response();
}
/* AVR ISP/STK500 board requests */
else if(ch=='A') {
ch2 = getch();
if(ch2==0x80) byte_response(HW_VER); // Hardware version
else if(ch2==0x81) byte_response(SW_MAJOR); // Software major version
else if(ch2==0x82) byte_response(SW_MINOR); // Software minor version
else if(ch2==0x98) byte_response(0x03); // Unknown but seems to be required by avr studio 3.56
else byte_response(0x00); // Covers various unnecessary responses we don't care about
}
/* Device Parameters DON'T CARE, DEVICE IS FIXED */
else if(ch=='B') {
getNch(20);
nothing_response();
}
/* Parallel programming stuff DON'T CARE */
else if(ch=='E') {
getNch(5);
nothing_response();
}
/* P: Enter programming mode */
/* R: Erase device, don't care as we will erase one page at a time anyway. */
else if(ch=='P' || ch=='R') {
nothing_response();
}
/* Leave programming mode */
else if(ch=='Q') {
nothing_response();
#ifdef WATCHDOG_MODS
// autoreset via watchdog (sneaky!)
WDTCSR = _BV(WDE);
while (1); // 16 ms
#endif
}
/* Set address, little endian. EEPROM in bytes, FLASH in words */
/* Perhaps extra address bytes may be added in future to support > 128kB FLASH. */
/* This might explain why little endian was used here, big endian used everywhere else. */
else if(ch=='U') {
address.byte[0] = getch();
address.byte[1] = getch();
nothing_response();
}
/* Universal SPI programming command, disabled. Would be used for fuses and lock bits. */
else if(ch=='V') {
if (getch() == 0x30) {
getch();
ch = getch();
getch();
if (ch == 0) {
byte_response(SIG1);
} else if (ch == 1) {
byte_response(SIG2);
} else {
byte_response(SIG3);
}
} else {
getNch(3);
byte_response(0x00);
}
}
/* Write memory, length is big endian and is in bytes */
else if(ch=='d') {
length.byte[1] = getch();
length.byte[0] = getch();
flags.eeprom = 0;
if (getch() == 'E') flags.eeprom = 1;
for (w=0;w<length.word;w++) {
buff[w] = getch(); // Store data in buffer, can't keep up with serial data stream whilst programming pages
}
if (getch() == ' ') {
if (flags.eeprom) { //Write to EEPROM one byte at a time
address.word <<= 1;
for(w=0;w<length.word;w++) {
#if defined(__AVR_ATmega168__) || defined(__AVR_ATmega328P__)
while(EECR & (1<<EEPE));
EEAR = (uint16_t)(void *)address.word;
EEDR = buff[w];
EECR |= (1<<EEMPE);
EECR |= (1<<EEPE);
#else
eeprom_write_byte((void *)address.word,buff[w]);
#endif
address.word++;
}
}
else { //Write to FLASH one page at a time
if (address.byte[1]>127) address_high = 0x01; //Only possible with m128, m256 will need 3rd address byte. FIXME
else address_high = 0x00;
#if defined(__AVR_ATmega128__) || defined(__AVR_ATmega1280__) || defined(__AVR_ATmega1281__)
RAMPZ = address_high;
#endif
address.word = address.word << 1; //address * 2 -> byte location
/* if ((length.byte[0] & 0x01) == 0x01) length.word++; //Even up an odd number of bytes */
if ((length.byte[0] & 0x01)) length.word++; //Even up an odd number of bytes
cli(); //Disable interrupts, just to be sure
#if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega1281__)
while(bit_is_set(EECR,EEPE)); //Wait for previous EEPROM writes to complete
#else
while(bit_is_set(EECR,EEWE)); //Wait for previous EEPROM writes to complete
#endif
asm volatile(
"clr r17 \n\t" //page_word_count
"lds r30,address \n\t" //Address of FLASH location (in bytes)
"lds r31,address+1 \n\t"
"ldi r28,lo8(buff) \n\t" //Start of buffer array in RAM
"ldi r29,hi8(buff) \n\t"
"lds r24,length \n\t" //Length of data to be written (in bytes)
"lds r25,length+1 \n\t"
"length_loop: \n\t" //Main loop, repeat for number of words in block
"cpi r17,0x00 \n\t" //If page_word_count=0 then erase page
"brne no_page_erase \n\t"
"wait_spm1: \n\t"
"lds r16,%0 \n\t" //Wait for previous spm to complete
"andi r16,1 \n\t"
"cpi r16,1 \n\t"
"breq wait_spm1 \n\t"
"ldi r16,0x03 \n\t" //Erase page pointed to by Z
"sts %0,r16 \n\t"
"spm \n\t"
#ifdef __AVR_ATmega163__
".word 0xFFFF \n\t"
"nop \n\t"
#endif
"wait_spm2: \n\t"
"lds r16,%0 \n\t" //Wait for previous spm to complete
"andi r16,1 \n\t"
"cpi r16,1 \n\t"
"breq wait_spm2 \n\t"
"ldi r16,0x11 \n\t" //Re-enable RWW section
"sts %0,r16 \n\t"
"spm \n\t"
#ifdef __AVR_ATmega163__
".word 0xFFFF \n\t"
"nop \n\t"
#endif
"no_page_erase: \n\t"
"ld r0,Y+ \n\t" //Write 2 bytes into page buffer
"ld r1,Y+ \n\t"
"wait_spm3: \n\t"
"lds r16,%0 \n\t" //Wait for previous spm to complete
"andi r16,1 \n\t"
"cpi r16,1 \n\t"
"breq wait_spm3 \n\t"
"ldi r16,0x01 \n\t" //Load r0,r1 into FLASH page buffer
"sts %0,r16 \n\t"
"spm \n\t"
"inc r17 \n\t" //page_word_count++
"cpi r17,%1 \n\t"
"brlo same_page \n\t" //Still same page in FLASH
"write_page: \n\t"
"clr r17 \n\t" //New page, write current one first
"wait_spm4: \n\t"
"lds r16,%0 \n\t" //Wait for previous spm to complete
"andi r16,1 \n\t"
"cpi r16,1 \n\t"
"breq wait_spm4 \n\t"
#ifdef __AVR_ATmega163__
"andi r30,0x80 \n\t" // m163 requires Z6:Z1 to be zero during page write
#endif
"ldi r16,0x05 \n\t" //Write page pointed to by Z
"sts %0,r16 \n\t"
"spm \n\t"
#ifdef __AVR_ATmega163__
".word 0xFFFF \n\t"
"nop \n\t"
"ori r30,0x7E \n\t" // recover Z6:Z1 state after page write (had to be zero during write)
#endif
"wait_spm5: \n\t"
"lds r16,%0 \n\t" //Wait for previous spm to complete
"andi r16,1 \n\t"
"cpi r16,1 \n\t"
"breq wait_spm5 \n\t"
"ldi r16,0x11 \n\t" //Re-enable RWW section
"sts %0,r16 \n\t"
"spm \n\t"
#ifdef __AVR_ATmega163__
".word 0xFFFF \n\t"
"nop \n\t"
#endif
"same_page: \n\t"
"adiw r30,2 \n\t" //Next word in FLASH
"sbiw r24,2 \n\t" //length-2
"breq final_write \n\t" //Finished
"rjmp length_loop \n\t"
"final_write: \n\t"
"cpi r17,0 \n\t"
"breq block_done \n\t"
"adiw r24,2 \n\t" //length+2, fool above check on length after short page write
"rjmp write_page \n\t"
"block_done: \n\t"
"clr __zero_reg__ \n\t" //restore zero register
#if defined __AVR_ATmega168__ || __AVR_ATmega328P__ || __AVR_ATmega128__ || __AVR_ATmega1280__ || __AVR_ATmega1281__
: "=m" (SPMCSR) : "M" (PAGE_SIZE) : "r0","r16","r17","r24","r25","r28","r29","r30","r31"
#else
: "=m" (SPMCR) : "M" (PAGE_SIZE) : "r0","r16","r17","r24","r25","r28","r29","r30","r31"
#endif
);
/* Should really add a wait for RWW section to be enabled, don't actually need it since we never */
/* exit the bootloader without a power cycle anyhow */
}
putch(0x14);
putch(0x10);
} else {
if (++error_count == MAX_ERROR_COUNT)
app_start();
}
}
/* Read memory block mode, length is big endian. */
else if(ch=='t') {
length.byte[1] = getch();
length.byte[0] = getch();
#if defined(__AVR_ATmega128__) || defined(__AVR_ATmega1280__)
if (address.word>0x7FFF) flags.rampz = 1; // No go with m256, FIXME
else flags.rampz = 0;
#endif
address.word = address.word << 1; // address * 2 -> byte location
if (getch() == 'E') flags.eeprom = 1;
else flags.eeprom = 0;
if (getch() == ' ') { // Command terminator
putch(0x14);
for (w=0;w < length.word;w++) { // Can handle odd and even lengths okay
if (flags.eeprom) { // Byte access EEPROM read
#if defined(__AVR_ATmega168__) || defined(__AVR_ATmega328P__)
while(EECR & (1<<EEPE));
EEAR = (uint16_t)(void *)address.word;
EECR |= (1<<EERE);
putch(EEDR);
#else
putch(eeprom_read_byte((void *)address.word));
#endif
address.word++;
}
else {
if (!flags.rampz) putch(pgm_read_byte_near(address.word));
#if defined(__AVR_ATmega128__) || defined(__AVR_ATmega1280__)
else putch(pgm_read_byte_far(address.word + 0x10000));
// Hmmmm, yuck FIXME when m256 arrvies
#endif
address.word++;
}
}
putch(0x10);
}
}
/* Get device signature bytes */
else if(ch=='u') {
if (getch() == ' ') {
putch(0x14);
putch(SIG1);
putch(SIG2);
putch(SIG3);
putch(0x10);
} else {
if (++error_count == MAX_ERROR_COUNT)
app_start();
}
}
/* Read oscillator calibration byte */
else if(ch=='v') {
byte_response(0x00);
}
#if defined MONITOR
/* here come the extended monitor commands by Erik Lins */
/* check for three times exclamation mark pressed */
else if(ch=='!') {
ch = getch();
if(ch=='!') {
ch = getch();
if(ch=='!') {
PGM_P welcome = "";
#if defined(__AVR_ATmega128__) || defined(__AVR_ATmega1280__)
uint16_t extaddr;
#endif
uint8_t addrl, addrh;
#ifdef CRUMB128
welcome = "ATmegaBOOT / Crumb128 - (C) J.P.Kyle, E.Lins - 050815\n\r";
#elif defined PROBOMEGA128
welcome = "ATmegaBOOT / PROBOmega128 - (C) J.P.Kyle, E.Lins - 050815\n\r";
#elif defined SAVVY128
welcome = "ATmegaBOOT / Savvy128 - (C) J.P.Kyle, E.Lins - 050815\n\r";
#elif defined __AVR_ATmega1280__
welcome = "ATmegaBOOT / Arduino Mega - (C) Arduino LLC - 090930\n\r";
#endif
/* turn on LED */
LED_DDR |= _BV(LED);
LED_PORT &= ~_BV(LED);
/* print a welcome message and command overview */
for(i=0; welcome[i] != '\0'; ++i) {
putch(welcome[i]);
}
/* test for valid commands */
for(;;) {
putch('\n');
putch('\r');
putch(':');
putch(' ');
ch = getch();
putch(ch);
/* toggle LED */
if(ch == 't') {
if(bit_is_set(LED_PIN,LED)) {
LED_PORT &= ~_BV(LED);
putch('1');
} else {
LED_PORT |= _BV(LED);
putch('0');
}
}
/* read byte from address */
else if(ch == 'r') {
ch = getch(); putch(ch);
addrh = gethex();
addrl = gethex();
putch('=');
ch = *(uint8_t *)((addrh << 8) + addrl);
puthex(ch);
}
/* write a byte to address */
else if(ch == 'w') {
ch = getch(); putch(ch);
addrh = gethex();
addrl = gethex();
ch = getch(); putch(ch);
ch = gethex();
*(uint8_t *)((addrh << 8) + addrl) = ch;
}
/* read from uart and echo back */
else if(ch == 'u') {
for(;;) {
putch(getch());
}
}
#if defined(__AVR_ATmega128__) || defined(__AVR_ATmega1280__)
/* external bus loop */
else if(ch == 'b') {
putch('b');
putch('u');
putch('s');
MCUCR = 0x80;
XMCRA = 0;
XMCRB = 0;
extaddr = 0x1100;
for(;;) {
ch = *(volatile uint8_t *)extaddr;
if(++extaddr == 0) {
extaddr = 0x1100;
}
}
}
#endif
else if(ch == 'j') {
app_start();
}
} /* end of monitor functions */
}
}
}
/* end of monitor */
#endif
else if (++error_count == MAX_ERROR_COUNT) {
app_start();
}
} /* end of forever loop */
}
char gethexnib(void) {
char a;
a = getch(); putch(a);
if(a >= 'a') {
return (a - 'a' + 0x0a);
} else if(a >= '0') {
return(a - '0');
}
return a;
}
char gethex(void) {
return (gethexnib() << 4) + gethexnib();
}
void puthex(char ch) {
char ah;
ah = ch >> 4;
if(ah >= 0x0a) {
ah = ah - 0x0a + 'a';
} else {
ah += '0';
}
ch &= 0x0f;
if(ch >= 0x0a) {
ch = ch - 0x0a + 'a';
} else {
ch += '0';
}
putch(ah);
putch(ch);
}
void putch(char ch)
{
#if defined(__AVR_ATmega128__) || defined(__AVR_ATmega1280__)
if(bootuart == 1) {
while (!(UCSR0A & _BV(UDRE0)));
UDR0 = ch;
}
else if (bootuart == 2) {
while (!(UCSR1A & _BV(UDRE1)));
UDR1 = ch;
}
#elif defined(__AVR_ATmega168__) || defined(__AVR_ATmega328P__)
while (!(UCSR0A & _BV(UDRE0)));
UDR0 = ch;
#else
/* m8,16,32,169,8515,8535,163 */
while (!(UCSRA & _BV(UDRE)));
UDR = ch;
#endif
}
char getch(void)
{
#if defined(__AVR_ATmega128__) || defined(__AVR_ATmega1280__)
uint32_t count = 0;
if(bootuart == 1) {
while(!(UCSR0A & _BV(RXC0))) {
/* 20060803 DojoCorp:: Addon coming from the previous Bootloader*/
/* HACKME:: here is a good place to count times*/
count++;
if (count > MAX_TIME_COUNT)
app_start();
}
return UDR0;
}
else if(bootuart == 2) {
while(!(UCSR1A & _BV(RXC1))) {
/* 20060803 DojoCorp:: Addon coming from the previous Bootloader*/
/* HACKME:: here is a good place to count times*/
count++;
if (count > MAX_TIME_COUNT)
app_start();
}
return UDR1;
}
return 0;
#elif defined(__AVR_ATmega168__) || defined(__AVR_ATmega328P__)
uint32_t count = 0;
while(!(UCSR0A & _BV(RXC0))){
/* 20060803 DojoCorp:: Addon coming from the previous Bootloader*/
/* HACKME:: here is a good place to count times*/
count++;
if (count > MAX_TIME_COUNT)
app_start();
}
return UDR0;
#else
/* m8,16,32,169,8515,8535,163 */
uint32_t count = 0;
while(!(UCSRA & _BV(RXC))){
/* 20060803 DojoCorp:: Addon coming from the previous Bootloader*/
/* HACKME:: here is a good place to count times*/
count++;
if (count > MAX_TIME_COUNT)
app_start();
}
return UDR;
#endif
}
void getNch(uint8_t count)
{
while(count--) {
#if defined(__AVR_ATmega128__) || defined(__AVR_ATmega1280__)
if(bootuart == 1) {
while(!(UCSR0A & _BV(RXC0)));
UDR0;
}
else if(bootuart == 2) {
while(!(UCSR1A & _BV(RXC1)));
UDR1;
}
#elif defined(__AVR_ATmega168__) || defined(__AVR_ATmega328P__)
getch();
#else
/* m8,16,32,169,8515,8535,163 */
/* 20060803 DojoCorp:: Addon coming from the previous Bootloader*/
//while(!(UCSRA & _BV(RXC)));
//UDR;
getch(); // need to handle time out
#endif
}
}
void byte_response(uint8_t val)
{
if (getch() == ' ') {
putch(0x14);
putch(val);
putch(0x10);
} else {
if (++error_count == MAX_ERROR_COUNT)
app_start();
}
}
void nothing_response(void)
{
if (getch() == ' ') {
putch(0x14);
putch(0x10);
} else {
if (++error_count == MAX_ERROR_COUNT)
app_start();
}
}
void flash_led(uint8_t count)
{
while (count--) {
LED_PORT |= _BV(LED);
_delay_ms(100);
LED_PORT &= ~_BV(LED);
_delay_ms(100);
}
}
/* end of file ATmegaBOOT.c */

View File

@ -0,0 +1,245 @@
:020000021000EC
:10F000000C9472F80C9492F80C9492F80C9492F878
:10F010000C9492F80C9492F80C9492F80C9492F848
:10F020000C9492F80C9492F80C9492F80C9492F838
:10F030000C9492F80C9492F80C9492F80C9492F828
:10F040000C9492F80C9492F80C9492F80C9492F818
:10F050000C9492F80C9492F80C9492F80C9492F808
:10F060000C9492F80C9492F80C9492F80C9492F8F8
:10F070000C9492F80C9492F80C9492F80C9492F8E8
:10F080000C9492F80C9492F80C9492F80C9492F8D8
:10F090000C9492F80C9492F80C9492F80C9492F8C8
:10F0A0000C9492F80C9492F80C9492F80C9492F8B8
:10F0B0000C9492F80C9492F80C9492F80C9492F8A8
:10F0C0000C9492F80C9492F80C9492F80C9492F898
:10F0D0000C9492F80C9492F80C9492F80C9492F888
:10F0E0000C9492F811241FBECFEFD1E2DEBFCDBF4A
:10F0F00012E0A0E0B2E0EEEDFEEF01E00BBF02C0D7
:10F1000007900D92A833B107D9F71BBE13E0A8E30F
:10F11000B2E001C01D92A334B107E1F70E9412FAD8
:10F120000C946DFF0C9400F8982F959595959595F6
:10F130009595905D8F708A301CF1282F295A809107
:10F140003802813019F0823071F008958091C0004A
:10F1500085FFFCCF9093C6008091C00085FFFCCF57
:10F160002093C60008958091C80085FFFCCF90933E
:10F17000CE008091C80085FFFCCF2093CE0008957B
:10F18000282F205DDCCF982F80913802813019F034
:10F19000823041F008958091C00085FFFCCF9093AC
:10F1A000C60008958091C80085FFFCCF9093CE00E3
:10F1B0000895EF92FF920F931F9380913802813050
:10F1C00069F1823031F080E01F910F91FF90EF9054
:10F1D0000895EE24FF2487018091C80087FD17C0A1
:10F1E0000894E11CF11C011D111D81E4E81682E464
:10F1F000F8068FE0080780E0180770F3E0913A0204
:10F20000F0913B0209958091C80087FFE9CF80917A
:10F21000CE001F910F91FF90EF900895EE24FF24F0
:10F2200087018091C00087FD17C00894E11CF11C84
:10F23000011D111D81E4E81682E4F8068FE008073D
:10F2400080E0180770F3E0913A02F0913B020995D3
:10F250008091C00087FFE9CF8091C6001F910F9178
:10F26000FF90EF9008950E94D9F8982F809138026E
:10F27000813049F0823091F091366CF490330CF08B
:10F280009053892F08958091C00085FFFCCF909303
:10F29000C60091369CF39755892F08958091C80038
:10F2A00085FFFCCF9093CE00E7CF1F930E9433F9E8
:10F2B000182F0E9433F91295107F810F1F91089526
:10F2C000982F20913802992339F0213031F02230E3
:10F2D00061F091509923C9F708958091C00087FF8C
:10F2E000FCCF8091C6009150F5CF8091C80087FF78
:10F2F000FCCF8091CE009150EDCF1F93182F0E942C
:10F30000D9F8803249F0809139028F5F80933902B9
:10F31000853091F11F910895809138028130B9F0C4
:10F320008230C1F78091C80085FFFCCF84E18093D3
:10F33000CE008091C80085FFFCCF1093CE00809155
:10F34000C80085FFFCCF80E18093CE00E3CF8091A1
:10F35000C00085FFFCCF84E18093C6008091C0008F
:10F3600085FFFCCF1093C6008091C00085FFFCCFC5
:10F3700080E18093C600CECFE0913A02F0913B024B
:10F3800009951F9108950E94D9F8803241F080912B
:10F3900039028F5F80933902853029F10895809179
:10F3A0003802813089F08230C9F78091C80085FF2A
:10F3B000FCCF84E18093CE008091C80085FFFCCF14
:10F3C00080E18093CE0008958091C00085FFFCCF3E
:10F3D00084E18093C6008091C00085FFFCCF80E16E
:10F3E0008093C6000895E0913A02F0913B0209959E
:10F3F000089540E951E08823A1F02F9A28EE33E0E8
:10F40000FA013197F1F721503040D1F72F9828EECB
:10F4100033E0FA013197F1F721503040D1F78150B4
:10F4200061F708952F923F924F925F926F927F9271
:10F430008F929F92AF92BF92CF92DF92EF92FF9204
:10F440000F931F93CF93DF93000081E080933802E6
:10F4500080E18093C4001092C5001092C00086E045
:10F460008093C20088E18093C1006898709A279ABF
:10F4700081E00E94F9F9E4E1EE2E7EE1D72E67E902
:10F48000C62E53E0B52E40E1A42E9924939431E486
:10F49000832E26E5722E92E5692E80E2582E09E42D
:10F4A000402E13E5312EB0E52B2E0E94D9F8803383
:10F4B000C9F1813309F452C0803409F4C8C08134E1
:10F4C00009F4EAC0823489F1853409F4CAC0803570
:10F4D00049F1823539F1813529F1853509F4ECC0DE
:10F4E000863509F409C1843609F428C1843709F442
:10F4F000ABC1853709F473C2863709F4D9C08132AC
:10F5000009F4B7C2809139028F5F80933902853048
:10F5100061F6E0913A02F0913B0209950E94D9F818
:10F52000803339F60E94C3F9C0CF2091380293E1AD
:10F5300005C0223061F09923A9F391502130C9F719
:10F540008091C00087FFFCCF8091C600F4CF8091EE
:10F55000C80087FFFCCF8091CE00EDCF0E94D9F884
:10F56000803281F6809138028130D1F1823009F009
:10F570009CCF8091C80085FFFCCFE092CE008091A7
:10F58000C80085FFFCCF8092CE008091C80085FF27
:10F59000FCCF7092CE008091C80085FFFCCF6092B6
:10F5A000CE008091C80085FFFCCF5092CE008091A4
:10F5B000C80085FFFCCF4092CE008091C80085FF37
:10F5C000FCCF3092CE008091C80085FFFCCF209206
:10F5D000CE008091C80085FFFCCFA092CE0065CF01
:10F5E0008091C00085FFFCCFE092C6008091C000F2
:10F5F00085FFFCCF8092C6008091C00085FFFCCFC4
:10F600007092C6008091C00085FFFCCF6092C6005A
:10F610008091C00085FFFCCF5092C6008091C00051
:10F6200085FFFCCF4092C6008091C00085FFFCCFD3
:10F630003092C6008091C00085FFFCCF2092C600AA
:10F640008091C00085FFFCCFA092C6002ECF0E9403
:10F65000D9F8863808F466CF0E94D9F80E94C3F919
:10F6600024CF2091380294E0213041F0223069F01B
:10F67000992309F457CF91502130C1F78091C000F0
:10F6800087FFFCCF8091C600F3CF8091C80087FF31
:10F69000FCCF8091CE00ECCF0E94D9F8803841F1A8
:10F6A000813809F447C0823809F4CAC08839E1F0CA
:10F6B00080E00E947DF9F9CE0E94D9F880933C0247
:10F6C0000E94D9F880933D020E94C3F9EECE0E94B9
:10F6D000D9F80E94D9F8182F0E94D9F8112309F4FB
:10F6E0007EC2113009F40AC283E00E947DF9DDCEAA
:10F6F00082E00E947DF9D9CE0E94D9F8803339F397
:10F700002091380292E0213039F0223061F09923C3
:10F7100079F291502130C9F78091C00087FFFCCF6A
:10F720008091C600F4CF8091C80087FFFCCF809104
:10F73000CE00EDCF81E00E947DF9B7CE0E94D9F8CE
:10F7400080933F030E94D9F880933E038091420347
:10F750008E7F809342030E94D9F8853409F4B3C1A7
:10F7600080913E0390913F03892B89F000E010E0E7
:10F770000E94D9F8F801E25CFD4F80830F5F1F4FB4
:10F7800080913E0390913F030817190788F30E9468
:10F79000D9F8803209F0B6CE8091420380FFB2C121
:10F7A00040913C0250913D02440F551F50933D0241
:10F7B00040933C0260913E0370913F0361157105D7
:10F7C000F1F080E090E09A01280F391FFC01E25C23
:10F7D000FD4FE081F999FECF1FBA32BD21BDE0BDDA
:10F7E0000FB6F894FA9AF99A0FBE01968617970702
:10F7F00050F3460F571F50933D0240933C028091B7
:10F800003802813081F0823009F04FCE8091C800FB
:10F8100085FFFCCFE092CE008091C80085FFFCCF31
:10F82000A092CE0042CE8091C00085FFFCCFE09236
:10F83000C6008091C00085FFFCCFA092C60035CEE7
:10F8400080E10E947DF931CE0E94D9F880933F0378
:10F850000E94D9F880933E0320913C0230913D02F2
:10F8600037FD46C1809142038D7F80934203220F72
:10F87000331F30933D0220933C020E94D9F8853417
:10F8800009F430C1809142038E7F809342030E942D
:10F89000D9F8803209F009CE60913802613009F45C
:10F8A0006FC0623009F473C000913E0310913F03B2
:10F8B0000115110509F440C080914203782F717041
:10F8C000F82EF69481E0F82240913C0250913D02DE
:10F8D00020E030E013C0FF2009F060C0FA019491ED
:10F8E000613009F43BC0623009F441C0CA0101969D
:10F8F0002F5F3F4FAC0120173107D0F4772359F326
:10F90000F999FECF52BD41BDF89A90B56130F9F03A
:10F91000623061F78091C80085FFFCCF9093CE00E4
:10F92000CA0101962F5F3F4FAC012017310730F31A
:10F9300090933D0280933C02613009F4CAC062306A
:10F9400009F0B3CD8091C80085FFFCCF46CE8091F1
:10F95000C00085FFFCCF9093C600C8CF8091C00047
:10F9600085FDF9CF8091C00085FFF8CFF4CF80915D
:10F97000C80085FDD3CF8091C80085FFF8CFCECFDA
:10F980008091C00085FFFCCFE092C6008DCF8091B2
:10F99000C80085FFFCCFE092CE0086CFCA01A0E070
:10F9A000B0E080509040AF4FBF4FABBFFC0197918C
:10F9B000613061F0623009F099CF8091C80085FD17
:10F9C000ADCF8091C80085FFF8CFA8CF8091C0004F
:10F9D00085FDC1CF8091C00085FFF8CFBCCF0E94CC
:10F9E000D9F8803209F08ECD80913802813011F142
:10F9F000823009F05ACD8091C80085FFFCCFE0929B
:10FA0000CE008091C80085FFFCCFD092CE008091BF
:10FA1000C80085FFFCCFC092CE008091C80085FF52
:10FA2000FCCFB092CE008091C80085FFFCCFA092A1
:10FA3000CE003BCD8091C00085FFFCCFE092C60098
:10FA40008091C00085FFFCCFD092C6008091C0009D
:10FA500085FFFCCFC092C6008091C00085FFFCCF1F
:10FA6000B092C6008091C00085FFFCCFA092C60076
:10FA70001CCD0E94D9F8813209F017CD0E94D9F827
:10FA8000813209F012CD279A2F98109240032091CD
:10FA90003802E1E491E00EC0223009F4A4C0909352
:10FAA0004003E92FF0E0E050FE4FE0819F5FEE233E
:10FAB00009F4A0C0213081F78091C00085FFFCCF00
:10FAC000E093C600ECCF80914203816080934203B3
:10FAD00047CE8091C00085FDB7CD8091C00085FFE5
:10FAE000F8CFB2CD80914203816080934203CFCEA4
:10FAF00080914203826080934203B9CE87E90E94DD
:10FB00007DF9D3CC80913D028823880F880B892111
:10FB1000809341038BBF80913C0290913D02880FFE
:10FB2000991F90933D0280933C0280913E0380FF99
:10FB300009C080913E0390913F03019690933F034B
:10FB400080933E03F894F999FECF1127E0913C028F
:10FB5000F0913D02CEE3D2E080913E0390913F03CD
:10FB6000103091F40091570001700130D9F303E097
:10FB700000935700E8950091570001700130D9F3C8
:10FB800001E100935700E895099019900091570002
:10FB900001700130D9F301E000935700E895139507
:10FBA000103898F011270091570001700130D9F3F7
:10FBB00005E000935700E89500915700017001306F
:10FBC000D9F301E100935700E8953296029709F0C6
:10FBD000C7CF103011F00296E5CF112410CE8EE180
:10FBE0000E947DF962CC8091C80085FFFCCFE09334
:10FBF000CE0055CF7AE0B72E6DE0A62E5AE3952EB3
:10FC000040E2842E3DE3732E90E3692E81E3582E6B
:10FC1000213009F442C0223009F45FC00E94D9F8B3
:10FC2000982F20913802213089F1223009F44EC0FA
:10FC3000943709F46BC0923709F405C1973709F47A
:10FC40007BC0953799F0923609F4BDC09A3601F71A
:10FC5000E0913A02F0913B02099520913802D8CF09
:10FC60008091C00085FFFCCF9093C6000E94D9F818
:10FC7000982F80913802813099F38230B9F78091C2
:10FC8000C80085FFFCCF9093CE00F0CF8091C000DC
:10FC900085FFFCCF9093C600CBCF8091C00085FF3D
:10FCA000FCCFB092C6008091C00085FFFCCFA0922F
:10FCB000C6008091C00085FFFCCF9092C600809165
:10FCC000C00085FFFCCF8092C600A8CF8091C800FD
:10FCD00085FFFCCF9093CE00ABCF8091C80085FF0D
:10FCE000FCCFB092CE008091C80085FFFCCFA092DF
:10FCF000CE008091C80085FFFCCF9092CE0080910D
:10FD0000C80085FFFCCF8092CE0088CF1F9947C0E6
:10FD10002F9A213051F0223009F07ACF8091C8001B
:10FD200085FFFCCF6092CE0073CF8091C00085FF2D
:10FD3000FCCF6092C6006CCF0E94D9F8982F8091BA
:10FD400038028130F1F0823009F4ABC00E9455F9DD
:10FD5000082F0E9455F9182F0E94D9F8982F8091EA
:10FD600038028130A9F0823009F4A2C00E9455F90E
:10FD7000D02ECC24F601E10FF11D808320913802B2
:10FD800047CF8091C00085FFFCCF9093C600DECFA7
:10FD90008091C00085FFFCCF9093C600E7CF2F98DD
:10FDA000213051F0223009F033CF8091C80085FF17
:10FDB000FCCF5092CE002CCF8091C00085FFFCCFAD
:10FDC0005092C60025CF213041F1223081F080E8E9
:10FDD00085BF109274001092750080E091E1FC01E3
:10FDE000819180E091E13097D1F3CF01F8CF8091FC
:10FDF000C80085FFFCCF82E68093CE008091C800CA
:10FE000085FFFCCF85E78093CE008091C80085FFF9
:10FE1000FCCF83E78093CE00DACF8091C00085FFCE
:10FE2000FCCF82E68093C6008091C00085FFFCCFA6
:10FE300085E78093C6008091C00085FFFCCF83E7F3
:10FE40008093C600C4CF0E94D9F8982F80913802C1
:10FE50008130C9F08230D1F10E9455F9182F0E94EB
:10FE600055F9982F809138028130A1F0823039F114
:10FE7000F12EEE24F701E90FF11D80810E9494F824
:10FE800020913802C5CE8091C00085FFFCCF9093B1
:10FE9000C600E2CF8091C00085FFFCCF7092C60003
:10FEA000E7CF8091C80085FFFCCF9093CE004ECF66
:10FEB0008091C80085FFFCCF9093CE0057CF8091F2
:10FEC000C80085FFFCCF7092CE00D2CF8091C800D1
:0EFED00085FFFCCF9093CE00BFCFF894FFCFFC
:10FEDE0041546D656761424F4F54202F204172642B
:10FEEE0075696E6F204D656761202D20284329208E
:10FEFE0041726475696E6F204C4C43202D20303951
:08FF0E00303933300A0D008088
:040000031000F000F9
:00000001FF

View File

@ -0,0 +1,125 @@
:107800000C94343C0C94513C0C94513C0C94513CE1
:107810000C94513C0C94513C0C94513C0C94513CB4
:107820000C94513C0C94513C0C94513C0C94513CA4
:107830000C94513C0C94513C0C94513C0C94513C94
:107840000C94513C0C94513C0C94513C0C94513C84
:107850000C94513C0C94513C0C94513C0C94513C74
:107860000C94513C0C94513C11241FBECFEFD8E036
:10787000DEBFCDBF11E0A0E0B1E0ECE9FFE702C060
:1078800005900D92A230B107D9F712E0A2E0B1E065
:1078900001C01D92AD30B107E1F70E942D3D0C945F
:1078A000CC3F0C94003C982F959595959595959582
:1078B000905D8F708A307CF0282F295A8091C0000B
:1078C00085FFFCCF9093C6008091C00085FFFCCF60
:1078D0002093C6000895282F205DF0CF982F809127
:1078E000C00085FFFCCF9093C6000895EF92FF92F1
:1078F0000F931F93EE24FF2487018091C00087FD22
:1079000017C00894E11CF11C011D111D81E4E8164B
:1079100082E4F8068FE0080780E0180770F3E09132
:107920000401F091050109958091C00087FFE9CF1E
:107930008091C6001F910F91FF90EF9008950E94D3
:10794000763C982F8091C00085FFFCCF9093C600B5
:1079500091362CF490330CF09053892F089597555D
:10796000892F08951F930E949F3C182F0E949F3CCF
:107970001295107F810F1F9108951F93182F882350
:1079800021F00E94763C1150E1F71F9108951F935A
:10799000182F0E94763C803249F0809103018F5F5E
:1079A000809303018530C1F01F9108958091C0003C
:1079B00085FFFCCF84E18093C6008091C00085FFE5
:1079C000FCCF1093C6008091C00085FFFCCF80E102
:1079D0008093C6001F910895E0910401F091050184
:1079E00009951F9108950E94763C803241F0809164
:1079F00003018F5F80930301853081F008958091AA
:107A0000C00085FFFCCF84E18093C6008091C00058
:107A100085FFFCCF80E18093C6000895E0910401CA
:107A2000F09105010995089540E951E08823A1F0FE
:107A30002D9A28EE33E0FA013197F1F721503040CA
:107A4000D1F72D9828EE33E0FA013197F1F7215064
:107A50003040D1F7815061F708953F924F925F9285
:107A60006F927F928F929F92AF92BF92CF92DF924E
:107A7000EF92FF920F931F93CF93DF93000080E16B
:107A80008093C4001092C50088E18093C10086E015
:107A90008093C2005098589A259A81E00E94143D24
:107AA00024E1F22E9EE1E92E85E9D82E0FE0C02ECA
:107AB00010E1B12EAA24A394B1E49B2EA6E58A2E50
:107AC000F2E57F2EE0E26E2E79E4572E63E5462E36
:107AD00050E5352E0E94763C8033B1F18133B9F107
:107AE000803409F46FC0813409F476C0823409F41B
:107AF00085C0853409F488C0803531F1823521F1A3
:107B0000813511F1853509F485C0863509F48DC0BC
:107B1000843609F496C0843709F403C1853709F423
:107B200072C1863709F466C0809103018F5F80932C
:107B30000301853079F6E0910401F0910501099582
:107B40000E94763C803351F60E94F33CC3CF0E94E2
:107B5000763C803249F78091C00085FFFCCFF092DF
:107B6000C6008091C00085FFFCCF9092C600809136
:107B7000C00085FFFCCF8092C6008091C00085FFC9
:107B8000FCCF7092C6008091C00085FFFCCF609250
:107B9000C6008091C00085FFFCCF5092C600809146
:107BA000C00085FFFCCF4092C6008091C00085FFD9
:107BB000FCCF3092C6008091C00085FFFCCFB09210
:107BC000C60088CF0E94763C863808F4BDCF0E945C
:107BD000763C0E94F33C7ECF0E94763C803809F4CC
:107BE0009CC0813809F40BC1823809F43CC1883942
:107BF00009F48FC080E00E94C73C6CCF84E10E94F2
:107C0000BD3C0E94F33C66CF85E00E94BD3C0E94D3
:107C1000F33C60CF0E94763C809306010E94763C44
:107C2000809307010E94F33C55CF0E94763C80333D
:107C300009F41DC183E00E94BD3C80E00E94C73C66
:107C400049CF0E94763C809309020E94763C809343
:107C5000080280910C028E7F80930C020E94763C79
:107C6000853409F415C18091080290910902892B8D
:107C700089F000E010E00E94763CF801E85FFE4FDA
:107C800080830F5F1F4F80910802909109020817AF
:107C9000190788F30E94763C803209F045CF809125
:107CA0000C0280FF01C16091060170910701660F0F
:107CB000771F7093070160930601A0910802B091AD
:107CC00009021097C9F0E8E0F1E09B01AD014E0F09
:107CD0005F1FF999FECF32BD21BD819180BDFA9A17
:107CE000F99A2F5F3F4FE417F50799F76A0F7B1F4B
:107CF00070930701609306018091C00085FFFCCF5F
:107D0000F092C6008091C00085FFFCCFB092C60003
:107D1000E1CE83E00E94C73CDDCE82E00E94C73CFA
:107D2000D9CE0E94763C809309020E94763C8093D3
:107D300008028091060190910701880F991F909386
:107D40000701809306010E94763C853409F4A6C0A1
:107D500080910C028E7F80930C020E94763C8032D0
:107D600009F0B8CE8091C00085FFFCCFF092C6002C
:107D7000609108027091090261157105B9F140E046
:107D800050E080910C02A82FA170B82FB27011C0E2
:107D9000BB2309F45CC0E0910601F0910701319624
:107DA000F0930701E09306014F5F5F4F46175707B7
:107DB000E8F4AA2369F3F999FECF209106013091E6
:107DC000070132BD21BDF89A90B58091C00085FFB2
:107DD000FCCF9093C6002F5F3F4F30930701209355
:107DE00006014F5F5F4F4617570718F38091C00099
:107DF00085FDE5CE8091C00085FFF8CFE0CE81E023
:107E00000E94C73C67CE0E94763C803209F08CCE3F
:107E10008091C00085FFFCCFF092C6008091C00029
:107E200085FFFCCFE092C6008091C00085FFFCCFAB
:107E3000D092C6008091C00085FFFCCFC092C600E2
:107E40008091C00085FFFCCFB092C60043CEE09188
:107E50000601F091070194918091C00085FFFCCF4D
:107E60009093C6009CCF80E10E94C73C33CE0E9415
:107E7000763C0E94763C182F0E94763C112309F430
:107E800083C0113009F484C08FE00E94C73C22CE29
:107E900080910C02816080930C02E5CE80910C02EF
:107EA000816080930C0259CF809107018823880F4D
:107EB000880B8A2180930B02809106019091070123
:107EC000880F991F90930701809306018091080203
:107ED00080FF09C080910802909109020196909359
:107EE000090280930802F894F999FECF1127E091D6
:107EF0000601F0910701C8E0D1E08091080290915D
:107F00000902103091F40091570001700130D9F34B
:107F100003E000935700E89500915700017001308D
:107F2000D9F301E100935700E89509901990009169
:107F3000570001700130D9F301E000935700E89534
:107F40001395103498F011270091570001700130FB
:107F5000D9F305E000935700E895009157000170B0
:107F60000130D9F301E100935700E895329602976A
:107F700009F0C7CF103011F00296E5CF112480919F
:107F8000C00085FFB9CEBCCE8EE10E94C73CA2CD19
:0C7F900085E90E94C73C9ECDF894FFCF0D
:027F9C00800063
:040000030000780081
:00000001FF

View File

@ -0,0 +1,124 @@
:107800000C94343C0C94513C0C94513C0C94513CE1
:107810000C94513C0C94513C0C94513C0C94513CB4
:107820000C94513C0C94513C0C94513C0C94513CA4
:107830000C94513C0C94513C0C94513C0C94513C94
:107840000C94513C0C94513C0C94513C0C94513C84
:107850000C94513C0C94513C0C94513C0C94513C74
:107860000C94513C0C94513C11241FBECFEFD8E036
:10787000DEBFCDBF11E0A0E0B1E0EAE8FFE702C063
:1078800005900D92A230B107D9F712E0A2E0B1E065
:1078900001C01D92AD30B107E1F70E942D3D0C945F
:1078A000C33F0C94003C982F95959595959595958B
:1078B000905D8F708A307CF0282F295A8091C0000B
:1078C00085FFFCCF9093C6008091C00085FFFCCF60
:1078D0002093C6000895282F205DF0CF982F809127
:1078E000C00085FFFCCF9093C6000895EF92FF92F1
:1078F0000F931F93EE24FF2487018091C00087FD22
:1079000017C00894E11CF11C011D111D81E2E8164D
:1079100081EAF80687E0080780E0180770F3E09135
:107920000401F091050109958091C00087FFE9CF1E
:107930008091C6001F910F91FF90EF9008950E94D3
:10794000763C982F8091C00085FFFCCF9093C600B5
:1079500091362CF490330CF09053892F089597555D
:10796000892F08951F930E949F3C182F0E949F3CCF
:107970001295107F810F1F9108951F93182F882350
:1079800021F00E94763C1150E1F71F9108951F935A
:10799000182F0E94763C803249F0809103018F5F5E
:1079A000809303018530C1F01F9108958091C0003C
:1079B00085FFFCCF84E18093C6008091C00085FFE5
:1079C000FCCF1093C6008091C00085FFFCCF80E102
:1079D0008093C6001F910895E0910401F091050184
:1079E00009951F9108950E94763C803241F0809164
:1079F00003018F5F80930301853081F008958091AA
:107A0000C00085FFFCCF84E18093C6008091C00058
:107A100085FFFCCF80E18093C6000895E0910401CA
:107A2000F09105010995089548EC50E08823A1F0F4
:107A30002D9A28EE33E0FA013197F1F721503040CA
:107A4000D1F72D9828EE33E0FA013197F1F7215064
:107A50003040D1F7815061F708953F924F925F9285
:107A60006F927F928F929F92AF92BF92CF92DF924E
:107A7000EF92FF920F931F93CF93DF93000082E06A
:107A80008093C00080E18093C4001092C50088E11B
:107A90008093C10086E08093C2005098589A259A3E
:107AA00081E00E94143D24E1F22E9EE1E92E85E959
:107AB000D82E0FE0C02E10E1B12EAA24A394B1E479
:107AC0009B2EA6E58A2EF2E57F2EE0E26E2E79E46B
:107AD000572E63E5462E50E5352E0E94763C8033C6
:107AE000B1F18133B9F1803409F46FC0813409F404
:107AF00076C0823409F485C0853409F488C08035A5
:107B000031F1823521F1813511F1853509F485C0D6
:107B1000863509F48DC0843609F496C0843709F49B
:107B200003C1853709F472C1863709F466C08091B4
:107B300003018F5F80930301853079F6E0910401A2
:107B4000F091050109950E94763C803351F60E9420
:107B5000F33CC3CF0E94763C803249F78091C0004D
:107B600085FFFCCFF092C6008091C00085FFFCCF5E
:107B70009092C6008091C00085FFFCCF8092C60025
:107B80008091C00085FFFCCF7092C6008091C0003C
:107B900085FFFCCF6092C6008091C00085FFFCCFBE
:107BA0005092C6008091C00085FFFCCF4092C60075
:107BB0008091C00085FFFCCF3092C6008091C0004C
:107BC00085FFFCCFB092C60088CF0E94763C8638F5
:107BD00008F4BDCF0E94763C0E94F33C7ECF0E9409
:107BE000763C803809F49CC0813809F40BC1823896
:107BF00009F430C1883909F48FC080E00E94C73C85
:107C00006CCF84E10E94BD3C0E94F33C66CF85E0CE
:107C10000E94BD3C0E94F33C60CF0E94763C809362
:107C200006010E94763C809307010E94F33C55CFE9
:107C30000E94763C803309F411C183E00E94BD3C70
:107C400080E00E94C73C49CF0E94763C80930902A5
:107C50000E94763C8093080280910C028E7F809374
:107C60000C020E94763C853409F409C18091080217
:107C700090910902892B89F000E010E00E94763C87
:107C8000F801E85FFE4F80830F5F1F4F809108026D
:107C9000909109020817190788F30E94763C8032F8
:107CA00009F045CF80910C0280FFF5C0609106017C
:107CB00070910701660F771F7093070160930601AB
:107CC000A0910802B09109021097C9F0E8E0F1E034
:107CD0009B01AD014E0F5F1FF999FECF32BD21BD53
:107CE000819180BDFA9AF99A2F5F3F4FE417F5070B
:107CF00099F76A0F7B1F70930701609306018091CB
:107D0000C00085FFFCCFF092C6008091C00085FFC7
:107D1000FCCFB092C600E1CE83E00E94C73CDDCE2E
:107D200082E00E94C73CD9CE0E94763C8093090233
:107D30000E94763C80930802809106019091070191
:107D4000880F991F90930701809306010E94763C4B
:107D5000853409F49AC080910C028E7F80930C02C6
:107D60000E94763C803209F0B8CE8091C00085FF39
:107D7000FCCFF092C600A0910802B09109021097C2
:107D8000C1F180910C02082F0170182F1695117007
:107D9000E0910601F0910701AF014F5F5F4FBA011B
:107DA00020E030E00023B1F4112339F49491809164
:107DB000C00085FFFCCF9093C6002F5F3F4FCB01E3
:107DC0000196FA012A173B0780F4BC014F5F5F4F11
:107DD000002351F3F999FECFF2BDE1BDF89A90B5B9
:107DE0008091C00085FFFCCFE6CF709307016093C0
:107DF00006018091C00085FDE5CE8091C00085FF21
:107E0000F8CFE0CE81E00E94C73C67CE0E94763C6E
:107E1000803209F08CCE8091C00085FFFCCFF092BB
:107E2000C6008091C00085FFFCCFE092C600809123
:107E3000C00085FFFCCFD092C6008091C00085FFB6
:107E4000FCCFC092C6008091C00085FFFCCFB092ED
:107E5000C60043CE80E10E94C73C3FCE0E94763CE4
:107E60000E94763C182F0E94763C112309F483C0AF
:107E7000113009F484C08FE00E94C73C2ECE80915F
:107E80000C02816080930C02F1CE80910C02816023
:107E900080930C0265CF809107018823880F880B9F
:107EA0008A2180930B028091060190910701880F2F
:107EB000991F90930701809306018091080280FF2B
:107EC00009C08091080290910902019690930902DD
:107ED00080930802F894F999FECF1127E0910601EA
:107EE000F0910701C8E0D1E0809108029091090269
:107EF000103091F40091570001700130D9F303E084
:107F000000935700E8950091570001700130D9F3B4
:107F100001E100935700E8950990199000915700EE
:107F200001700130D9F301E000935700E8951395F3
:107F3000103498F011270091570001700130D9F3E7
:107F400005E000935700E89500915700017001305B
:107F5000D9F301E100935700E8953296029709F0B2
:107F6000C7CF103011F00296E5CF11248091C000E8
:107F700085FFC5CEC8CE8EE10E94C73CAECD85E957
:0A7F80000E94C73CAACDF894FFCF81
:027F8A00800075
:040000030000780081
:00000001FF

View File

@ -0,0 +1,126 @@
:103800000C94341C0C94511C0C94511C0C94511CA1
:103810000C94511C0C94511C0C94511C0C94511C74
:103820000C94511C0C94511C0C94511C0C94511C64
:103830000C94511C0C94511C0C94511C0C94511C54
:103840000C94511C0C94511C0C94511C0C94511C44
:103850000C94511C0C94511C0C94511C0C94511C34
:103860000C94511C0C94511C11241FBECFEFD4E0BA
:10387000DEBFCDBF11E0A0E0B1E0E4EAFFE302C0AB
:1038800005900D92A230B107D9F712E0A2E0B1E0A5
:1038900001C01D92AD30B107E1F70E94361D0C94B6
:1038A000D01F0C94001C982F9595959595959595FE
:1038B000905D8F708A307CF0282F295A8091C0004B
:1038C00085FFFCCF9093C6008091C00085FFFCCFA0
:1038D0002093C6000895282F205DF0CF982F809167
:1038E000C00085FFFCCF9093C6000895EF92FF9231
:1038F0000F931F93EE24FF2487018091C00087FD62
:1039000017C00894E11CF11C011D111D81E4E8168B
:1039100082E4F8068FE0080780E0180770F3E09172
:103920000401F091050109958091C00087FFE9CF5E
:103930008091C6001F910F91FF90EF9008950E9413
:10394000761C982F8091C00085FFFCCF9093C60015
:1039500091362CF490330CF09053892F089597559D
:10396000892F08951F930E949F1C182F0E949F1C4F
:103970001295107F810F1F910895882351F0982F81
:1039800091508091C00087FFFCCF8091C6009923A1
:10399000B9F708951F93182F0E94761C803249F0C2
:1039A000809103018F5F809303018530C1F01F91E7
:1039B00008958091C00085FFFCCF84E18093C6000C
:1039C0008091C00085FFFCCF1093C6008091C0009D
:1039D00085FFFCCF80E18093C6001F910895E091A0
:1039E0000401F091050109951F9108950E94761C2C
:1039F000803241F0809103018F5F80930301853015
:103A000081F008958091C00085FFFCCF84E1809310
:103A1000C6008091C00085FFFCCF80E18093C60086
:103A20000895E0910401F09105010995089510921F
:103A30000A028823D1F090E040E951E02D9A28EE67
:103A400033E0FA013197F1F721503040D1F72D984A
:103A500028EE33E0FA013197F1F721503040D1F7E9
:103A60009F5F981758F380930A0208953F924F92F0
:103A70005F926F927F928F929F92AF92BF92CF92FE
:103A8000DF92EF92FF920F931F93CF93DF9300008B
:103A900083E38093C4001092C50088E18093C10045
:103AA00086E08093C2005098589A259A81E00E943F
:103AB000171D44E1F42E3EE1E32E24E9D22E96E0D8
:103AC000C92E80E1B82EAA24A39401E4902E16E515
:103AD000812EB2E57B2EA0E26A2EF9E45F2EE3E5AB
:103AE0004E2E70E5372E0E94761C8033B1F1813363
:103AF00009F441C0803409F479C0813409F48CC0E0
:103B0000823471F1853409F47BC0803531F182351E
:103B100021F1813511F1853509F48DC0863509F41F
:103B20009DC0843609F4AEC0843709F41BC18537C3
:103B300009F485C1863709F47AC0809103018F5F4B
:103B400080930301853079F6E0910401F09105013D
:103B500009950E94761C803351F60E94F61CC3CF53
:103B600093E18091C00087FFFCCF8091C60099232C
:103B7000A1F39150F6CF0E94761C8032F1F680912D
:103B8000C00085FFFCCFF092C6008091C00085FF89
:103B9000FCCF9092C6008091C00085FFFCCF809240
:103BA000C6008091C00085FFFCCF7092C600809156
:103BB000C00085FFFCCF6092C6008091C00085FFE9
:103BC000FCCF5092C6008091C00085FFFCCF409290
:103BD000C6008091C00085FFFCCF3092C600809166
:103BE000C00085FFFCCFB092C6007DCF0E94761C3E
:103BF000863808F4B2CF0E94761C0E94F61C73CF60
:103C000094E08091C00087FFFCCF8091C60099238B
:103C100009F4A3CF9150F5CF0E94761C8038D1F0E3
:103C2000813861F1823809F499C0883979F080E0EF
:103C30000E94CA1C58CF0E94761C809306010E94E5
:103C4000761C809307010E94F61C4DCF83E00E94F2
:103C5000CA1C49CF82E00E94CA1C45CF0E94761C34
:103C6000803309F486C192E08091C00087FFFCCFC9
:103C70008091C6009923D9F29150F6CF81E00E943D
:103C8000CA1C31CF0E94761C809309020E94761CC8
:103C90008093080280910C028E7F80930C020E9418
:103CA000761C853429F480910C02816080930C028B
:103CB0008091080290910902892B89F000E010E0C0
:103CC0000E94761CF801E85FFE4F80830F5F1F4F54
:103CD00080910802909109020817190788F30E9441
:103CE000761C803209F029CF80910C0280FFD1C070
:103CF0004091060150910701440F551F5093070151
:103D000040930601A0910802B09109021097C9F0F2
:103D1000E8E0F1E09A01BD016E0F7F1FF999FECF37
:103D200032BD21BD819180BDFA9AF99A2F5F3F4F34
:103D3000E617F70799F74A0F5B1F50930701409367
:103D400006018091C00085FFFCCFF092C6008091F3
:103D5000C00085FFFCCFB092C600C5CE80E10E94B6
:103D6000CA1CC1CE0E94761C809309020E94761C58
:103D7000809308028091060190910701880F991F96
:103D800090930701809306010E94761C853409F404
:103D90007AC080910C028E7F80930C020E94761C68
:103DA000803209F0A0CE8091C00085FFFCCFF09258
:103DB000C600A0910802B09109021097B9F1809154
:103DC0000C02182F1170082F0270E0910601F0917B
:103DD00007019F012F5F3F4FB90140E050E01123E1
:103DE000B1F4002339F494918091C00085FFFCCF99
:103DF0009093C6004F5F5F4FCB010196F9014A17C0
:103E00005B0780F4BC012F5F3F4F112351F3F999F9
:103E1000FECFF2BDE1BDF89A90B58091C00085FF5C
:103E2000FCCFE6CF70930701609306018091C0003C
:103E300085FDD9CE8091C00085FFF8CFD4CE0E94F9
:103E4000761C803209F079CE8091C00085FFFCCFCE
:103E5000F092C6008091C00085FFFCCFE092C600C2
:103E60008091C00085FFFCCFD092C6008091C00039
:103E700085FFFCCFC092C6008091C00085FFFCCFBB
:103E8000B092C60030CE80910C02816080930C020B
:103E900085CF809107018823880F880B8A21809322
:103EA0000B028091060190910701880F991F909352
:103EB0000701809306018091080280FF09C080916C
:103EC00008029091090201969093090280930802DA
:103ED000F894F999FECF1127E0910601F0910701BE
:103EE000C8E0D1E08091080290910902103091F46D
:103EF0000091570001700130D9F303E0009357009F
:103F0000E8950091570001700130D9F301E1009369
:103F10005700E89509901990009157000170013001
:103F2000D9F301E000935700E8951395103498F009
:103F300011270091570001700130D9F305E000937B
:103F40005700E8950091570001700130D9F301E165
:103F500000935700E8953296029709F0C7CF1030CA
:103F600011F00296E5CF11248091C00085FFE9CEC3
:103F7000ECCE0E94761C0E94761C182F0E94761CA4
:103F8000112351F0113021F086E00E94CA1CABCD04
:103F900084E90E94CA1CA7CD8EE10E94CA1CA3CD51
:043FA000F894FFCFC3
:023FA40080009B
:0400000300003800C1
:00000001FF

View File

@ -0,0 +1,110 @@
:103800000C94341C0C94511C0C94511C0C94511CA1
:103810000C94511C0C94511C0C94511C0C94511C74
:103820000C94511C0C94511C0C94511C0C94511C64
:103830000C94511C0C94511C0C94511C0C94511C54
:103840000C94511C0C94511C0C94511C0C94511C44
:103850000C94511C0C94511C0C94511C0C94511C34
:103860000C94511C0C94511C11241FBECFEFD4E0BA
:10387000DEBFCDBF11E0A0E0B1E0E4EAFEE302C0AC
:1038800005900D92A230B107D9F712E0A2E0B1E0A5
:1038900001C01D92AD30B107E1F70E94ED1C0C9400
:1038A000511F0C94001C482F10920A0280E08417CC
:1038B000E0F4582F2D9A28EE33E080E991E001974B
:1038C000F1F721503040C9F72D9828EE33E080E918
:1038D00091E00197F1F721503040C9F7852F8F5FB4
:1038E000582F841738F380930A020895EF92FF92BD
:1038F0000F931F93EE24FF2487018091C00087FD62
:1039000017C00894E11CF11C011D111D81E0E8168F
:1039100082E1F8068AE7080780E0180770F3E09173
:103920000201F091030109958091C00087FFE9CF62
:103930008091C600992787FD90951F910F91FF9068
:10394000EF900895982F8091C00085FFFCCF909351
:10395000C60008950E94761C803271F080910401A7
:103960008F5F80930401853009F00895E091020192
:10397000F09103010995089584E10E94A21C80E161
:103980000E94A21C0895CF93C82F0E94761C8032FB
:1039900041F0809104018F5F80930401853081F4B0
:1039A0000AC084E10E94A21C8C2F0E94A21C80E10C
:1039B0000E94A21C05C0E0910201F091030109954B
:1039C000CF910895CF93C82FC150CF3F21F00E94CF
:1039D000761CC150E0F7CF910895CFEFD4E0DEBF61
:1039E000CDBF000083E38093C4001092C50088E13E
:1039F0008093C10086E08093C2005098589A259A1F
:103A000083E00E94531C0E94761C8033B1F1813305
:103A1000B9F1803409F455C0813409F45BC08234B3
:103A200009F46DC0853409F470C0803531F18235F8
:103A300021F1813511F1853509F46BC0863509F422
:103A400073C0843609F47AC0843709F4CEC0853750
:103A500009F429C1863709F44AC0809104018F5FB7
:103A600080930401853079F6E0910201F091030121
:103A700009950E94761C803351F60E94AA1CC3CF80
:103A80000E94761CC82F803241F784E10E94A21C5C
:103A900081E40E94A21C86E50E94A21C82E50E948D
:103AA000A21C8C2F0E94A21C89E40E94A21C83E508
:103AB0000E94A21C80E50E94A21C80E10E94A21C20
:103AC000A2CF0E94761C8638C0F20E94761C0E940B
:103AD000AA1C99CF0E94761C803809F486C18138CF
:103AE00009F487C1823809F488C1883921F080E05F
:103AF0000E94C31C88CF83E00E94C31C84CF84E152
:103B00000E94E21C0E94AA1C7ECF85E00E94E21C5B
:103B1000F9CF0E94761C809306010E94761C809348
:103B200007010E94AA1C6FCF0E94761C803309F403
:103B3000CAC083E00E94E21C80E0DACF0E94761CBB
:103B4000809309020E94761C8093080280910C02E7
:103B50008E7F80930C020E94761C853409F4C4C0C9
:103B600000E010E0809108029091090218161906F1
:103B700070F4C8E0D1E00E94761C89930F5F1F4F5C
:103B8000809108029091090208171907A0F30E947A
:103B9000761C803209F061CF80910C0280FFAEC0AC
:103BA000E0910601F0910701EE0FFF1F00E010E029
:103BB00020910802309109021216130680F4A8E041
:103BC000B1E0F999FECFF2BDE1BD8D9180BDFA9AC9
:103BD000F99A31960F5F1F4F0217130790F3F09376
:103BE0000701E093060184E166CF0E94761C809372
:103BF00009020E94761C8093080280910601909130
:103C00000701880F991F90930701809306010E9476
:103C1000761C853409F46EC080910C028E7F8093EF
:103C20000C020E94761C803209F0EDCE84E10E94E5
:103C3000A21C00E010E02091080230910902121647
:103C4000130608F03ACFE0910601F0910701809148
:103C50000C0280FF1FC0F999FECFF2BDE1BDF89ABA
:103C600080B50E94A21CE0910601F09107013196F7
:103C7000F0930701E09306012091080230910902B8
:103C80000F5F1F4F0217130708F017CF80910C0228
:103C900080FDE1CF869580FFB4C03196F093070197
:103CA000E0930601EDCF0E94761C803209F0D5CE5C
:103CB00084E10E94A21C8EE10E94A21C84E90E9461
:103CC000A21C86E0F8CE0E94761C0E94761CC82FAB
:103CD0000E94761CCC2309F47CC0C13009F47DC05D
:103CE00086E00E94C31C8FCE80910C02816080937D
:103CF0000C0236CF80910C02816091CF8091070138
:103D000087FD6FC010920B02809106019091070110
:103D1000880F991F909307018093060180910802F4
:103D200080FF09C08091080290910902019690934A
:103D3000090280930802F894F999FECF1127E091C7
:103D40000601F0910701C8E0D1E08091080290914E
:103D50000902103091F40091570001700130D9F33D
:103D600003E000935700E89500915700017001307F
:103D7000D9F301E100935700E8950990199000915B
:103D8000570001700130D9F301E000935700E89526
:103D90001395103498F011270091570001700130ED
:103DA000D9F305E000935700E895009157000170A2
:103DB0000130D9F301E100935700E895329602975C
:103DC00009F0C7CF103011F00296E5CF112484E13D
:103DD00072CE8EE10E94C31C16CE84E90E94C31CE1
:103DE00012CE81E080930B028FCF82E00E94C31C31
:103DF0000ACE81E00E94C31C06CE80E10E94C31C53
:103E000002CE84910E94A21C2091080230910902E6
:103E1000E0910601F091070140CFCF930E94761CFC
:103E2000C82F0E94A21CC13614F0C75503C0C0336E
:103E30000CF0C0538C2F992787FD9095CF91089552
:103E40000F931F930E940D1F082F112707FD109538
:103E500002951295107F1027007F10270E940D1FDA
:103E6000800F992787FD90951F910F910895CF930B
:103E7000C82F85958595859585958A3034F0895A22
:103E8000CF70CA3034F0C95A05C0805DCF70CA30D7
:103E9000D4F7C05D0E94A21C8C2F0E94A21CCF915F
:043EA0000895FFCFB3
:023EA40080009C
:0400000300003800C1
:00000001FF

View File

@ -0,0 +1,126 @@
:103800000C94341C0C94511C0C94511C0C94511CA1
:103810000C94511C0C94511C0C94511C0C94511C74
:103820000C94511C0C94511C0C94511C0C94511C64
:103830000C94511C0C94511C0C94511C0C94511C54
:103840000C94511C0C94511C0C94511C0C94511C44
:103850000C94511C0C94511C0C94511C0C94511C34
:103860000C94511C0C94511C11241FBECFEFD4E0BA
:10387000DEBFCDBF11E0A0E0B1E0EEEAFFE302C0A1
:1038800005900D92A230B107D9F712E0A2E0B1E0A5
:1038900001C01D92AD30B107E1F70E94331D0C94B9
:1038A000D51F0C94001C982F9595959595959595F9
:1038B000905D8F708A307CF0282F295A8091C0004B
:1038C00085FFFCCF9093C6008091C00085FFFCCFA0
:1038D0002093C6000895282F205DF0CF982F809167
:1038E000C00085FFFCCF9093C6000895EF92FF9231
:1038F0000F931F93EE24FF2487018091C00087FD62
:1039000017C00894E11CF11C011D111D81E2E8168D
:1039100081EAF80687E0080780E0180770F3E09175
:103920000401F091050109958091C00087FFE9CF5E
:103930008091C6001F910F91FF90EF9008950E9413
:10394000761C982F8091C00085FFFCCF9093C60015
:1039500091362CF490330CF09053892F089597559D
:10396000892F08951F930E949F1C182F0E949F1C4F
:103970001295107F810F1F9108951F93182F882390
:1039800021F00E94761C1150E1F71F9108951F93BA
:10399000182F0E94761C803249F0809103018F5FBE
:1039A000809303018530C1F01F9108958091C0007C
:1039B00085FFFCCF84E18093C6008091C00085FF25
:1039C000FCCF1093C6008091C00085FFFCCF80E142
:1039D0008093C6001F910895E0910401F0910501C4
:1039E00009951F9108950E94761C803241F08091C4
:1039F00003018F5F80930301853081F008958091EA
:103A0000C00085FFFCCF84E18093C6008091C00098
:103A100085FFFCCF80E18093C6000895E09104010A
:103A2000F09105010995089510920A028823D1F0BA
:103A300090E048EC50E02D9A28EE33E0FA013197FF
:103A4000F1F721503040D1F72D9828EE33E0FA01FC
:103A50003197F1F721503040D1F79F5F981758F315
:103A600080930A0208953F924F925F926F927F92E5
:103A70008F929F92AF92BF92CF92DF92EF92FF927E
:103A80000F931F93CF93DF9394B714BE8091600080
:103A90008861809360001092600091FF0CC289E100
:103AA0008093C4001092C50088E18093C10086E035
:103AB0008093C2005098589A259A81E00E94141D64
:103AC00044E1F42E3EE1E32E24E9D22E96E0C92E05
:103AD00080E1B82EAA24A39401E4902E16E5812E4D
:103AE000B2E57B2EA0E26A2EF9E45F2EE3E54E2ECE
:103AF00070E5372E0E94761C8033B9F18133C1F115
:103B0000803409F470C0813409F477C0823409F438
:103B100086C0853409F489C0803539F1823529F1B0
:103B2000813509F4AFC1853509F485C0863509F4BE
:103B30008DC0843609F435C1843709F4C1C0853796
:103B400009F490C0863709F466C0809103018F5F45
:103B500080930301853071F6E0910401F091050135
:103B600009950E94761C803349F60E94F31CC2CF4F
:103B70000E94761C803249F78091C00085FFFCCFFF
:103B8000F092C6008091C00085FFFCCF9092C600E5
:103B90008091C00085FFFCCF8092C6008091C0005C
:103BA00085FFFCCF7092C6008091C00085FFFCCFDE
:103BB0006092C6008091C00085FFFCCF5092C60085
:103BC0008091C00085FFFCCF4092C6008091C0006C
:103BD00085FFFCCF3092C6008091C00085FFFCCFEE
:103BE000B092C60087CF0E94761C863808F4BDCFFD
:103BF0000E94761C0E94F31C7DCF0E94761C8038A8
:103C000009F45AC0813809F453C0823809F440C11C
:103C1000883909F449C080E00E94C71C6BCF84E159
:103C20000E94BD1C0E94F31C65CF85E00E94BD1C54
:103C30000E94F31C5FCF0E94761C809306010E94B5
:103C4000761C809307010E94F31C54CF0E94761CBF
:103C5000803309F421C183E00E94BD1C80E00E94F2
:103C6000C71C48CF0E94761C803209F06ECF80912D
:103C7000C00085FFFCCFF092C6008091C00085FF98
:103C8000FCCFE092C6008091C00085FFFCCFD092AF
:103C9000C6008091C00085FFFCCFC092C600809115
:103CA000C00085FFFCCF9CCF83E00E94C71C22CFC1
:103CB00081E00E94C71C1ECF82E00E94C71C1ACF61
:103CC0000E94761C809309020E94761C8093080251
:103CD0008091060190910701880F991F9093070129
:103CE000809306010E94761C853409F4C5C080913A
:103CF0000C028E7F80930C020E94761C803209F0A9
:103D0000F9CE8091C00085FFFCCFF092C600609193
:103D10000802709109026115710591F140E050E0CF
:103D200080910C02A82FA170B82FB27010C0BB23D5
:103D300061F1E0910601F09107013196F0930701DE
:103D4000E09306014F5F5F4F46175707C8F4AA2359
:103D500071F3F999FECF209106013091070132BD30
:103D600021BDF89A90B58091C00085FFFCCF90935B
:103D7000C6002F5F3F4F3093070120930601E2CF2B
:103D80008091C00085FFFCCF2BCFE0910601F09120
:103D9000070194918091C00085FFFCCF9093C600ED
:103DA000CCCF0E94761C809309020E94761C8093DF
:103DB000080280910C028E7F80930C020E94761C78
:103DC000853429F480910C02816080930C028091EB
:103DD000080290910902892B89F000E010E00E940E
:103DE000761CF801E85FFE4F80830F5F1F4F8091C4
:103DF0000802909109020817190788F30E94761C9F
:103E0000803209F0A2CE80910C0280FF62C0409106
:103E1000060150910701440F551F5093070140932D
:103E20000601609108027091090261157105C9F0DF
:103E3000E8E0F1E09A01DB01AE0FBF1FF999FECF78
:103E400032BD21BD819180BDFA9AF99A2F5F3F4F13
:103E5000EA17FB0799F7460F571F50930701409346
:103E600006018091C00085FFFCCFF092C6008091D2
:103E7000C00085FFFCCFB4CE80910C02816080939E
:103E80000C023ACF0E94F31C88E080936000FFCFC1
:103E900080E10E94C71C2ECE0E94761C0E94761CD8
:103EA000182F0E94761C112381F0113051F086E00A
:103EB0000E94C71C1FCEE0910401F09105010995F5
:103EC000EECD84E90E94C71C15CE8EE10E94C71C6E
:103ED00011CE809107018823880F880B8A21809357
:103EE0000B028091060190910701880F991F909312
:103EF0000701809306018091080280FF09C080912C
:103F00000802909109020196909309028093080299
:103F1000F894F999FECF1127E0910601F09107017D
:103F2000C8E0D1E08091080290910902103091F42C
:103F30000091570001700130D9F303E0009357005E
:103F4000E8950091570001700130D9F301E1009329
:103F50005700E895099019900091570001700130C1
:103F6000D9F301E000935700E8951395103498F0C9
:103F700011270091570001700130D9F305E000933B
:103F80005700E8950091570001700130D9F301E125
:103F900000935700E8953296029709F0C7CF10308A
:0E3FA00011F00296E5CF11245CCFF894FFCF0C
:023FAE00800091
:0400000300003800C1
:00000001FF

View File

@ -0,0 +1,224 @@
# Makefile for ATmegaBOOT
# E.Lins, 18.7.2005
# $Id$
#
# Instructions
#
# To make bootloader .hex file:
# make diecimila
# make lilypad
# make ng
# etc...
#
# To burn bootloader .hex file:
# make diecimila_isp
# make lilypad_isp
# make ng_isp
# etc...
# program name should not be changed...
PROGRAM = ATmegaBOOT_168
# enter the parameters for the avrdude isp tool
ISPTOOL = stk500v2
ISPPORT = usb
ISPSPEED = -b 115200
MCU_TARGET = atmega168
LDSECTION = --section-start=.text=0x3800
# the efuse should really be 0xf8; since, however, only the lower
# three bits of that byte are used on the atmega168, avrdude gets
# confused if you specify 1's for the higher bits, see:
# http://tinker.it/now/2007/02/24/the-tale-of-avrdude-atmega168-and-extended-bits-fuses/
#
# similarly, the lock bits should be 0xff instead of 0x3f (to
# unlock the bootloader section) and 0xcf instead of 0x0f (to
# lock it), but since the high two bits of the lock byte are
# unused, avrdude would get confused.
ISPFUSES = avrdude -c $(ISPTOOL) -p $(MCU_TARGET) -P $(ISPPORT) $(ISPSPEED) \
-e -u -U lock:w:0x3f:m -U efuse:w:0x$(EFUSE):m -U hfuse:w:0x$(HFUSE):m -U lfuse:w:0x$(LFUSE):m
ISPFLASH = avrdude -c $(ISPTOOL) -p $(MCU_TARGET) -P $(ISPPORT) $(ISPSPEED) \
-U flash:w:$(PROGRAM)_$(TARGET).hex -U lock:w:0x0f:m
STK500 = "C:\Program Files\Atmel\AVR Tools\STK500\Stk500.exe"
STK500-1 = $(STK500) -e -d$(MCU_TARGET) -pf -vf -if$(PROGRAM)_$(TARGET).hex \
-lFF -LFF -f$(HFUSE)$(LFUSE) -EF8 -ms -q -cUSB -I200kHz -s -wt
STK500-2 = $(STK500) -d$(MCU_TARGET) -ms -q -lCF -LCF -cUSB -I200kHz -s -wt
OBJ = $(PROGRAM).o
OPTIMIZE = -O2
DEFS =
LIBS =
CC = avr-gcc
# Override is only needed by avr-lib build system.
override CFLAGS = -g -Wall $(OPTIMIZE) -mmcu=$(MCU_TARGET) -DF_CPU=$(AVR_FREQ) $(DEFS)
override LDFLAGS = -Wl,$(LDSECTION)
#override LDFLAGS = -Wl,-Map,$(PROGRAM).map,$(LDSECTION)
OBJCOPY = avr-objcopy
OBJDUMP = avr-objdump
all:
lilypad: TARGET = lilypad
lilypad: CFLAGS += '-DMAX_TIME_COUNT=F_CPU>>1' '-DNUM_LED_FLASHES=3'
lilypad: AVR_FREQ = 8000000L
lilypad: $(PROGRAM)_lilypad.hex
lilypad_isp: lilypad
lilypad_isp: TARGET = lilypad
lilypad_isp: HFUSE = DD
lilypad_isp: LFUSE = E2
lilypad_isp: EFUSE = 00
lilypad_isp: isp
lilypad_resonator: TARGET = lilypad_resonator
lilypad_resonator: CFLAGS += '-DMAX_TIME_COUNT=F_CPU>>4' '-DNUM_LED_FLASHES=3'
lilypad_resonator: AVR_FREQ = 8000000L
lilypad_resonator: $(PROGRAM)_lilypad_resonator.hex
lilypad_resonator_isp: lilypad_resonator
lilypad_resonator_isp: TARGET = lilypad_resonator
lilypad_resonator_isp: HFUSE = DD
lilypad_resonator_isp: LFUSE = C6
lilypad_resonator_isp: EFUSE = 00
lilypad_resonator_isp: isp
pro8: TARGET = pro_8MHz
pro8: CFLAGS += '-DMAX_TIME_COUNT=F_CPU>>4' '-DNUM_LED_FLASHES=1' '-DWATCHDOG_MODS'
pro8: AVR_FREQ = 8000000L
pro8: $(PROGRAM)_pro_8MHz.hex
pro8_isp: pro8
pro8_isp: TARGET = pro_8MHz
pro8_isp: HFUSE = DD
pro8_isp: LFUSE = C6
pro8_isp: EFUSE = 00
pro8_isp: isp
pro16: TARGET = pro_16MHz
pro16: CFLAGS += '-DMAX_TIME_COUNT=F_CPU>>4' '-DNUM_LED_FLASHES=1' '-DWATCHDOG_MODS'
pro16: AVR_FREQ = 16000000L
pro16: $(PROGRAM)_pro_16MHz.hex
pro16_isp: pro16
pro16_isp: TARGET = pro_16MHz
pro16_isp: HFUSE = DD
pro16_isp: LFUSE = C6
pro16_isp: EFUSE = 00
pro16_isp: isp
pro20: TARGET = pro_20mhz
pro20: CFLAGS += '-DMAX_TIME_COUNT=F_CPU>>4' '-DNUM_LED_FLASHES=1' '-DWATCHDOG_MODS'
pro20: AVR_FREQ = 20000000L
pro20: $(PROGRAM)_pro_20mhz.hex
pro20_isp: pro20
pro20_isp: TARGET = pro_20mhz
pro20_isp: HFUSE = DD
pro20_isp: LFUSE = C6
pro20_isp: EFUSE = 00
pro20_isp: isp
diecimila: TARGET = diecimila
diecimila: CFLAGS += '-DMAX_TIME_COUNT=F_CPU>>4' '-DNUM_LED_FLASHES=1'
diecimila: AVR_FREQ = 16000000L
diecimila: $(PROGRAM)_diecimila.hex
diecimila_isp: diecimila
diecimila_isp: TARGET = diecimila
diecimila_isp: HFUSE = DD
diecimila_isp: LFUSE = FF
diecimila_isp: EFUSE = 00
diecimila_isp: isp
ng: TARGET = ng
ng: CFLAGS += '-DMAX_TIME_COUNT=F_CPU>>1' '-DNUM_LED_FLASHES=3'
ng: AVR_FREQ = 16000000L
ng: $(PROGRAM)_ng.hex
ng_isp: ng
ng_isp: TARGET = ng
ng_isp: HFUSE = DD
ng_isp: LFUSE = FF
ng_isp: EFUSE = 00
ng_isp: isp
atmega328: TARGET = atmega328
atmega328: MCU_TARGET = atmega328p
atmega328: CFLAGS += '-DMAX_TIME_COUNT=F_CPU>>4' '-DNUM_LED_FLASHES=1' -DBAUD_RATE=57600
atmega328: AVR_FREQ = 16000000L
atmega328: LDSECTION = --section-start=.text=0x7800
atmega328: $(PROGRAM)_atmega328.hex
atmega328_isp: atmega328
atmega328_isp: TARGET = atmega328
atmega328_isp: MCU_TARGET = atmega328p
atmega328_isp: HFUSE = DA
atmega328_isp: LFUSE = FF
atmega328_isp: EFUSE = 05
atmega328_isp: isp
atmega328_pro8: TARGET = atmega328_pro_8MHz
atmega328_pro8: MCU_TARGET = atmega328p
atmega328_pro8: CFLAGS += '-DMAX_TIME_COUNT=F_CPU>>4' '-DNUM_LED_FLASHES=1' -DBAUD_RATE=57600 -DDOUBLE_SPEED
atmega328_pro8: AVR_FREQ = 8000000L
atmega328_pro8: LDSECTION = --section-start=.text=0x7800
atmega328_pro8: $(PROGRAM)_atmega328_pro_8MHz.hex
atmega328_pro8_isp: atmega328_pro8
atmega328_pro8_isp: TARGET = atmega328_pro_8MHz
atmega328_pro8_isp: MCU_TARGET = atmega328p
atmega328_pro8_isp: HFUSE = DA
atmega328_pro8_isp: LFUSE = FF
atmega328_pro8_isp: EFUSE = 05
atmega328_pro8_isp: isp
mega: TARGET = atmega1280
mega: MCU_TARGET = atmega1280
mega: CFLAGS += '-DMAX_TIME_COUNT=F_CPU>>4' '-DNUM_LED_FLASHES=0' -DBAUD_RATE=57600
mega: AVR_FREQ = 16000000L
mega: LDSECTION = --section-start=.text=0x1F000
mega: $(PROGRAM)_atmega1280.hex
mega_isp: mega
mega_isp: TARGET = atmega1280
mega_isp: MCU_TARGET = atmega1280
mega_isp: HFUSE = DA
mega_isp: LFUSE = FF
mega_isp: EFUSE = F5
mega_isp: isp
isp: $(TARGET)
$(ISPFUSES)
$(ISPFLASH)
isp-stk500: $(PROGRAM)_$(TARGET).hex
$(STK500-1)
$(STK500-2)
%.elf: $(OBJ)
$(CC) $(CFLAGS) $(LDFLAGS) -o $@ $^ $(LIBS)
clean:
rm -rf *.o *.elf *.lst *.map *.sym *.lss *.eep *.srec *.bin *.hex
%.lst: %.elf
$(OBJDUMP) -h -S $< > $@
%.hex: %.elf
$(OBJCOPY) -j .text -j .data -O ihex $< $@
%.srec: %.elf
$(OBJCOPY) -j .text -j .data -O srec $< $@
%.bin: %.elf
$(OBJCOPY) -j .text -j .data -O binary $< $@

View File

@ -0,0 +1,507 @@
/**********************************************************/
/* Serial Bootloader for Atmel mega8 AVR Controller */
/* */
/* ATmegaBOOT.c */
/* */
/* Copyright (c) 2003, Jason P. Kyle */
/* */
/* Hacked by DojoCorp - ZGZ - MMX - IVR */
/* Hacked by David A. Mellis */
/* */
/* This program is free software; you can redistribute it */
/* and/or modify it under the terms of the GNU General */
/* Public License as published by the Free Software */
/* Foundation; either version 2 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 Public */
/* License for more details. */
/* */
/* You should have received a copy of the GNU General */
/* Public License along with this program; if not, write */
/* to the Free Software Foundation, Inc., */
/* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
/* */
/* Licence can be viewed at */
/* http://www.fsf.org/licenses/gpl.txt */
/* */
/* Target = Atmel AVR m8 */
/**********************************************************/
#include <inttypes.h>
#include <avr/io.h>
#include <avr/pgmspace.h>
#include <avr/eeprom.h>
#include <avr/interrupt.h>
#include <avr/delay.h>
//#define F_CPU 16000000
/* We, Malmoitians, like slow interaction
* therefore the slow baud rate ;-)
*/
//#define BAUD_RATE 9600
/* 6.000.000 is more or less 8 seconds at the
* speed configured here
*/
//#define MAX_TIME_COUNT 6000000
#define MAX_TIME_COUNT (F_CPU>>1)
///#define MAX_TIME_COUNT_MORATORY 1600000
/* SW_MAJOR and MINOR needs to be updated from time to time to avoid warning message from AVR Studio */
#define HW_VER 0x02
#define SW_MAJOR 0x01
#define SW_MINOR 0x12
// AVR-GCC compiler compatibility
// avr-gcc compiler v3.1.x and older doesn't support outb() and inb()
// if necessary, convert outb and inb to outp and inp
#ifndef outb
#define outb(sfr,val) (_SFR_BYTE(sfr) = (val))
#endif
#ifndef inb
#define inb(sfr) _SFR_BYTE(sfr)
#endif
/* defines for future compatibility */
#ifndef cbi
#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit))
#endif
#ifndef sbi
#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))
#endif
/* Adjust to suit whatever pin your hardware uses to enter the bootloader */
#define eeprom_rb(addr) eeprom_read_byte ((uint8_t *)(addr))
#define eeprom_rw(addr) eeprom_read_word ((uint16_t *)(addr))
#define eeprom_wb(addr, val) eeprom_write_byte ((uint8_t *)(addr), (uint8_t)(val))
/* Onboard LED is connected to pin PB5 */
#define LED_DDR DDRB
#define LED_PORT PORTB
#define LED_PIN PINB
#define LED PINB5
#define SIG1 0x1E // Yep, Atmel is the only manufacturer of AVR micros. Single source :(
#define SIG2 0x93
#define SIG3 0x07
#define PAGE_SIZE 0x20U //32 words
void putch(char);
char getch(void);
void getNch(uint8_t);
void byte_response(uint8_t);
void nothing_response(void);
union address_union {
uint16_t word;
uint8_t byte[2];
} address;
union length_union {
uint16_t word;
uint8_t byte[2];
} length;
struct flags_struct {
unsigned eeprom : 1;
unsigned rampz : 1;
} flags;
uint8_t buff[256];
//uint8_t address_high;
uint8_t pagesz=0x80;
uint8_t i;
//uint8_t bootuart0=0,bootuart1=0;
void (*app_start)(void) = 0x0000;
int main(void)
{
uint8_t ch,ch2;
uint16_t w;
//cbi(BL_DDR,BL);
//sbi(BL_PORT,BL);
asm volatile("nop\n\t");
/* check if flash is programmed already, if not start bootloader anyway */
//if(pgm_read_byte_near(0x0000) != 0xFF) {
/* check if bootloader pin is set low */
//if(bit_is_set(BL_PIN,BL)) app_start();
//}
/* initialize UART(s) depending on CPU defined */
/* m8 */
UBRRH = (((F_CPU/BAUD_RATE)/16)-1)>>8; // set baud rate
UBRRL = (((F_CPU/BAUD_RATE)/16)-1);
UCSRB = (1<<RXEN)|(1<<TXEN); // enable Rx & Tx
UCSRC = (1<<URSEL)|(1<<UCSZ1)|(1<<UCSZ0); // config USART; 8N1
//UBRRL = (uint8_t)(F_CPU/(BAUD_RATE*16L)-1);
//UBRRH = (F_CPU/(BAUD_RATE*16L)-1) >> 8;
//UCSRA = 0x00;
//UCSRC = 0x86;
//UCSRB = _BV(TXEN)|_BV(RXEN);
/* this was giving uisp problems, so I removed it; without it, the boot
works on with uisp and avrdude on the mac (at least). */
//putch('\0');
//uint32_t l;
//uint32_t time_count;
//time_count=0;
/* set LED pin as output */
sbi(LED_DDR,LED);
for (i = 0; i < 16; i++) {
outb(LED_PORT, inb(LED_PORT) ^ _BV(LED));
_delay_loop_2(0);
}
//for (l=0; l<40000000; l++)
//outb(LED_PORT, inb(LED_PORT) ^= _BV(LED));
/* flash onboard LED three times to signal entering of bootloader */
//for(i=0; i<3; ++i) {
//for(l=0; l<40000000; ++l);
//sbi(LED_PORT,LED);
//for(l=0; l<40000000; ++l);
//cbi(LED_PORT,LED);
//}
/* see comment at previous call to putch() */
//putch('\0'); // this line is needed for the synchronization of the programmer
/* forever */
for (;;) {
//if((inb(UCSRA) & _BV(RXC))){
/* get character from UART */
ch = getch();
/* A bunch of if...else if... gives smaller code than switch...case ! */
/* Hello is anyone home ? */
if(ch=='0') {
nothing_response();
}
/* Request programmer ID */
/* Not using PROGMEM string due to boot block in m128 being beyond 64kB boundry */
/* Would need to selectively manipulate RAMPZ, and it's only 9 characters anyway so who cares. */
else if(ch=='1') {
if (getch() == ' ') {
putch(0x14);
putch('A');
putch('V');
putch('R');
putch(' ');
putch('I');
putch('S');
putch('P');
putch(0x10);
}
}
/* AVR ISP/STK500 board commands DON'T CARE so default nothing_response */
else if(ch=='@') {
ch2 = getch();
if (ch2>0x85) getch();
nothing_response();
}
/* AVR ISP/STK500 board requests */
else if(ch=='A') {
ch2 = getch();
if(ch2==0x80) byte_response(HW_VER); // Hardware version
else if(ch2==0x81) byte_response(SW_MAJOR); // Software major version
else if(ch2==0x82) byte_response(SW_MINOR); // Software minor version
//else if(ch2==0x98) byte_response(0x03); // Unknown but seems to be required by avr studio 3.56
else byte_response(0x00); // Covers various unnecessary responses we don't care about
}
/* Device Parameters DON'T CARE, DEVICE IS FIXED */
else if(ch=='B') {
getNch(20);
nothing_response();
}
/* Parallel programming stuff DON'T CARE */
else if(ch=='E') {
getNch(5);
nothing_response();
}
/* Enter programming mode */
else if(ch=='P') {
nothing_response();
// FIXME: modified only here by DojoCorp, Mumbai, India, 20050626
//time_count=0; // exted the delay once entered prog.mode
}
/* Leave programming mode */
else if(ch=='Q') {
nothing_response();
//time_count=MAX_TIME_COUNT_MORATORY; // once the programming is done,
// we should start the application
// but uisp has problems with this,
// therefore we just change the times
// and give the programmer 1 sec to react
}
/* Erase device, don't care as we will erase one page at a time anyway. */
else if(ch=='R') {
nothing_response();
}
/* Set address, little endian. EEPROM in bytes, FLASH in words */
/* Perhaps extra address bytes may be added in future to support > 128kB FLASH. */
/* This might explain why little endian was used here, big endian used everywhere else. */
else if(ch=='U') {
address.byte[0] = getch();
address.byte[1] = getch();
nothing_response();
}
/* Universal SPI programming command, disabled. Would be used for fuses and lock bits. */
else if(ch=='V') {
getNch(4);
byte_response(0x00);
}
/* Write memory, length is big endian and is in bytes */
else if(ch=='d') {
length.byte[1] = getch();
length.byte[0] = getch();
flags.eeprom = 0;
if (getch() == 'E') flags.eeprom = 1;
for (w=0;w<length.word;w++) {
buff[w] = getch(); // Store data in buffer, can't keep up with serial data stream whilst programming pages
}
if (getch() == ' ') {
if (flags.eeprom) { //Write to EEPROM one byte at a time
for(w=0;w<length.word;w++) {
eeprom_wb(address.word,buff[w]);
address.word++;
}
} else { //Write to FLASH one page at a time
//if (address.byte[1]>127) address_high = 0x01; //Only possible with m128, m256 will need 3rd address byte. FIXME
//else address_high = 0x00;
//address.word = address.word << 1; //address * 2 -> byte location
//if ((length.byte[0] & 0x01)) length.word++; //Even up an odd number of bytes
cli(); //Disable interrupts, just to be sure
while(bit_is_set(EECR,EEWE)); //Wait for previous EEPROM writes to complete
asm volatile(
"clr r17 \n\t" //page_word_count
"lds r30,address \n\t" //Address of FLASH location (in words)
"lds r31,address+1 \n\t"
"lsl r30 \n\t" //address * 2 -> byte location
"rol r31 \n\t"
"ldi r28,lo8(buff) \n\t" //Start of buffer array in RAM
"ldi r29,hi8(buff) \n\t"
"lds r24,length \n\t" //Length of data to be written (in bytes)
"lds r25,length+1 \n\t"
"sbrs r24,0 \n\t" //Even up an odd number of bytes
"rjmp length_loop \n\t"
"adiw r24,1 \n\t"
"length_loop: \n\t" //Main loop, repeat for number of words in block
"cpi r17,0x00 \n\t" //If page_word_count=0 then erase page
"brne no_page_erase \n\t"
"rcall wait_spm \n\t"
// "wait_spm1: \n\t"
// "lds r16,%0 \n\t" //Wait for previous spm to complete
// "andi r16,1 \n\t"
// "cpi r16,1 \n\t"
// "breq wait_spm1 \n\t"
"ldi r16,0x03 \n\t" //Erase page pointed to by Z
"sts %0,r16 \n\t"
"spm \n\t"
"rcall wait_spm \n\t"
// "wait_spm2: \n\t"
// "lds r16,%0 \n\t" //Wait for previous spm to complete
// "andi r16,1 \n\t"
// "cpi r16,1 \n\t"
// "breq wait_spm2 \n\t"
"ldi r16,0x11 \n\t" //Re-enable RWW section
"sts %0,r16 \n\t"
"spm \n\t"
"no_page_erase: \n\t"
"ld r0,Y+ \n\t" //Write 2 bytes into page buffer
"ld r1,Y+ \n\t"
"rcall wait_spm \n\t"
// "wait_spm3: \n\t"
// "lds r16,%0 \n\t" //Wait for previous spm to complete
// "andi r16,1 \n\t"
// "cpi r16,1 \n\t"
// "breq wait_spm3 \n\t"
"ldi r16,0x01 \n\t" //Load r0,r1 into FLASH page buffer
"sts %0,r16 \n\t"
"spm \n\t"
"inc r17 \n\t" //page_word_count++
"cpi r17,%1 \n\t"
"brlo same_page \n\t" //Still same page in FLASH
"write_page: \n\t"
"clr r17 \n\t" //New page, write current one first
"rcall wait_spm \n\t"
// "wait_spm4: \n\t"
// "lds r16,%0 \n\t" //Wait for previous spm to complete
// "andi r16,1 \n\t"
// "cpi r16,1 \n\t"
// "breq wait_spm4 \n\t"
"ldi r16,0x05 \n\t" //Write page pointed to by Z
"sts %0,r16 \n\t"
"spm \n\t"
"rcall wait_spm \n\t"
// "wait_spm5: \n\t"
// "lds r16,%0 \n\t" //Wait for previous spm to complete
// "andi r16,1 \n\t"
// "cpi r16,1 \n\t"
// "breq wait_spm5 \n\t"
"ldi r16,0x11 \n\t" //Re-enable RWW section
"sts %0,r16 \n\t"
"spm \n\t"
"same_page: \n\t"
"adiw r30,2 \n\t" //Next word in FLASH
"sbiw r24,2 \n\t" //length-2
"breq final_write \n\t" //Finished
"rjmp length_loop \n\t"
"wait_spm: \n\t"
"lds r16,%0 \n\t" //Wait for previous spm to complete
"andi r16,1 \n\t"
"cpi r16,1 \n\t"
"breq wait_spm \n\t"
"ret \n\t"
"final_write: \n\t"
"cpi r17,0 \n\t"
"breq block_done \n\t"
"adiw r24,2 \n\t" //length+2, fool above check on length after short page write
"rjmp write_page \n\t"
"block_done: \n\t"
"clr __zero_reg__ \n\t" //restore zero register
: "=m" (SPMCR) : "M" (PAGE_SIZE) : "r0","r16","r17","r24","r25","r28","r29","r30","r31");
/* Should really add a wait for RWW section to be enabled, don't actually need it since we never */
/* exit the bootloader without a power cycle anyhow */
}
putch(0x14);
putch(0x10);
}
}
/* Read memory block mode, length is big endian. */
else if(ch=='t') {
length.byte[1] = getch();
length.byte[0] = getch();
if (getch() == 'E') flags.eeprom = 1;
else {
flags.eeprom = 0;
address.word = address.word << 1; // address * 2 -> byte location
}
if (getch() == ' ') { // Command terminator
putch(0x14);
for (w=0;w < length.word;w++) { // Can handle odd and even lengths okay
if (flags.eeprom) { // Byte access EEPROM read
putch(eeprom_rb(address.word));
address.word++;
} else {
if (!flags.rampz) putch(pgm_read_byte_near(address.word));
address.word++;
}
}
putch(0x10);
}
}
/* Get device signature bytes */
else if(ch=='u') {
if (getch() == ' ') {
putch(0x14);
putch(SIG1);
putch(SIG2);
putch(SIG3);
putch(0x10);
}
}
/* Read oscillator calibration byte */
else if(ch=='v') {
byte_response(0x00);
}
// } else {
// time_count++;
// if (time_count>=MAX_TIME_COUNT) {
// app_start();
// }
// }
} /* end of forever loop */
}
void putch(char ch)
{
/* m8 */
while (!(inb(UCSRA) & _BV(UDRE)));
outb(UDR,ch);
}
char getch(void)
{
/* m8 */
uint32_t count = 0;
while(!(inb(UCSRA) & _BV(RXC))) {
/* HACKME:: here is a good place to count times*/
count++;
if (count > MAX_TIME_COUNT)
app_start();
}
return (inb(UDR));
}
void getNch(uint8_t count)
{
uint8_t i;
for(i=0;i<count;i++) {
/* m8 */
//while(!(inb(UCSRA) & _BV(RXC)));
//inb(UDR);
getch(); // need to handle time out
}
}
void byte_response(uint8_t val)
{
if (getch() == ' ') {
putch(0x14);
putch(val);
putch(0x10);
}
}
void nothing_response(void)
{
if (getch() == ' ') {
putch(0x14);
putch(0x10);
}
}
/* end of file ATmegaBOOT.c */

View File

@ -0,0 +1,66 @@
:101C000012C02BC02AC029C028C027C026C025C0AA
:101C100024C023C022C021C020C01FC01EC01DC0C0
:101C20001CC01BC01AC011241FBECFE5D4E0DEBF0C
:101C3000CDBF10E0A0E6B0E0E8EEFFE102C0059005
:101C40000D92A236B107D9F711E0A2E6B0E001C0CB
:101C50001D92AA36B107E1F74FC0D2CFEF92FF92A3
:101C60000F931F93EE24FF24870113C00894E11CF7
:101C7000F11C011D111D81E0E81682E1F8068AE7DA
:101C8000080780E0180728F0E0916200F0916300F7
:101C900009955F9BEBCF8CB1992787FD90951F919C
:101CA0000F91FF90EF9008955D9BFECF8CB9089542
:101CB000D5DF803221F484E1F7DF80E1F5DF08959C
:101CC0001F93182FCBDF803231F484E1EDDF812FB9
:101CD000EBDF80E1E9DF1F9108951F93CF93DF933E
:101CE000182FC0E0D0E002C0B9DF2196C117E0F3A1
:101CF000DF91CF911F910895CFE5D4E0DEBFCDBF36
:101D0000000010BC83E389B988E18AB986E880BD08
:101D1000BD9A1092680130E2E0E0F0E02FE088B375
:101D2000832788BBCF010197F1F7215027FFF7CF19
:101D300020E12093680192DF803381F1813399F4AF
:101D40008DDF8032C1F784E1AFDF81E4ADDF86E56E
:101D5000ABDF82E5A9DF80E2A7DF89E4A5DF83E5C9
:101D6000A3DF80E5C7C0803429F478DF8638B0F07F
:101D700075DF14C0813471F471DF803811F482E0B2
:101D80001DC1813811F481E019C1823809F015C1F3
:101D900082E114C1823421F484E19FDF89DFCBCF5B
:101DA000853411F485E0F9CF8035C1F38135B1F385
:101DB0008235A1F3853539F451DF809364004EDF1D
:101DC00080936500EBCF863519F484E086DFF5C09B
:101DD000843609F093C042DF809367013FDF809330
:101DE0006601809169018E7F8093690137DF8534B8
:101DF00029F480916901816080936901C0E0D0E09D
:101E000006E610E005C02ADFF80181938F012196D4
:101E10008091660190916701C817D907A0F31EDF72
:101E2000803209F088CF8091690180FF1FC020E0D7
:101E300030E0E6E6F0E012C0A0916400B0916500E9
:101E40008191082EC5D08091640090916500019623
:101E500090936500809364002F5F3F4F80916601EF
:101E6000909167012817390738F343C0F894E19936
:101E7000FECF1127E0916400F0916500EE0FFF1F87
:101E8000C6E6D0E0809166019091670180FF01C0B5
:101E90000196103051F422D003E000935700E895EA
:101EA0001DD001E100935700E8950990199016D0D4
:101EB00001E000935700E8951395103258F0112770
:101EC0000DD005E000935700E89508D001E100939C
:101ED0005700E8953296029739F0DBCF0091570012
:101EE00001700130D9F30895103011F00296E7CF58
:101EF000112484E1D9DE80E1D7DE1DCF843709F0DB
:101F00004BC0ACDE80936701A9DE80936601A6DE3C
:101F100090916901853421F49160909369010DC01D
:101F20009E7F909369018091640090916500880F75
:101F3000991F909365008093640090DE803209F0D1
:101F4000FACE84E1B1DEC0E0D0E01EC0809169012C
:101F500080FF07C0A0916400B091650031D0802D52
:101F600008C081FD07C0E0916400F0916500E49134
:101F70008E2F9ADE80916400909165000196909377
:101F800065008093640021968091660190916701BD
:101F9000C817D907D8F2AFCF853761F45FDE80323A
:101FA00009F0C9CE84E180DE8EE17EDE83E97CDE4D
:101FB00087E0A0CF863709F0BECE80E081DEBBCEC1
:101FC000E199FECFBFBBAEBBE09A11960DB208956A
:101FD000E199FECFBFBBAEBB0DBA11960FB6F89418
:081FE000E29AE19A0FBE089598
:021FE800800077
:0400000300001C00DD
:00000001FF

View File

@ -0,0 +1,88 @@
# Makefile for ATmegaBOOT
# E.Lins, 2004-10-14
# program name should not be changed...
PROGRAM = ATmegaBOOT
PRODUCT=atmega8
# enter the parameters for the UISP isp tool
ISPPARAMS = -dprog=stk500 -dserial=$(SERIAL) -dspeed=115200
#DIRAVR = /usr/local/avr
DIRAVRBIN = $(DIRAVR)/bin
DIRAVRUTILS = $(DIRAVR)/utils/bin
DIRINC = $(DIRAVR)/include
DIRLIB = $(DIRAVR)/avr/lib
MCU_TARGET = atmega8
LDSECTION = --section-start=.text=0x1c00
FUSE_L = 0xdf
FUSE_H = 0xca
ISPFUSES = $(DIRAVRBIN)/uisp -dpart=ATmega8 $(ISPPARAMS) --wr_fuse_l=$(FUSE_L) --wr_fuse_h=$(FUSE_H)
ISPFLASH = $(DIRAVRBIN)/uisp -dpart=ATmega8 $(ISPPARAMS) --erase --upload if=$(PROGRAM).hex -v
OBJ = $(PROGRAM).o
OPTIMIZE = -Os
DEFS = -DF_CPU=16000000 -DBAUD_RATE=19200
LIBS =
CC = $(DIRAVRBIN)/avr-gcc
# Override is only needed by avr-lib build system.
override CFLAGS = -g -Wall $(OPTIMIZE) -mmcu=$(MCU_TARGET) -D$(PRODUCT) $(DEFS) -I$(DIRINC)
override LDFLAGS = -Wl,-Map,$(PROGRAM).map,$(LDSECTION)
OBJCOPY = $(DIRAVRBIN)/avr-objcopy
OBJDUMP = $(DIRAVRBIN)/avr-objdump
SIZE = $(DIRAVRBIN)/avr-size
all: $(PROGRAM).elf lst text asm size
isp: $(PROGRAM).hex
$(ISPFUSES)
$(ISPFLASH)
$(PROGRAM).elf: $(OBJ)
$(CC) $(CFLAGS) $(LDFLAGS) -o $@ $^ $(LIBS)
clean:
rm -rf *.s
rm -rf *.o *.elf
rm -rf *.lst *.map
asm: $(PROGRAM).s
%.s: %.c
$(CC) -S $(CFLAGS) -g1 $^
lst: $(PROGRAM).lst
%.lst: %.elf
$(OBJDUMP) -h -S $< > $@
size: $(PROGRAM).hex
$(SIZE) $^
# Rules for building the .text rom images
text: hex bin srec
hex: $(PROGRAM).hex
bin: $(PROGRAM).bin
srec: $(PROGRAM).srec
%.hex: %.elf
$(OBJCOPY) -j .text -j .data -O ihex $< $@
%.srec: %.elf
$(OBJCOPY) -j .text -j .data -O srec $< $@
%.bin: %.elf
$(OBJCOPY) -j .text -j .data -O binary $< $@

View File

@ -0,0 +1,1032 @@
/**********************************************************/
/* Serial Bootloader for Atmel megaAVR Controllers */
/* */
/* tested with ATmega8, ATmega128 and ATmega168 */
/* should work with other mega's, see code for details */
/* */
/* ATmegaBOOT.c */
/* */
/* build: 050815 */
/* date : 15.08.2005 */
/* */
/* 20060802: hacked for Arduino by D. Cuartielles */
/* based on a previous hack by D. Mellis */
/* and D. Cuartielles */
/* */
/* Monitor and debug functions were added to the original */
/* code by Dr. Erik Lins, chip45.com. (See below) */
/* */
/* Thanks to Karl Pitrich for fixing a bootloader pin */
/* problem and more informative LED blinking! */
/* */
/* For the latest version see: */
/* http://www.chip45.com/ */
/* */
/* ------------------------------------------------------ */
/* */
/* based on stk500boot.c */
/* Copyright (c) 2003, Jason P. Kyle */
/* All rights reserved. */
/* see avr1.org for original file and information */
/* */
/* This program is free software; you can redistribute it */
/* and/or modify it under the terms of the GNU General */
/* Public License as published by the Free Software */
/* Foundation; either version 2 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 Public */
/* License for more details. */
/* */
/* You should have received a copy of the GNU General */
/* Public License along with this program; if not, write */
/* to the Free Software Foundation, Inc., */
/* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
/* */
/* Licence can be viewed at */
/* http://www.fsf.org/licenses/gpl.txt */
/* */
/* Target = Atmel AVR m128,m64,m32,m16,m8,m162,m163,m169, */
/* m8515,m8535. ATmega161 has a very small boot block so */
/* isn't supported. */
/* */
/* Tested with m128,m8,m163 - feel free to let me know */
/* how/if it works for you. */
/* */
/**********************************************************/
/* some includes */
#include <inttypes.h>
#include <avr/io.h>
#include <avr/pgmspace.h>
#include <avr/interrupt.h>
#include <avr/wdt.h>
#define set_output(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))
#define set_input(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit))
#define high(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))
#define low(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit))
/* the current avr-libc eeprom functions do not support the ATmega168 */
/* own eeprom write/read functions are used instead */
#ifndef __AVR_ATmega168__
#include <avr/eeprom.h>
#endif
/* define F_CPU according to AVR_FREQ set in Makefile */
/* Is there a better way to pass such a parameter from Makefile to source code ? */
#define F_CPU 16000000L
#include <util/delay.h>
/* 20060803: hacked by DojoCorp */
/* set the waiting time for the bootloader */
#define MAX_TIME_COUNT (F_CPU>>1)
/* set the UART baud rate */
/* 20060803: hacked by DojoCorp */
#define BAUD_RATE 115200
/* SW_MAJOR and MINOR needs to be updated from time to time to avoid warning message from AVR Studio */
/* never allow AVR Studio to do an update !!!! */
#define HW_VER 0x02
#define SW_MAJOR 0x01
#define SW_MINOR 0x0f
/* Adjust to suit whatever pin your hardware uses to enter the bootloader */
/* ATmega128 has two UARTS so two pins are used to enter bootloader and select UART */
/* BL0... means UART0, BL1... means UART1 */
#ifdef __AVR_ATmega128__
#define BL_DDR DDRF
#define BL_PORT PORTF
#define BL_PIN PINF
#define BL0 PINF7
#define BL1 PINF6
#else
/* other ATmegas have only one UART, so only one pin is defined to enter bootloader */
#define BL_DDR DDRD
#define BL_PORT PORTD
#define BL_PIN PIND
#define BL PIND6
#endif
/* onboard LED is used to indicate, that the bootloader was entered (3x flashing) */
/* if monitor functions are included, LED goes on after monitor was entered */
#ifdef __AVR_ATmega128__
/* Onboard LED is connected to pin PB7 (e.g. Crumb128, PROBOmega128, Savvy128) */
#define LED_DDR DDRB
#define LED_PORT PORTB
#define LED_PIN PINB
#define LED PINB7
#else
/* Onboard LED is connected to pin PB2 (e.g. Crumb8, Crumb168) */
#define LED_DDR DDRB
#define LED_PORT PORTB
#define LED_PIN PINB
/* 20060803: hacked by DojoCorp, LED pin is B5 in Arduino */
/* #define LED PINB2 */
#define LED PINB5
#endif
/* monitor functions will only be compiled when using ATmega128, due to bootblock size constraints */
#ifdef __AVR_ATmega128__
#define MONITOR
#endif
/* define various device id's */
/* manufacturer byte is always the same */
#define SIG1 0x1E // Yep, Atmel is the only manufacturer of AVR micros. Single source :(
#if defined __AVR_ATmega128__
#define SIG2 0x97
#define SIG3 0x02
#define PAGE_SIZE 0x80U //128 words
#elif defined __AVR_ATmega64__
#define SIG2 0x96
#define SIG3 0x02
#define PAGE_SIZE 0x80U //128 words
#elif defined __AVR_ATmega32__
#define SIG2 0x95
#define SIG3 0x02
#define PAGE_SIZE 0x40U //64 words
#elif defined __AVR_ATmega16__
#define SIG2 0x94
#define SIG3 0x03
#define PAGE_SIZE 0x40U //64 words
#elif defined __AVR_ATmega8__
#define SIG2 0x93
#define SIG3 0x07
#define PAGE_SIZE 0x20U //32 words
#elif defined __AVR_ATmega88__
#define SIG2 0x93
#define SIG3 0x0a
#define PAGE_SIZE 0x20U //32 words
#elif defined __AVR_ATmega168__
#define SIG2 0x94
#define SIG3 0x06
#define PAGE_SIZE 0x40U //64 words
#elif defined __AVR_ATmega162__
#define SIG2 0x94
#define SIG3 0x04
#define PAGE_SIZE 0x40U //64 words
#elif defined __AVR_ATmega163__
#define SIG2 0x94
#define SIG3 0x02
#define PAGE_SIZE 0x40U //64 words
#elif defined __AVR_ATmega169__
#define SIG2 0x94
#define SIG3 0x05
#define PAGE_SIZE 0x40U //64 words
#elif defined __AVR_ATmega8515__
#define SIG2 0x93
#define SIG3 0x06
#define PAGE_SIZE 0x20U //32 words
#elif defined __AVR_ATmega8535__
#define SIG2 0x93
#define SIG3 0x08
#define PAGE_SIZE 0x20U //32 words
#endif
/* function prototypes */
void putch(char);
char getch(void);
void getNch(uint8_t);
void byte_response(uint8_t);
void nothing_response(void);
char gethex(void);
void puthex(char);
void flash_led(uint8_t);
/* some variables */
union address_union {
uint16_t word;
uint8_t byte[2];
} address;
union length_union {
uint16_t word;
uint8_t byte[2];
} length;
struct flags_struct {
unsigned eeprom : 1;
unsigned rampz : 1;
} flags;
uint8_t buff[256];
uint8_t address_high;
uint8_t pagesz=0x80;
uint8_t i;
uint8_t bootuart = 0;
void (*app_start)(void) = 0x0000;
/* main program starts here */
int main(void)
{
uint8_t ch,ch2;
uint16_t w;
asm volatile("nop\n\t");
/* set pin direction for bootloader pin and enable pullup */
/* for ATmega128, two pins need to be initialized */
#ifdef __AVR_ATmega128__
BL_DDR &= ~_BV(BL0);
BL_DDR &= ~_BV(BL1);
BL_PORT |= _BV(BL0);
BL_PORT |= _BV(BL1);
#else
BL_DDR &= ~_BV(BL);
BL_PORT |= _BV(BL);
#endif
#ifdef __AVR_ATmega128__
/* check which UART should be used for booting */
if(bit_is_clear(BL_PIN, BL0)) {
bootuart = 1;
}
else if(bit_is_clear(BL_PIN, BL1)) {
bootuart = 2;
}
#endif
/* check if flash is programmed already, if not start bootloader anyway */
if(pgm_read_byte_near(0x0000) != 0xFF) {
#ifdef __AVR_ATmega128__
/* no UART was selected, start application */
if(!bootuart) {
app_start();
}
#else
/* check if bootloader pin is set low */
/* we don't start this part neither for the m8, nor m168 */
//if(bit_is_set(BL_PIN, BL)) {
// app_start();
// }
#endif
}
#ifdef __AVR_ATmega128__
/* no bootuart was selected, default to uart 0 */
if(!bootuart) {
bootuart = 1;
}
#endif
/* initialize UART(s) depending on CPU defined */
#ifdef __AVR_ATmega128__
if(bootuart == 1) {
UBRR0L = (uint8_t)(F_CPU/(BAUD_RATE*16L)-1);
UBRR0H = (F_CPU/(BAUD_RATE*16L)-1) >> 8;
UCSR0A = 0x00;
UCSR0C = 0x06;
UCSR0B = _BV(TXEN0)|_BV(RXEN0);
}
if(bootuart == 2) {
UBRR1L = (uint8_t)(F_CPU/(BAUD_RATE*16L)-1);
UBRR1H = (F_CPU/(BAUD_RATE*16L)-1) >> 8;
UCSR1A = 0x00;
UCSR1C = 0x06;
UCSR1B = _BV(TXEN1)|_BV(RXEN1);
}
#elif defined __AVR_ATmega163__
UBRR = (uint8_t)(F_CPU/(BAUD_RATE*16L)-1);
UBRRHI = (F_CPU/(BAUD_RATE*16L)-1) >> 8;
UCSRA = 0x00;
UCSRB = _BV(TXEN)|_BV(RXEN);
#elif defined __AVR_ATmega168__
UBRR0H = ((F_CPU / 16 + BAUD_RATE / 2) / BAUD_RATE - 1) >> 8;
UBRR0L = ((F_CPU / 16 + BAUD_RATE / 2) / BAUD_RATE - 1);
//UBRR0L = (uint8_t)(F_CPU/(BAUD_RATE*16L)-1);
//UBRR0H = (F_CPU/(BAUD_RATE*16L)-1) >> 8;
UCSR0B = (1<<RXEN0) | (1<<TXEN0);
UCSR0C = (1<<UCSZ00) | (1<<UCSZ01);
#elif defined __AVR_ATmega8__
/* m8 */
UBRRH = (((F_CPU/BAUD_RATE)/16)-1)>>8; // set baud rate
UBRRL = (((F_CPU/BAUD_RATE)/16)-1);
UCSRB = (1<<RXEN)|(1<<TXEN); // enable Rx & Tx
UCSRC = (1<<URSEL)|(1<<UCSZ1)|(1<<UCSZ0); // config USART; 8N1
#else
/* m16,m32,m169,m8515,m8535 */
UBRRL = (uint8_t)(F_CPU/(BAUD_RATE*16L)-1);
UBRRH = (F_CPU/(BAUD_RATE*16L)-1) >> 8;
UCSRA = 0x00;
UCSRC = 0x06;
UCSRB = _BV(TXEN)|_BV(RXEN);
#endif
/* set LED pin as output */
LED_DDR |= _BV(LED);
set_output(DDRD,PIND7);
high(PORTD,PD7);
for (i = 0; i < 16; i++) {
_delay_loop_2(0);
}
low(PORTD,PD7);
/* flash onboard LED to signal entering of bootloader */
#ifdef __AVR_ATmega128__
// 4x for UART0, 5x for UART1
flash_led(3 + bootuart);
#else
flash_led(3);
#endif
/* 20050803: by DojoCorp, this is one of the parts provoking the
system to stop listening, cancelled from the original */
//putch('\0');
//message("SET BT PAGEMODE 3 2000 1");
putch('S');
putch('E');
putch('T');
putch(' ');
putch('B');
putch('T');
putch(' ');
putch('P');
putch('A');
putch('G');
putch('E');
putch('M');
putch('O');
putch('D');
putch('E');
putch(' ');
putch('3');
putch(' ');
putch('2');
putch('0');
putch('0');
putch('0');
putch(' ');
putch('1');
putch(0x0D);
//put_s("SET BT ROLE 0 f 7d00");
putch('S');
putch('E');
putch('T');
putch(' ');
putch('B');
putch('T');
putch(' ');
putch('R');
putch('O');
putch('L');
putch('E');
putch(' ');
putch('0');
putch(' ');
putch('f');
putch(' ');
putch('7');
putch('d');
putch('0');
putch('0');
putch(0x0D);
/* forever loop */
for (;;) {
/* get character from UART */
ch = getch();
/* A bunch of if...else if... gives smaller code than switch...case ! */
/* Hello is anyone home ? */
if(ch=='0') {
nothing_response();
}
/* Request programmer ID */
/* Not using PROGMEM string due to boot block in m128 being beyond 64kB boundry */
/* Would need to selectively manipulate RAMPZ, and it's only 9 characters anyway so who cares. */
else if(ch=='1') {
if (getch() == ' ') {
putch(0x14);
putch('A');
putch('V');
putch('R');
putch(' ');
putch('I');
putch('S');
putch('P');
putch(0x10);
}
}
/* AVR ISP/STK500 board commands DON'T CARE so default nothing_response */
else if(ch=='@') {
ch2 = getch();
if (ch2>0x85) getch();
nothing_response();
}
/* AVR ISP/STK500 board requests */
else if(ch=='A') {
ch2 = getch();
if(ch2==0x80) byte_response(HW_VER); // Hardware version
else if(ch2==0x81) byte_response(SW_MAJOR); // Software major version
else if(ch2==0x82) byte_response(SW_MINOR); // Software minor version
else if(ch2==0x98) byte_response(0x03); // Unknown but seems to be required by avr studio 3.56
else byte_response(0x00); // Covers various unnecessary responses we don't care about
}
/* Device Parameters DON'T CARE, DEVICE IS FIXED */
else if(ch=='B') {
getNch(20);
nothing_response();
}
/* Parallel programming stuff DON'T CARE */
else if(ch=='E') {
getNch(5);
nothing_response();
}
/* Enter programming mode */
else if(ch=='P') {
nothing_response();
}
/* Leave programming mode */
else if(ch=='Q') {
nothing_response();
}
/* Erase device, don't care as we will erase one page at a time anyway. */
else if(ch=='R') {
nothing_response();
}
/* Set address, little endian. EEPROM in bytes, FLASH in words */
/* Perhaps extra address bytes may be added in future to support > 128kB FLASH. */
/* This might explain why little endian was used here, big endian used everywhere else. */
else if(ch=='U') {
address.byte[0] = getch();
address.byte[1] = getch();
nothing_response();
}
/* Universal SPI programming command, disabled. Would be used for fuses and lock bits. */
else if(ch=='V') {
getNch(4);
byte_response(0x00);
}
/* Write memory, length is big endian and is in bytes */
else if(ch=='d') {
length.byte[1] = getch();
length.byte[0] = getch();
flags.eeprom = 0;
if (getch() == 'E') flags.eeprom = 1;
for (w=0;w<length.word;w++) {
buff[w] = getch(); // Store data in buffer, can't keep up with serial data stream whilst programming pages
}
if (getch() == ' ') {
if (flags.eeprom) { //Write to EEPROM one byte at a time
for(w=0;w<length.word;w++) {
#ifdef __AVR_ATmega168__
while(EECR & (1<<EEPE));
EEAR = (uint16_t)(void *)address.word;
EEDR = buff[w];
EECR |= (1<<EEMPE);
EECR |= (1<<EEPE);
#else
eeprom_write_byte((void *)address.word,buff[w]);
#endif
address.word++;
}
}
else { //Write to FLASH one page at a time
if (address.byte[1]>127) address_high = 0x01; //Only possible with m128, m256 will need 3rd address byte. FIXME
else address_high = 0x00;
#ifdef __AVR_ATmega128__
RAMPZ = address_high;
#endif
address.word = address.word << 1; //address * 2 -> byte location
/* if ((length.byte[0] & 0x01) == 0x01) length.word++; //Even up an odd number of bytes */
if ((length.byte[0] & 0x01)) length.word++; //Even up an odd number of bytes
cli(); //Disable interrupts, just to be sure
// HACKME: EEPE used to be EEWE
while(bit_is_set(EECR,EEPE)); //Wait for previous EEPROM writes to complete
asm volatile(
"clr r17 \n\t" //page_word_count
"lds r30,address \n\t" //Address of FLASH location (in bytes)
"lds r31,address+1 \n\t"
"ldi r28,lo8(buff) \n\t" //Start of buffer array in RAM
"ldi r29,hi8(buff) \n\t"
"lds r24,length \n\t" //Length of data to be written (in bytes)
"lds r25,length+1 \n\t"
"length_loop: \n\t" //Main loop, repeat for number of words in block
"cpi r17,0x00 \n\t" //If page_word_count=0 then erase page
"brne no_page_erase \n\t"
"wait_spm1: \n\t"
"lds r16,%0 \n\t" //Wait for previous spm to complete
"andi r16,1 \n\t"
"cpi r16,1 \n\t"
"breq wait_spm1 \n\t"
"ldi r16,0x03 \n\t" //Erase page pointed to by Z
"sts %0,r16 \n\t"
"spm \n\t"
#ifdef __AVR_ATmega163__
".word 0xFFFF \n\t"
"nop \n\t"
#endif
"wait_spm2: \n\t"
"lds r16,%0 \n\t" //Wait for previous spm to complete
"andi r16,1 \n\t"
"cpi r16,1 \n\t"
"breq wait_spm2 \n\t"
"ldi r16,0x11 \n\t" //Re-enable RWW section
"sts %0,r16 \n\t"
"spm \n\t"
#ifdef __AVR_ATmega163__
".word 0xFFFF \n\t"
"nop \n\t"
#endif
"no_page_erase: \n\t"
"ld r0,Y+ \n\t" //Write 2 bytes into page buffer
"ld r1,Y+ \n\t"
"wait_spm3: \n\t"
"lds r16,%0 \n\t" //Wait for previous spm to complete
"andi r16,1 \n\t"
"cpi r16,1 \n\t"
"breq wait_spm3 \n\t"
"ldi r16,0x01 \n\t" //Load r0,r1 into FLASH page buffer
"sts %0,r16 \n\t"
"spm \n\t"
"inc r17 \n\t" //page_word_count++
"cpi r17,%1 \n\t"
"brlo same_page \n\t" //Still same page in FLASH
"write_page: \n\t"
"clr r17 \n\t" //New page, write current one first
"wait_spm4: \n\t"
"lds r16,%0 \n\t" //Wait for previous spm to complete
"andi r16,1 \n\t"
"cpi r16,1 \n\t"
"breq wait_spm4 \n\t"
#ifdef __AVR_ATmega163__
"andi r30,0x80 \n\t" // m163 requires Z6:Z1 to be zero during page write
#endif
"ldi r16,0x05 \n\t" //Write page pointed to by Z
"sts %0,r16 \n\t"
"spm \n\t"
#ifdef __AVR_ATmega163__
".word 0xFFFF \n\t"
"nop \n\t"
"ori r30,0x7E \n\t" // recover Z6:Z1 state after page write (had to be zero during write)
#endif
"wait_spm5: \n\t"
"lds r16,%0 \n\t" //Wait for previous spm to complete
"andi r16,1 \n\t"
"cpi r16,1 \n\t"
"breq wait_spm5 \n\t"
"ldi r16,0x11 \n\t" //Re-enable RWW section
"sts %0,r16 \n\t"
"spm \n\t"
#ifdef __AVR_ATmega163__
".word 0xFFFF \n\t"
"nop \n\t"
#endif
"same_page: \n\t"
"adiw r30,2 \n\t" //Next word in FLASH
"sbiw r24,2 \n\t" //length-2
"breq final_write \n\t" //Finished
"rjmp length_loop \n\t"
"final_write: \n\t"
"cpi r17,0 \n\t"
"breq block_done \n\t"
"adiw r24,2 \n\t" //length+2, fool above check on length after short page write
"rjmp write_page \n\t"
"block_done: \n\t"
"clr __zero_reg__ \n\t" //restore zero register
#if defined __AVR_ATmega168__
: "=m" (SPMCSR) : "M" (PAGE_SIZE) : "r0","r16","r17","r24","r25","r28","r29","r30","r31"
#else
: "=m" (SPMCR) : "M" (PAGE_SIZE) : "r0","r16","r17","r24","r25","r28","r29","r30","r31"
#endif
);
/* Should really add a wait for RWW section to be enabled, don't actually need it since we never */
/* exit the bootloader without a power cycle anyhow */
}
putch(0x14);
putch(0x10);
}
}
/* Read memory block mode, length is big endian. */
else if(ch=='t') {
length.byte[1] = getch();
length.byte[0] = getch();
#if defined __AVR_ATmega128__
if (address.word>0x7FFF) flags.rampz = 1; // No go with m256, FIXME
else flags.rampz = 0;
#endif
if (getch() == 'E') flags.eeprom = 1;
else {
flags.eeprom = 0;
address.word = address.word << 1; // address * 2 -> byte location
}
if (getch() == ' ') { // Command terminator
putch(0x14);
for (w=0;w < length.word;w++) { // Can handle odd and even lengths okay
if (flags.eeprom) { // Byte access EEPROM read
#ifdef __AVR_ATmega168__
while(EECR & (1<<EEPE));
EEAR = (uint16_t)(void *)address.word;
EECR |= (1<<EERE);
putch(EEDR);
#else
putch(eeprom_read_byte((void *)address.word));
#endif
address.word++;
}
else {
if (!flags.rampz) putch(pgm_read_byte_near(address.word));
#if defined __AVR_ATmega128__
else putch(pgm_read_byte_far(address.word + 0x10000));
// Hmmmm, yuck FIXME when m256 arrvies
#endif
address.word++;
}
}
putch(0x10);
}
}
/* Get device signature bytes */
else if(ch=='u') {
if (getch() == ' ') {
putch(0x14);
putch(SIG1);
putch(SIG2);
putch(SIG3);
putch(0x10);
}
}
/* Read oscillator calibration byte */
else if(ch=='v') {
byte_response(0x00);
}
#ifdef MONITOR
/* here come the extended monitor commands by Erik Lins */
/* check for three times exclamation mark pressed */
else if(ch=='!') {
ch = getch();
if(ch=='!') {
ch = getch();
if(ch=='!') {
#ifdef __AVR_ATmega128__
uint16_t extaddr;
#endif
uint8_t addrl, addrh;
#ifdef CRUMB128
PGM_P welcome = {"ATmegaBOOT / Crumb128 - (C) J.P.Kyle, E.Lins - 050815\n\r"};
#elif defined PROBOMEGA128
PGM_P welcome = {"ATmegaBOOT / PROBOmega128 - (C) J.P.Kyle, E.Lins - 050815\n\r"};
#elif defined SAVVY128
PGM_P welcome = {"ATmegaBOOT / Savvy128 - (C) J.P.Kyle, E.Lins - 050815\n\r"};
#endif
/* turn on LED */
LED_DDR |= _BV(LED);
LED_PORT &= ~_BV(LED);
/* print a welcome message and command overview */
for(i=0; welcome[i] != '\0'; ++i) {
putch(welcome[i]);
}
/* test for valid commands */
for(;;) {
putch('\n');
putch('\r');
putch(':');
putch(' ');
ch = getch();
putch(ch);
/* toggle LED */
if(ch == 't') {
if(bit_is_set(LED_PIN,LED)) {
LED_PORT &= ~_BV(LED);
putch('1');
} else {
LED_PORT |= _BV(LED);
putch('0');
}
}
/* read byte from address */
else if(ch == 'r') {
ch = getch(); putch(ch);
addrh = gethex();
addrl = gethex();
putch('=');
ch = *(uint8_t *)((addrh << 8) + addrl);
puthex(ch);
}
/* write a byte to address */
else if(ch == 'w') {
ch = getch(); putch(ch);
addrh = gethex();
addrl = gethex();
ch = getch(); putch(ch);
ch = gethex();
*(uint8_t *)((addrh << 8) + addrl) = ch;
}
/* read from uart and echo back */
else if(ch == 'u') {
for(;;) {
putch(getch());
}
}
#ifdef __AVR_ATmega128__
/* external bus loop */
else if(ch == 'b') {
putch('b');
putch('u');
putch('s');
MCUCR = 0x80;
XMCRA = 0;
XMCRB = 0;
extaddr = 0x1100;
for(;;) {
ch = *(volatile uint8_t *)extaddr;
if(++extaddr == 0) {
extaddr = 0x1100;
}
}
}
#endif
else if(ch == 'j') {
app_start();
}
}
/* end of monitor functions */
}
}
}
/* end of monitor */
#endif
}
/* end of forever loop */
}
char gethex(void) {
char ah,al;
ah = getch(); putch(ah);
al = getch(); putch(al);
if(ah >= 'a') {
ah = ah - 'a' + 0x0a;
} else if(ah >= '0') {
ah -= '0';
}
if(al >= 'a') {
al = al - 'a' + 0x0a;
} else if(al >= '0') {
al -= '0';
}
return (ah << 4) + al;
}
void puthex(char ch) {
char ah,al;
ah = (ch & 0xf0) >> 4;
if(ah >= 0x0a) {
ah = ah - 0x0a + 'a';
} else {
ah += '0';
}
al = (ch & 0x0f);
if(al >= 0x0a) {
al = al - 0x0a + 'a';
} else {
al += '0';
}
putch(ah);
putch(al);
}
void putch(char ch)
{
#ifdef __AVR_ATmega128__
if(bootuart == 1) {
while (!(UCSR0A & _BV(UDRE0)));
UDR0 = ch;
}
else if (bootuart == 2) {
while (!(UCSR1A & _BV(UDRE1)));
UDR1 = ch;
}
#elif defined __AVR_ATmega168__
while (!(UCSR0A & _BV(UDRE0)));
UDR0 = ch;
#else
/* m8,16,32,169,8515,8535,163 */
while (!(UCSRA & _BV(UDRE)));
UDR = ch;
#endif
}
char getch(void)
{
#ifdef __AVR_ATmega128__
if(bootuart == 1) {
while(!(UCSR0A & _BV(RXC0)));
return UDR0;
}
else if(bootuart == 2) {
while(!(UCSR1A & _BV(RXC1)));
return UDR1;
}
return 0;
#elif defined __AVR_ATmega168__
uint32_t count = 0;
while(!(UCSR0A & _BV(RXC0))){
/* 20060803 DojoCorp:: Addon coming from the previous Bootloader*/
/* HACKME:: here is a good place to count times*/
count++;
if (count > MAX_TIME_COUNT)
app_start();
}
return UDR0;
#else
/* m8,16,32,169,8515,8535,163 */
uint32_t count = 0;
while(!(UCSRA & _BV(RXC))){
/* 20060803 DojoCorp:: Addon coming from the previous Bootloader*/
/* HACKME:: here is a good place to count times*/
count++;
if (count > MAX_TIME_COUNT)
app_start();
}
return UDR;
#endif
}
void getNch(uint8_t count)
{
uint8_t i;
for(i=0;i<count;i++) {
#ifdef __AVR_ATmega128__
if(bootuart == 1) {
while(!(UCSR0A & _BV(RXC0)));
UDR0;
}
else if(bootuart == 2) {
while(!(UCSR1A & _BV(RXC1)));
UDR1;
}
#elif defined __AVR_ATmega168__
while(!(UCSR0A & _BV(RXC0)));
UDR0;
#else
/* m8,16,32,169,8515,8535,163 */
/* 20060803 DojoCorp:: Addon coming from the previous Bootloader*/
//while(!(UCSRA & _BV(RXC)));
//UDR;
uint8_t i;
for(i=0;i<count;i++) {
getch(); // need to handle time out
}
#endif
}
}
void byte_response(uint8_t val)
{
if (getch() == ' ') {
putch(0x14);
putch(val);
putch(0x10);
}
}
void nothing_response(void)
{
if (getch() == ' ') {
putch(0x14);
putch(0x10);
}
}
void flash_led(uint8_t count)
{
/* flash onboard LED three times to signal entering of bootloader */
uint32_t l;
if (count == 0) {
count = 3;
}
for (i = 0; i < count; ++i) {
LED_PORT |= _BV(LED);
for(l = 0; l < (2 * F_CPU); ++l);
LED_PORT &= ~_BV(LED);
for(l = 0; l < (F_CPU / 5); ++l);
}
}
/* end of file ATmegaBOOT.c */

View File

@ -0,0 +1,121 @@
:103800000C94341C0C944F1C0C944F1C0C944F1CA7
:103810000C944F1C0C944F1C0C944F1C0C944F1C7C
:103820000C944F1C0C944F1C0C944F1C0C944F1C6C
:103830000C944F1C0C944F1C0C944F1C0C944F1C5C
:103840000C944F1C0C944F1C0C944F1C0C944F1C4C
:103850000C944F1C0C944F1C0C944F1C0C944F1C3C
:103860000C944F1C0C944F1C11241FBECFEFD4E0BE
:10387000DEBFCDBF11E0A0E0B1E0E0E6FFE302C0B3
:1038800005900D92A230B107D9F712E0A2E0B1E0A5
:1038900001C01D92AC30B107E1F70C94D61C0C941A
:1038A000001C882309F483E01092090290E0981725
:1038B000F0F4692F2D9A2FEF37E448EE51E02253B0
:1038C00030404040504057FFFACF2D982FEF33ED56
:1038D00040E350E0225330404040504057FFFACF81
:1038E000962F9F5F692F981728F3909309020895E8
:1038F000982F8091C00085FFFCCF9093C60008955B
:10390000EF92FF920F931F93EE24FF248701809183
:10391000C00087FD17C00894E11CF11C011D111D9A
:1039200081E0E81682E1F8068AE7080780E01807D8
:1039300070F3E0910201F091030109958091C000BC
:1039400087FFE9CF8091C600992787FD90951F9149
:103950000F91FF90EF9008950E94801C803209F033
:10396000089584E10E94781C80E10E94781C0895EB
:10397000CF93C82F0E94801C803249F484E10E94BA
:10398000781C8C2F0E94781C80E10E94781CCF91BB
:103990000895282F90E007C08091C0008823E4F7A5
:1039A0008091C6009F5F9217B8F30895CFEFD4E0DF
:1039B000DEBFCDBF000056985E9A1092C50088E029
:1039C0008093C40088E18093C10086E08093C200A8
:1039D000259A579A5F9A109209022FE080E090E0B2
:1039E0000197F1F7215027FFF9CF20E12093090239
:1039F0005F9883E00E94511C83E50E94781C85E457
:103A00000E94781C84E50E94781C80E20E94781C49
:103A100082E40E94781C84E50E94781C80E20E9467
:103A2000781C80E50E94781C81E40E94781C87E461
:103A30000E94781C85E40E94781C8DE40E94781C0A
:103A40008FE40E94781C84E40E94781C85E40E9424
:103A5000781C80E20E94781C83E30E94781C80E23C
:103A60000E94781C82E30E94781C80E30E94781CEC
:103A700080E30E94781C80E30E94781C80E20E9410
:103A8000781C81E30E94781C8DE00E94781C83E5FD
:103A90000E94781C85E40E94781C84E50E94781CB2
:103AA00080E20E94781C82E40E94781C84E50E94D7
:103AB000781C80E20E94781C82E50E94781C8FE4CA
:103AC0000E94781C8CE40E94781C85E40E94781C7B
:103AD00080E20E94781C80E30E94781C80E20E94B1
:103AE000781C86E60E94781C80E20E94781C87E39E
:103AF0000E94781C84E60E94781C80E30E94781C57
:103B000080E30E94781C8DE00E94781C0E94801C3B
:103B1000803361F1813369F1803409F449C0813423
:103B200009F44FC0823409F45DC0853409F460C0E3
:103B30008035E1F08135D1F08235C1F0853509F469
:103B40005BC0863509F463C0843609F465C08437E8
:103B500009F4B9C0853709F414C18637B9F680E095
:103B60000E94B81C0E94801C8033A1F60E94AC1CED
:103B7000CDCF0E94801CC82F803241F684E10E9484
:103B8000781C81E40E94781C86E50E94781C82E5FE
:103B90000E94781C8C2F0E94781C89E40E94781C5B
:103BA00083E50E94781C80E50E94781C80E1ACCF00
:103BB0000E94801C8638D0F20E94801C0E94AC1C9F
:103BC000A5CF0E94801C803809F4EDC0813809F42B
:103BD000EEC0823809F4EFC0883909F683E00E940C
:103BE000B81CC0CF84E10E94C91C0E94AC1C8ECFBF
:103BF00085E00E94C91CF9CF0E94801C80930501BA
:103C00000E94801C809306010E94AC1C7FCF84E040
:103C10000E94C91C80E0A4CF0E94801C80930802EF
:103C20000E94801C8093070280910B028E7F8093FC
:103C30000B020E94801C853409F4C1C000E010E032
:103C400080910702909108021816190670F4C7E0D7
:103C5000D1E00E94801C89930F5F1F4F8091070263
:103C60009091080208171907A0F30E94801C803267
:103C700009F04CCF80910B0280FFADC000E010E056
:103C8000209107023091080212161306C0F4E09149
:103C90000501F0910601A7E0B1E0F999FECFF2BD70
:103CA000E1BD8D9180BDFA9AF99A31960F5F1F4F51
:103CB0000217130790F3F0930601E093050184E1E6
:103CC0000E94781C73CF0E94801C809308020E947F
:103CD000801C809307020E94801C853409F475C003
:103CE00080910B028E7F80930B0280910501909151
:103CF0000601880F991F90930601809305010E9489
:103D0000801C803209F002CF84E10E94781C00E020
:103D100010E020910702309108021216130608F0F5
:103D200045CFE0910501F091060180910B0280FFE3
:103D30001FC0F999FECFF2BDE1BDF89A80B50E948F
:103D4000781CE0910501F09106013196F09306018F
:103D5000E093050120910702309108020F5F1F4F89
:103D60000217130708F022CF80910B0280FDE1CFEC
:103D7000869580FF9BC03196F0930601E093050184
:103D8000EDCF0E94801C803209F0C0CE84E10E94F9
:103D9000781C8EE10E94781C84E90E94781C86E0E1
:103DA0000E94781C03CF82E00E94B81CDBCE81E029
:103DB0000E94B81CD7CE8FE00E94B81CD3CE809151
:103DC0000B02816080930B0239CF80910B028160DE
:103DD00080930B0294CF8091060187FD73C01092EF
:103DE0000A028091050190910601880F991F909316
:103DF0000601809305018091070280FF09C0809130
:103E0000070290910802019690930802809307029E
:103E1000F894F999FECF1127E0910501F091060180
:103E2000C7E0D1E08091070290910802103091F430
:103E30000091570001700130D9F303E0009357005F
:103E4000E8950091570001700130D9F301E100932A
:103E50005700E895099019900091570001700130C2
:103E6000D9F301E000935700E8951395103498F0CA
:103E700011270091570001700130D9F305E000933C
:103E80005700E8950091570001700130D9F301E126
:103E900000935700E8953296029709F0C7CF10308B
:103EA00011F00296E5CF112484E10ACF84910E949B
:103EB000781C2091070230910802E0910501F091F1
:103EC000060159CF81E080930A028BCF1F93CF93D5
:103ED0000E94801CC82F0E94781C0E94801C182FF2
:103EE0000E94781CC1362CF0C75511363CF017558E
:103EF00008C0C033D4F3C0531136CCF710330CF0E4
:103F00001053C295C07FC10F8C2F992787FD9095C4
:103F1000CF911F910895CF93282F992787FD9095D2
:103F2000807F9070959587959595879595958795C0
:103F3000959587958A303CF0895AC22FCF70CA3048
:103F40003CF0C95A06C0805DC22FCF70CA30CCF792
:103F5000C05D0E94781C8C2F0E94781CCF91089520
:023F60008000DF
:0400000300003800C1
:00000001FF

View File

@ -0,0 +1,117 @@
:103800000C94341C0C944F1C0C944F1C0C944F1CA7
:103810000C944F1C0C944F1C0C944F1C0C944F1C7C
:103820000C944F1C0C944F1C0C944F1C0C944F1C6C
:103830000C944F1C0C944F1C0C944F1C0C944F1C5C
:103840000C944F1C0C944F1C0C944F1C0C944F1C4C
:103850000C944F1C0C944F1C0C944F1C0C944F1C3C
:103860000C944F1C0C944F1C11241FBECFEFD4E0BE
:10387000DEBFCDBF11E0A0E0B1E0E8E1FFE302C0B0
:1038800005900D92A230B107D9F712E0A2E0B1E0A5
:1038900001C01D92AD30B107E1F70C94311D0C94BD
:1038A000001CCF93DF93CDB7DEB724970FB6F89403
:1038B000DEBF0FBECDBF382F882309F433E010924E
:1038C0000A02332309F44BC020E02D9A19821A8290
:1038D0001B821C8289819A81AB81BC8180549F416B
:1038E000A040B040A0F489819A81AB81BC8101964F
:1038F000A11DB11D89839A83AB83BC8389819A8181
:10390000AB81BC8180549F41A040B04060F32D98B2
:1039100019821A821B821C8289819A81AB81BC81A7
:1039200080549F41A040B040A0F489819A81AB812E
:10393000BC810196A11DB11D89839A83AB83BC8391
:1039400089819A81AB81BC8180549F41A040B04065
:1039500060F32F5F231708F4B8CF20930A02249650
:103960000FB6F894DEBF0FBECDBFDF91CF910895A3
:10397000EF92FF920F931F93EE24FF248701809113
:10398000C00087FD17C00894E11CF11C011D111D2A
:1039900081E0E81689E0F8068DE3080780E0180763
:1039A00070F3E0910201F091030109958091C0004C
:1039B00087FFE9CF8091C600992787FD90951F91D9
:1039C0000F91FF90EF900895982F8091C00085FF90
:1039D000FCCF9093C60008950E94B81C803271F00D
:1039E000809104018F5F80930401853009F0089570
:1039F000E0910201F09103010995089584E10E948C
:103A0000E41C80E10E94E41C08951F93182F0E947B
:103A1000B81C803269F0809104018F5F80930401AB
:103A2000853079F4E0910201F0910301099509C014
:103A300084E10E94E41C812F0E94E41C80E10E942A
:103A4000E41C1F910895282F882351F090E0809165
:103A5000C00087FFFCCF8091C6009F5F2917B9F790
:103A60000895CFEFD4E0DEBFCDBF000089E18093A1
:103A7000C4001092C50088E18093C10086E0809365
:103A8000C2005098589A259A83E00E94511C0E94C7
:103A9000B81C8033B1F18133B9F1803409F454C0DA
:103AA000813409F45AC0823409F469C0853409F4B8
:103AB0006CC0803531F1813521F1823511F18535C8
:103AC00009F4B2C0863509F4BAC0843609F463C07B
:103AD000843709F4BBC0853709F40EC1863709F471
:103AE0004AC0809104018F5F80930401853079F68C
:103AF000E0910201F091030109950E94B81C803306
:103B000051F60E94EC1CC3CF0E94B81C803249F7CA
:103B100084E10E94E41C81E40E94E41C86E50E948A
:103B2000E41C82E50E94E41C80E20E94E41C89E41B
:103B30000E94E41C83E50E94E41C80E50E94E41CD2
:103B400080E10E94E41CA3CF0E94B81C8638C8F212
:103B50000E94B81C0E94EC1C9ACF0E94B81C8038AE
:103B600009F4F7C0813809F4F8C0823809F4F9C0C3
:103B7000883909F4BDC080E00E94051D88CF84E12A
:103B80000E94231D0E94EC1C82CF85E00E94231D11
:103B90000E94EC1C7CCF0E94B81C809309020E94FA
:103BA000B81C8093080280910C028E7F80930C02D7
:103BB0000E94B81C853409F4C6C080910802909117
:103BC0000902892B09F0ADC00E94B81C803209F0AF
:103BD00088CF80910C0280FFC8C08091080290912C
:103BE00009020097D1F02091060130910701E8E029
:103BF000F1E0AC014E0F5F1FF999FECF32BD21BD40
:103C0000819180BDFA9AF99A2F5F3F4F4E175F0757
:103C100099F7309307012093060184E10E94E41C88
:103C200080E10E94E41C33CF0E94B81C80930601FF
:103C30000E94B81C809307010E94EC1C28CF84E0EE
:103C40000E94231D80E00E94051D21CF0E94B81C08
:103C5000809309020E94B81C809308020E94B81C3D
:103C6000853409F4F4C080910C028E7F80930C029D
:103C70008091060190910701880F991F9093070189
:103C8000809306010E94B81C803209F000CF84E1C5
:103C90000E94E41C2091080230910902211531058F
:103CA00019F1C0E0D0E0E0910601F09107018091A8
:103CB0000C0280FFC4C0F999FECFF2BDE1BDF89AB5
:103CC00080B50E94E41CE0910601F0910701319655
:103CD000F0930701E0930601209108023091090258
:103CE0002196C217D30718F380E10E94E41CCFCEBF
:103CF00083E00E94051DCBCE0E94B81C803209F0E3
:103D0000F0CE84E10E94E41C8EE10E94E41C84E970
:103D10000E94E41C86E00E94E41C80E10E94E41CF6
:103D2000B6CEC0E0D0E008E011E00E94B81CF80177
:103D300081938F0121968091080290910902C81702
:103D4000D90798F341CF80910C02816080930C02D7
:103D500034CF82E00E94051D9ACE81E00E94051DAD
:103D600096CE80E10E94051D92CE8091070187FDCD
:103D700080C010920B028091060190910701880F7C
:103D8000991F90930701809306018091080280FF9C
:103D900009C080910802909109020196909309024E
:103DA00080930802F894F999FECF1127E09106015B
:103DB000F0910701C8E0D1E08091080290910902DA
:103DC000103091F40091570001700130D9F303E0F5
:103DD00000935700E8950091570001700130D9F326
:103DE00001E100935700E895099019900091570060
:103DF00001700130D9F301E000935700E895139565
:103E0000103498F011270091570001700130D9F358
:103E100005E000935700E8950091570001700130CC
:103E2000D9F301E100935700E8953296029709F023
:103E3000C7CF103011F00296E5CF1124EECE81FFEE
:103E40000CC03196F0930701E093060149CF8091B1
:103E50000C02816080930C0215CF84910E94E41CB7
:103E60002091080230910902E0910601F0910701CA
:103E7000E8CF81E080930B027ECF0F931F930E94C7
:103E8000B81C182F0E94E41C0E94B81C082F0E9426
:103E9000E41C11362CF0175501363CF0075508C0CC
:103EA0001033D4F310530136CCF700330CF0005329
:103EB0001295107F100F812F992787FD90951F91E4
:103EC0000F9108951F93282F992787FD9095807F44
:103ED00090709595879595958795959587959595E6
:103EE00087958A304CF0982F995A822F8F708A309C
:103EF0004CF0182F195A08C0982F905D822F8F70A0
:103F00008A30BCF7182F105D892F0E94E41C812F86
:083F10000E94E41C1F910895BA
:023F1800800027
:0400000300003800C1
:00000001FF

View File

@ -0,0 +1,979 @@
/**********************************************************/
/* Serial Bootloader for Atmel megaAVR Controllers */
/* */
/* tested with ATmega8, ATmega128 and ATmega168 */
/* should work with other mega's, see code for details */
/* */
/* ATmegaBOOT.c */
/* */
/* 20070626: hacked for Arduino Diecimila (which auto- */
/* resets when a USB connection is made to it) */
/* by D. Mellis */
/* 20060802: hacked for Arduino by D. Cuartielles */
/* based on a previous hack by D. Mellis */
/* and D. Cuartielles */
/* */
/* Monitor and debug functions were added to the original */
/* code by Dr. Erik Lins, chip45.com. (See below) */
/* */
/* Thanks to Karl Pitrich for fixing a bootloader pin */
/* problem and more informative LED blinking! */
/* */
/* For the latest version see: */
/* http://www.chip45.com/ */
/* */
/* ------------------------------------------------------ */
/* */
/* based on stk500boot.c */
/* Copyright (c) 2003, Jason P. Kyle */
/* All rights reserved. */
/* see avr1.org for original file and information */
/* */
/* This program is free software; you can redistribute it */
/* and/or modify it under the terms of the GNU General */
/* Public License as published by the Free Software */
/* Foundation; either version 2 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 Public */
/* License for more details. */
/* */
/* You should have received a copy of the GNU General */
/* Public License along with this program; if not, write */
/* to the Free Software Foundation, Inc., */
/* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
/* */
/* Licence can be viewed at */
/* http://www.fsf.org/licenses/gpl.txt */
/* */
/* Target = Atmel AVR m128,m64,m32,m16,m8,m162,m163,m169, */
/* m8515,m8535. ATmega161 has a very small boot block so */
/* isn't supported. */
/* */
/* Tested with m168 */
/**********************************************************/
/* $Id$ */
/* some includes */
#include <inttypes.h>
#include <avr/io.h>
#include <avr/pgmspace.h>
#include <avr/interrupt.h>
#include <avr/wdt.h>
/* the current avr-libc eeprom functions do not support the ATmega168 */
/* own eeprom write/read functions are used instead */
#ifndef __AVR_ATmega168__
#include <avr/eeprom.h>
#endif
/* Use the F_CPU defined in Makefile */
/* 20060803: hacked by DojoCorp */
/* 20070626: hacked by David A. Mellis to decrease waiting time for auto-reset */
/* set the waiting time for the bootloader */
/* get this from the Makefile instead */
/* #define MAX_TIME_COUNT (F_CPU>>4) */
/* 20070707: hacked by David A. Mellis - after this many errors give up and launch application */
#define MAX_ERROR_COUNT 5
/* set the UART baud rate */
/* 20060803: hacked by DojoCorp */
//#define BAUD_RATE 115200
#define BAUD_RATE 19200
/* SW_MAJOR and MINOR needs to be updated from time to time to avoid warning message from AVR Studio */
/* never allow AVR Studio to do an update !!!! */
#define HW_VER 0x02
#define SW_MAJOR 0x01
#define SW_MINOR 0x10
/* Adjust to suit whatever pin your hardware uses to enter the bootloader */
/* ATmega128 has two UARTS so two pins are used to enter bootloader and select UART */
/* BL0... means UART0, BL1... means UART1 */
#ifdef __AVR_ATmega128__
#define BL_DDR DDRF
#define BL_PORT PORTF
#define BL_PIN PINF
#define BL0 PINF7
#define BL1 PINF6
#else
/* other ATmegas have only one UART, so only one pin is defined to enter bootloader */
#define BL_DDR DDRD
#define BL_PORT PORTD
#define BL_PIN PIND
#define BL PIND6
#endif
/* onboard LED is used to indicate, that the bootloader was entered (3x flashing) */
/* if monitor functions are included, LED goes on after monitor was entered */
#ifdef __AVR_ATmega128__
/* Onboard LED is connected to pin PB7 (e.g. Crumb128, PROBOmega128, Savvy128) */
#define LED_DDR DDRB
#define LED_PORT PORTB
#define LED_PIN PINB
#define LED PINB7
#else
/* Onboard LED is connected to pin PB2 (e.g. Crumb8, Crumb168) */
#define LED_DDR DDRB
#define LED_PORT PORTB
#define LED_PIN PINB
/* 20060803: hacked by DojoCorp, LED pin is B5 in Arduino */
/* #define LED PINB2 */
#define LED PINB5
#endif
/* monitor functions will only be compiled when using ATmega128, due to bootblock size constraints */
#ifdef __AVR_ATmega128__
#define MONITOR
#endif
/* define various device id's */
/* manufacturer byte is always the same */
#define SIG1 0x1E // Yep, Atmel is the only manufacturer of AVR micros. Single source :(
#if defined __AVR_ATmega128__
#define SIG2 0x97
#define SIG3 0x02
#define PAGE_SIZE 0x80U //128 words
#elif defined __AVR_ATmega64__
#define SIG2 0x96
#define SIG3 0x02
#define PAGE_SIZE 0x80U //128 words
#elif defined __AVR_ATmega32__
#define SIG2 0x95
#define SIG3 0x02
#define PAGE_SIZE 0x40U //64 words
#elif defined __AVR_ATmega16__
#define SIG2 0x94
#define SIG3 0x03
#define PAGE_SIZE 0x40U //64 words
#elif defined __AVR_ATmega8__
#define SIG2 0x93
#define SIG3 0x07
#define PAGE_SIZE 0x20U //32 words
#elif defined __AVR_ATmega88__
#define SIG2 0x93
#define SIG3 0x0a
#define PAGE_SIZE 0x20U //32 words
#elif defined __AVR_ATmega168__
#define SIG2 0x94
#define SIG3 0x06
#define PAGE_SIZE 0x40U //64 words
#elif defined __AVR_ATmega162__
#define SIG2 0x94
#define SIG3 0x04
#define PAGE_SIZE 0x40U //64 words
#elif defined __AVR_ATmega163__
#define SIG2 0x94
#define SIG3 0x02
#define PAGE_SIZE 0x40U //64 words
#elif defined __AVR_ATmega169__
#define SIG2 0x94
#define SIG3 0x05
#define PAGE_SIZE 0x40U //64 words
#elif defined __AVR_ATmega8515__
#define SIG2 0x93
#define SIG3 0x06
#define PAGE_SIZE 0x20U //32 words
#elif defined __AVR_ATmega8535__
#define SIG2 0x93
#define SIG3 0x08
#define PAGE_SIZE 0x20U //32 words
#endif
/* function prototypes */
void putch(char);
char getch(void);
void getNch(uint8_t);
void byte_response(uint8_t);
void nothing_response(void);
char gethex(void);
void puthex(char);
void flash_led(uint8_t);
/* some variables */
union address_union {
uint16_t word;
uint8_t byte[2];
} address;
union length_union {
uint16_t word;
uint8_t byte[2];
} length;
struct flags_struct {
unsigned eeprom : 1;
unsigned rampz : 1;
} flags;
uint8_t buff[256];
uint8_t address_high;
uint8_t pagesz=0x80;
uint8_t i;
uint8_t bootuart = 0;
uint8_t error_count = 0;
void (*app_start)(void) = 0x0000;
/* main program starts here */
int main(void)
{
uint8_t ch,ch2;
uint16_t w;
asm volatile("nop\n\t");
/* set pin direction for bootloader pin and enable pullup */
/* for ATmega128, two pins need to be initialized */
#ifdef __AVR_ATmega128__
BL_DDR &= ~_BV(BL0);
BL_DDR &= ~_BV(BL1);
BL_PORT |= _BV(BL0);
BL_PORT |= _BV(BL1);
#else
/* We run the bootloader regardless of the state of this pin. Thus, don't
put it in a different state than the other pins. --DAM, 070709
BL_DDR &= ~_BV(BL);
BL_PORT |= _BV(BL);
*/
#endif
#ifdef __AVR_ATmega128__
/* check which UART should be used for booting */
if(bit_is_clear(BL_PIN, BL0)) {
bootuart = 1;
}
else if(bit_is_clear(BL_PIN, BL1)) {
bootuart = 2;
}
#endif
/* check if flash is programmed already, if not start bootloader anyway */
if(pgm_read_byte_near(0x0000) != 0xFF) {
#ifdef __AVR_ATmega128__
/* no UART was selected, start application */
if(!bootuart) {
app_start();
}
#else
/* check if bootloader pin is set low */
/* we don't start this part neither for the m8, nor m168 */
//if(bit_is_set(BL_PIN, BL)) {
// app_start();
// }
#endif
}
#ifdef __AVR_ATmega128__
/* no bootuart was selected, default to uart 0 */
if(!bootuart) {
bootuart = 1;
}
#endif
/* initialize UART(s) depending on CPU defined */
#ifdef __AVR_ATmega128__
if(bootuart == 1) {
UBRR0L = (uint8_t)(F_CPU/(BAUD_RATE*16L)-1);
UBRR0H = (F_CPU/(BAUD_RATE*16L)-1) >> 8;
UCSR0A = 0x00;
UCSR0C = 0x06;
UCSR0B = _BV(TXEN0)|_BV(RXEN0);
}
if(bootuart == 2) {
UBRR1L = (uint8_t)(F_CPU/(BAUD_RATE*16L)-1);
UBRR1H = (F_CPU/(BAUD_RATE*16L)-1) >> 8;
UCSR1A = 0x00;
UCSR1C = 0x06;
UCSR1B = _BV(TXEN1)|_BV(RXEN1);
}
#elif defined __AVR_ATmega163__
UBRR = (uint8_t)(F_CPU/(BAUD_RATE*16L)-1);
UBRRHI = (F_CPU/(BAUD_RATE*16L)-1) >> 8;
UCSRA = 0x00;
UCSRB = _BV(TXEN)|_BV(RXEN);
#elif defined __AVR_ATmega168__
UBRR0L = (uint8_t)(F_CPU/(BAUD_RATE*16L)-1);
UBRR0H = (F_CPU/(BAUD_RATE*16L)-1) >> 8;
UCSR0B = (1<<RXEN0) | (1<<TXEN0);
UCSR0C = (1<<UCSZ00) | (1<<UCSZ01);
/* Enable internal pull-up resistor on pin D0 (RX), in order
to supress line noise that prevents the bootloader from
timing out (DAM: 20070509) */
DDRD &= ~_BV(PIND0);
PORTD |= _BV(PIND0);
#elif defined __AVR_ATmega8__
/* m8 */
UBRRH = (((F_CPU/BAUD_RATE)/16)-1)>>8; // set baud rate
UBRRL = (((F_CPU/BAUD_RATE)/16)-1);
UCSRB = (1<<RXEN)|(1<<TXEN); // enable Rx & Tx
UCSRC = (1<<URSEL)|(1<<UCSZ1)|(1<<UCSZ0); // config USART; 8N1
#else
/* m16,m32,m169,m8515,m8535 */
UBRRL = (uint8_t)(F_CPU/(BAUD_RATE*16L)-1);
UBRRH = (F_CPU/(BAUD_RATE*16L)-1) >> 8;
UCSRA = 0x00;
UCSRC = 0x06;
UCSRB = _BV(TXEN)|_BV(RXEN);
#endif
/* set LED pin as output */
LED_DDR |= _BV(LED);
/* flash onboard LED to signal entering of bootloader */
#ifdef __AVR_ATmega128__
// 4x for UART0, 5x for UART1
flash_led(NUM_LED_FLASHES + bootuart);
#else
flash_led(NUM_LED_FLASHES);
#endif
/* 20050803: by DojoCorp, this is one of the parts provoking the
system to stop listening, cancelled from the original */
//putch('\0');
/* forever loop */
for (;;) {
/* get character from UART */
ch = getch();
/* A bunch of if...else if... gives smaller code than switch...case ! */
/* Hello is anyone home ? */
if(ch=='0') {
nothing_response();
}
/* Request programmer ID */
/* Not using PROGMEM string due to boot block in m128 being beyond 64kB boundry */
/* Would need to selectively manipulate RAMPZ, and it's only 9 characters anyway so who cares. */
else if(ch=='1') {
if (getch() == ' ') {
putch(0x14);
putch('A');
putch('V');
putch('R');
putch(' ');
putch('I');
putch('S');
putch('P');
putch(0x10);
} else {
if (++error_count == MAX_ERROR_COUNT)
app_start();
}
}
/* AVR ISP/STK500 board commands DON'T CARE so default nothing_response */
else if(ch=='@') {
ch2 = getch();
if (ch2>0x85) getch();
nothing_response();
}
/* AVR ISP/STK500 board requests */
else if(ch=='A') {
ch2 = getch();
if(ch2==0x80) byte_response(HW_VER); // Hardware version
else if(ch2==0x81) byte_response(SW_MAJOR); // Software major version
else if(ch2==0x82) byte_response(SW_MINOR); // Software minor version
else if(ch2==0x98) byte_response(0x03); // Unknown but seems to be required by avr studio 3.56
else byte_response(0x00); // Covers various unnecessary responses we don't care about
}
/* Device Parameters DON'T CARE, DEVICE IS FIXED */
else if(ch=='B') {
getNch(20);
nothing_response();
}
/* Parallel programming stuff DON'T CARE */
else if(ch=='E') {
getNch(5);
nothing_response();
}
/* Enter programming mode */
else if(ch=='P') {
nothing_response();
}
/* Leave programming mode */
else if(ch=='Q') {
nothing_response();
}
/* Erase device, don't care as we will erase one page at a time anyway. */
else if(ch=='R') {
nothing_response();
}
/* Set address, little endian. EEPROM in bytes, FLASH in words */
/* Perhaps extra address bytes may be added in future to support > 128kB FLASH. */
/* This might explain why little endian was used here, big endian used everywhere else. */
else if(ch=='U') {
address.byte[0] = getch();
address.byte[1] = getch();
nothing_response();
}
/* Universal SPI programming command, disabled. Would be used for fuses and lock bits. */
else if(ch=='V') {
getNch(4);
byte_response(0x00);
}
/* Write memory, length is big endian and is in bytes */
else if(ch=='d') {
length.byte[1] = getch();
length.byte[0] = getch();
flags.eeprom = 0;
if (getch() == 'E') flags.eeprom = 1;
for (w=0;w<length.word;w++) {
buff[w] = getch(); // Store data in buffer, can't keep up with serial data stream whilst programming pages
}
if (getch() == ' ') {
if (flags.eeprom) { //Write to EEPROM one byte at a time
for(w=0;w<length.word;w++) {
#ifdef __AVR_ATmega168__
while(EECR & (1<<EEPE));
EEAR = (uint16_t)(void *)address.word;
EEDR = buff[w];
EECR |= (1<<EEMPE);
EECR |= (1<<EEPE);
#else
eeprom_write_byte((void *)address.word,buff[w]);
#endif
address.word++;
}
}
else { //Write to FLASH one page at a time
if (address.byte[1]>127) address_high = 0x01; //Only possible with m128, m256 will need 3rd address byte. FIXME
else address_high = 0x00;
#ifdef __AVR_ATmega128__
RAMPZ = address_high;
#endif
address.word = address.word << 1; //address * 2 -> byte location
/* if ((length.byte[0] & 0x01) == 0x01) length.word++; //Even up an odd number of bytes */
if ((length.byte[0] & 0x01)) length.word++; //Even up an odd number of bytes
cli(); //Disable interrupts, just to be sure
// HACKME: EEPE used to be EEWE
while(bit_is_set(EECR,EEPE)); //Wait for previous EEPROM writes to complete
asm volatile(
"clr r17 \n\t" //page_word_count
"lds r30,address \n\t" //Address of FLASH location (in bytes)
"lds r31,address+1 \n\t"
"ldi r28,lo8(buff) \n\t" //Start of buffer array in RAM
"ldi r29,hi8(buff) \n\t"
"lds r24,length \n\t" //Length of data to be written (in bytes)
"lds r25,length+1 \n\t"
"length_loop: \n\t" //Main loop, repeat for number of words in block
"cpi r17,0x00 \n\t" //If page_word_count=0 then erase page
"brne no_page_erase \n\t"
"wait_spm1: \n\t"
"lds r16,%0 \n\t" //Wait for previous spm to complete
"andi r16,1 \n\t"
"cpi r16,1 \n\t"
"breq wait_spm1 \n\t"
"ldi r16,0x03 \n\t" //Erase page pointed to by Z
"sts %0,r16 \n\t"
"spm \n\t"
#ifdef __AVR_ATmega163__
".word 0xFFFF \n\t"
"nop \n\t"
#endif
"wait_spm2: \n\t"
"lds r16,%0 \n\t" //Wait for previous spm to complete
"andi r16,1 \n\t"
"cpi r16,1 \n\t"
"breq wait_spm2 \n\t"
"ldi r16,0x11 \n\t" //Re-enable RWW section
"sts %0,r16 \n\t"
"spm \n\t"
#ifdef __AVR_ATmega163__
".word 0xFFFF \n\t"
"nop \n\t"
#endif
"no_page_erase: \n\t"
"ld r0,Y+ \n\t" //Write 2 bytes into page buffer
"ld r1,Y+ \n\t"
"wait_spm3: \n\t"
"lds r16,%0 \n\t" //Wait for previous spm to complete
"andi r16,1 \n\t"
"cpi r16,1 \n\t"
"breq wait_spm3 \n\t"
"ldi r16,0x01 \n\t" //Load r0,r1 into FLASH page buffer
"sts %0,r16 \n\t"
"spm \n\t"
"inc r17 \n\t" //page_word_count++
"cpi r17,%1 \n\t"
"brlo same_page \n\t" //Still same page in FLASH
"write_page: \n\t"
"clr r17 \n\t" //New page, write current one first
"wait_spm4: \n\t"
"lds r16,%0 \n\t" //Wait for previous spm to complete
"andi r16,1 \n\t"
"cpi r16,1 \n\t"
"breq wait_spm4 \n\t"
#ifdef __AVR_ATmega163__
"andi r30,0x80 \n\t" // m163 requires Z6:Z1 to be zero during page write
#endif
"ldi r16,0x05 \n\t" //Write page pointed to by Z
"sts %0,r16 \n\t"
"spm \n\t"
#ifdef __AVR_ATmega163__
".word 0xFFFF \n\t"
"nop \n\t"
"ori r30,0x7E \n\t" // recover Z6:Z1 state after page write (had to be zero during write)
#endif
"wait_spm5: \n\t"
"lds r16,%0 \n\t" //Wait for previous spm to complete
"andi r16,1 \n\t"
"cpi r16,1 \n\t"
"breq wait_spm5 \n\t"
"ldi r16,0x11 \n\t" //Re-enable RWW section
"sts %0,r16 \n\t"
"spm \n\t"
#ifdef __AVR_ATmega163__
".word 0xFFFF \n\t"
"nop \n\t"
#endif
"same_page: \n\t"
"adiw r30,2 \n\t" //Next word in FLASH
"sbiw r24,2 \n\t" //length-2
"breq final_write \n\t" //Finished
"rjmp length_loop \n\t"
"final_write: \n\t"
"cpi r17,0 \n\t"
"breq block_done \n\t"
"adiw r24,2 \n\t" //length+2, fool above check on length after short page write
"rjmp write_page \n\t"
"block_done: \n\t"
"clr __zero_reg__ \n\t" //restore zero register
#if defined __AVR_ATmega168__
: "=m" (SPMCSR) : "M" (PAGE_SIZE) : "r0","r16","r17","r24","r25","r28","r29","r30","r31"
#else
: "=m" (SPMCR) : "M" (PAGE_SIZE) : "r0","r16","r17","r24","r25","r28","r29","r30","r31"
#endif
);
/* Should really add a wait for RWW section to be enabled, don't actually need it since we never */
/* exit the bootloader without a power cycle anyhow */
}
putch(0x14);
putch(0x10);
} else {
if (++error_count == MAX_ERROR_COUNT)
app_start();
}
}
/* Read memory block mode, length is big endian. */
else if(ch=='t') {
length.byte[1] = getch();
length.byte[0] = getch();
#if defined __AVR_ATmega128__
if (address.word>0x7FFF) flags.rampz = 1; // No go with m256, FIXME
else flags.rampz = 0;
#endif
if (getch() == 'E') flags.eeprom = 1;
else {
flags.eeprom = 0;
address.word = address.word << 1; // address * 2 -> byte location
}
if (getch() == ' ') { // Command terminator
putch(0x14);
for (w=0;w < length.word;w++) { // Can handle odd and even lengths okay
if (flags.eeprom) { // Byte access EEPROM read
#ifdef __AVR_ATmega168__
while(EECR & (1<<EEPE));
EEAR = (uint16_t)(void *)address.word;
EECR |= (1<<EERE);
putch(EEDR);
#else
putch(eeprom_read_byte((void *)address.word));
#endif
address.word++;
}
else {
if (!flags.rampz) putch(pgm_read_byte_near(address.word));
#if defined __AVR_ATmega128__
else putch(pgm_read_byte_far(address.word + 0x10000));
// Hmmmm, yuck FIXME when m256 arrvies
#endif
address.word++;
}
}
putch(0x10);
}
}
/* Get device signature bytes */
else if(ch=='u') {
if (getch() == ' ') {
putch(0x14);
putch(SIG1);
putch(SIG2);
putch(SIG3);
putch(0x10);
} else {
if (++error_count == MAX_ERROR_COUNT)
app_start();
}
}
/* Read oscillator calibration byte */
else if(ch=='v') {
byte_response(0x00);
}
#ifdef MONITOR
/* here come the extended monitor commands by Erik Lins */
/* check for three times exclamation mark pressed */
else if(ch=='!') {
ch = getch();
if(ch=='!') {
ch = getch();
if(ch=='!') {
#ifdef __AVR_ATmega128__
uint16_t extaddr;
#endif
uint8_t addrl, addrh;
#ifdef CRUMB128
PGM_P welcome = {"ATmegaBOOT / Crumb128 - (C) J.P.Kyle, E.Lins - 050815\n\r"};
#elif defined PROBOMEGA128
PGM_P welcome = {"ATmegaBOOT / PROBOmega128 - (C) J.P.Kyle, E.Lins - 050815\n\r"};
#elif defined SAVVY128
PGM_P welcome = {"ATmegaBOOT / Savvy128 - (C) J.P.Kyle, E.Lins - 050815\n\r"};
#endif
/* turn on LED */
LED_DDR |= _BV(LED);
LED_PORT &= ~_BV(LED);
/* print a welcome message and command overview */
for(i=0; welcome[i] != '\0'; ++i) {
putch(welcome[i]);
}
/* test for valid commands */
for(;;) {
putch('\n');
putch('\r');
putch(':');
putch(' ');
ch = getch();
putch(ch);
/* toggle LED */
if(ch == 't') {
if(bit_is_set(LED_PIN,LED)) {
LED_PORT &= ~_BV(LED);
putch('1');
} else {
LED_PORT |= _BV(LED);
putch('0');
}
}
/* read byte from address */
else if(ch == 'r') {
ch = getch(); putch(ch);
addrh = gethex();
addrl = gethex();
putch('=');
ch = *(uint8_t *)((addrh << 8) + addrl);
puthex(ch);
}
/* write a byte to address */
else if(ch == 'w') {
ch = getch(); putch(ch);
addrh = gethex();
addrl = gethex();
ch = getch(); putch(ch);
ch = gethex();
*(uint8_t *)((addrh << 8) + addrl) = ch;
}
/* read from uart and echo back */
else if(ch == 'u') {
for(;;) {
putch(getch());
}
}
#ifdef __AVR_ATmega128__
/* external bus loop */
else if(ch == 'b') {
putch('b');
putch('u');
putch('s');
MCUCR = 0x80;
XMCRA = 0;
XMCRB = 0;
extaddr = 0x1100;
for(;;) {
ch = *(volatile uint8_t *)extaddr;
if(++extaddr == 0) {
extaddr = 0x1100;
}
}
}
#endif
else if(ch == 'j') {
app_start();
}
}
/* end of monitor functions */
}
}
}
/* end of monitor */
#endif
else if (++error_count == MAX_ERROR_COUNT) {
app_start();
}
}
/* end of forever loop */
}
char gethex(void) {
char ah,al;
ah = getch(); putch(ah);
al = getch(); putch(al);
if(ah >= 'a') {
ah = ah - 'a' + 0x0a;
} else if(ah >= '0') {
ah -= '0';
}
if(al >= 'a') {
al = al - 'a' + 0x0a;
} else if(al >= '0') {
al -= '0';
}
return (ah << 4) + al;
}
void puthex(char ch) {
char ah,al;
ah = (ch & 0xf0) >> 4;
if(ah >= 0x0a) {
ah = ah - 0x0a + 'a';
} else {
ah += '0';
}
al = (ch & 0x0f);
if(al >= 0x0a) {
al = al - 0x0a + 'a';
} else {
al += '0';
}
putch(ah);
putch(al);
}
void putch(char ch)
{
#ifdef __AVR_ATmega128__
if(bootuart == 1) {
while (!(UCSR0A & _BV(UDRE0)));
UDR0 = ch;
}
else if (bootuart == 2) {
while (!(UCSR1A & _BV(UDRE1)));
UDR1 = ch;
}
#elif defined __AVR_ATmega168__
while (!(UCSR0A & _BV(UDRE0)));
UDR0 = ch;
#else
/* m8,16,32,169,8515,8535,163 */
while (!(UCSRA & _BV(UDRE)));
UDR = ch;
#endif
}
char getch(void)
{
#ifdef __AVR_ATmega128__
if(bootuart == 1) {
while(!(UCSR0A & _BV(RXC0)));
return UDR0;
}
else if(bootuart == 2) {
while(!(UCSR1A & _BV(RXC1)));
return UDR1;
}
return 0;
#elif defined __AVR_ATmega168__
uint32_t count = 0;
while(!(UCSR0A & _BV(RXC0))){
/* 20060803 DojoCorp:: Addon coming from the previous Bootloader*/
/* HACKME:: here is a good place to count times*/
count++;
if (count > MAX_TIME_COUNT)
app_start();
}
return UDR0;
#else
/* m8,16,32,169,8515,8535,163 */
uint32_t count = 0;
while(!(UCSRA & _BV(RXC))){
/* 20060803 DojoCorp:: Addon coming from the previous Bootloader*/
/* HACKME:: here is a good place to count times*/
count++;
if (count > MAX_TIME_COUNT)
app_start();
}
return UDR;
#endif
}
void getNch(uint8_t count)
{
uint8_t i;
for(i=0;i<count;i++) {
#ifdef __AVR_ATmega128__
if(bootuart == 1) {
while(!(UCSR0A & _BV(RXC0)));
UDR0;
}
else if(bootuart == 2) {
while(!(UCSR1A & _BV(RXC1)));
UDR1;
}
#elif defined __AVR_ATmega168__
while(!(UCSR0A & _BV(RXC0)));
UDR0;
#else
/* m8,16,32,169,8515,8535,163 */
/* 20060803 DojoCorp:: Addon coming from the previous Bootloader*/
//while(!(UCSRA & _BV(RXC)));
//UDR;
uint8_t i;
for(i=0;i<count;i++) {
getch(); // need to handle time out
}
#endif
}
}
void byte_response(uint8_t val)
{
if (getch() == ' ') {
putch(0x14);
putch(val);
putch(0x10);
} else {
if (++error_count == MAX_ERROR_COUNT)
app_start();
}
}
void nothing_response(void)
{
if (getch() == ' ') {
putch(0x14);
putch(0x10);
} else {
if (++error_count == MAX_ERROR_COUNT)
app_start();
}
}
void flash_led(uint8_t count)
{
/* flash onboard LED three times to signal entering of bootloader */
/* l needs to be volatile or the delay loops below might get
optimized away if compiling with optimizations (DAM). */
volatile uint32_t l;
if (count == 0) {
count = 3;
}
for (i = 0; i < count; ++i) {
LED_PORT |= _BV(LED);
for(l = 0; l < (F_CPU / 1000); ++l);
LED_PORT &= ~_BV(LED);
for(l = 0; l < (F_CPU / 1000); ++l);
}
}
/* end of file ATmegaBOOT.c */

View File

@ -0,0 +1,84 @@
# Makefile for ATmegaBOOT
# E.Lins, 18.7.2005
# $Id$
# Instructions
#
# To build the bootloader for the LilyPad:
# make lily
# program name should not be changed...
PROGRAM = ATmegaBOOT_168
# enter the target CPU frequency
AVR_FREQ = 8000000L
# enter the parameters for the avrdude isp tool
ISPTOOL = stk500v2
ISPPORT = usb
ISPSPEED = -b 115200
MCU_TARGET = atmega168
LDSECTION = --section-start=.text=0x3800
# the efuse should really be 0xf8; since, however, only the lower
# three bits of that byte are used on the atmega168, avrdude gets
# confused if you specify 1's for the higher bits, see:
# http://tinker.it/now/2007/02/24/the-tale-of-avrdude-atmega168-and-extended-bits-fuses/
#
# similarly, the lock bits should be 0xff instead of 0x3f (to
# unlock the bootloader section) and 0xcf instead of 0x0f (to
# lock it), but since the high two bits of the lock byte are
# unused, avrdude would get confused.
ISPFUSES = avrdude -c $(ISPTOOL) -p m168 -P $(ISPPORT) $(ISPSPEED) -e -u -U lock:w:0x3f:m -U efuse:w:0x00:m -U hfuse:w:0xdd:m -U lfuse:w:0xff:m
ISPFLASH = avrdude -c $(ISPTOOL) -p m168 -P $(ISPPORT) $(ISPSPEED) -U flash:w:$(PROGRAM)_$(TARGET).hex -U lock:w:0x0f:m
OBJ = $(PROGRAM).o
OPTIMIZE = -O2
DEFS =
LIBS =
CC = avr-gcc
# Override is only needed by avr-lib build system.
override CFLAGS = -g -Wall $(OPTIMIZE) -mmcu=$(MCU_TARGET) -DF_CPU=$(AVR_FREQ) $(DEFS)
override LDFLAGS = -Wl,$(LDSECTION)
#override LDFLAGS = -Wl,-Map,$(PROGRAM).map,$(LDSECTION)
OBJCOPY = avr-objcopy
OBJDUMP = avr-objdump
all:
lily: CFLAGS += '-DMAX_TIME_COUNT=F_CPU>>1' '-DNUM_LED_FLASHES=3'
lily: $(PROGRAM).hex
$(PROGRAM).hex: $(PROGRAM).elf
$(OBJCOPY) -j .text -j .data -O ihex $< $@
$(PROGRAM).elf: $(OBJ)
$(CC) $(CFLAGS) $(LDFLAGS) -o $@ $^ $(LIBS)
$(OBJ):
avr-gcc $(CFLAGS) $(LDFLAGS) -c -g -O2 -Wall -mmcu=atmega168 ATmegaBOOT.c -o ATmegaBOOT_168.o
%.lst: %.elf
$(OBJDUMP) -h -S $< > $@
%.srec: %.elf
$(OBJCOPY) -j .text -j .data -O srec $< $@
%.bin: %.elf
$(OBJCOPY) -j .text -j .data -O binary $< $@
clean:
rm -rf *.o *.elf *.lst *.map *.sym *.lss *.eep *.srec *.bin *.hex
install:
avrdude -p m168 -c stk500v2 -P /dev/cu.USA19H1b1P1.1 -e -u -U lock:w:0x3f:m -U efuse:w:0x00:m -U hfuse:w:0xdd:m -U lfuse:w:0xe2:m
avrdude -p m168 -c stk500v2 -P /dev/cu.USA19H1b1P1.1 -e -u -U flash:w:ATmegaBOOT_168.hex -U lock:w:0x0f:m

View File

@ -0,0 +1,191 @@
/*
HardwareSerial.cpp - Hardware serial library for Wiring
Copyright (c) 2006 Nicholas Zambetti. All right reserved.
This library 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 2.1 of the License, or (at your option) any later version.
This library 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
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
Modified 23 November 2006 by David A. Mellis
*/
#include <stdio.h>
#include <string.h>
#include <inttypes.h>
#include "wiring.h"
#include "wiring_private.h"
#include "HardwareSerial.h"
// Define constants and variables for buffering incoming serial data. We're
// using a ring buffer (I think), in which rx_buffer_head is the index of the
// location to which to write the next incoming character and rx_buffer_tail
// is the index of the location from which to read.
#define RX_BUFFER_SIZE 128
struct ring_buffer {
unsigned char buffer[RX_BUFFER_SIZE];
int head;
int tail;
};
ring_buffer rx_buffer = { { 0 }, 0, 0 };
#if defined(__AVR_ATmega1280__)
ring_buffer rx_buffer1 = { { 0 }, 0, 0 };
ring_buffer rx_buffer2 = { { 0 }, 0, 0 };
ring_buffer rx_buffer3 = { { 0 }, 0, 0 };
#endif
inline void store_char(unsigned char c, ring_buffer *rx_buffer)
{
int i = (rx_buffer->head + 1) % RX_BUFFER_SIZE;
// if we should be storing the received character into the location
// just before the tail (meaning that the head would advance to the
// current location of the tail), we're about to overflow the buffer
// and so we don't write the character or advance the head.
if (i != rx_buffer->tail) {
rx_buffer->buffer[rx_buffer->head] = c;
rx_buffer->head = i;
}
}
#if defined(__AVR_ATmega1280__)
SIGNAL(SIG_USART0_RECV)
{
unsigned char c = UDR0;
store_char(c, &rx_buffer);
}
SIGNAL(SIG_USART1_RECV)
{
unsigned char c = UDR1;
store_char(c, &rx_buffer1);
}
SIGNAL(SIG_USART2_RECV)
{
unsigned char c = UDR2;
store_char(c, &rx_buffer2);
}
SIGNAL(SIG_USART3_RECV)
{
unsigned char c = UDR3;
store_char(c, &rx_buffer3);
}
#else
#if defined(__AVR_ATmega8__)
SIGNAL(SIG_UART_RECV)
#else
SIGNAL(USART_RX_vect)
#endif
{
#if defined(__AVR_ATmega8__)
unsigned char c = UDR;
#else
unsigned char c = UDR0;
#endif
store_char(c, &rx_buffer);
}
#endif
// Constructors ////////////////////////////////////////////////////////////////
HardwareSerial::HardwareSerial(ring_buffer *rx_buffer,
volatile uint8_t *ubrrh, volatile uint8_t *ubrrl,
volatile uint8_t *ucsra, volatile uint8_t *ucsrb,
volatile uint8_t *udr,
uint8_t rxen, uint8_t txen, uint8_t rxcie, uint8_t udre)
{
_rx_buffer = rx_buffer;
_ubrrh = ubrrh;
_ubrrl = ubrrl;
_ucsra = ucsra;
_ucsrb = ucsrb;
_udr = udr;
_rxen = rxen;
_txen = txen;
_rxcie = rxcie;
_udre = udre;
}
// Public Methods //////////////////////////////////////////////////////////////
void HardwareSerial::begin(long speed)
{
*_ubrrh = ((F_CPU / 16 + speed / 2) / speed - 1) >> 8;
*_ubrrl = ((F_CPU / 16 + speed / 2) / speed - 1);
sbi(*_ucsrb, _rxen);
sbi(*_ucsrb, _txen);
sbi(*_ucsrb, _rxcie);
}
uint8_t HardwareSerial::available(void)
{
return (RX_BUFFER_SIZE + _rx_buffer->head - _rx_buffer->tail) % RX_BUFFER_SIZE;
}
int HardwareSerial::read(void)
{
// if the head isn't ahead of the tail, we don't have any characters
if (_rx_buffer->head == _rx_buffer->tail) {
return -1;
} else {
unsigned char c = _rx_buffer->buffer[_rx_buffer->tail];
_rx_buffer->tail = (_rx_buffer->tail + 1) % RX_BUFFER_SIZE;
return c;
}
}
void HardwareSerial::flush()
{
// don't reverse this or there may be problems if the RX interrupt
// occurs after reading the value of rx_buffer_head but before writing
// the value to rx_buffer_tail; the previous value of rx_buffer_head
// may be written to rx_buffer_tail, making it appear as if the buffer
// don't reverse this or there may be problems if the RX interrupt
// occurs after reading the value of rx_buffer_head but before writing
// the value to rx_buffer_tail; the previous value of rx_buffer_head
// may be written to rx_buffer_tail, making it appear as if the buffer
// were full, not empty.
_rx_buffer->head = _rx_buffer->tail;
}
void HardwareSerial::write(uint8_t c)
{
while (!((*_ucsra) & (1 << _udre)))
;
*_udr = c;
}
// Preinstantiate Objects //////////////////////////////////////////////////////
#if defined(__AVR_ATmega8__)
HardwareSerial Serial(&rx_buffer, &UBRRH, &UBRRL, &UCSRA, &UCSRB, &UDR, RXEN, TXEN, RXCIE, UDRE);
#else
HardwareSerial Serial(&rx_buffer, &UBRR0H, &UBRR0L, &UCSR0A, &UCSR0B, &UDR0, RXEN0, TXEN0, RXCIE0, UDRE0);
#endif
#if defined(__AVR_ATmega1280__)
HardwareSerial Serial1(&rx_buffer1, &UBRR1H, &UBRR1L, &UCSR1A, &UCSR1B, &UDR1, RXEN1, TXEN1, RXCIE1, UDRE1);
HardwareSerial Serial2(&rx_buffer2, &UBRR2H, &UBRR2L, &UCSR2A, &UCSR2B, &UDR2, RXEN2, TXEN2, RXCIE2, UDRE2);
HardwareSerial Serial3(&rx_buffer3, &UBRR3H, &UBRR3L, &UCSR3A, &UCSR3B, &UDR3, RXEN3, TXEN3, RXCIE3, UDRE3);
#endif

View File

@ -0,0 +1,65 @@
/*
HardwareSerial.h - Hardware serial library for Wiring
Copyright (c) 2006 Nicholas Zambetti. All right reserved.
This library 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 2.1 of the License, or (at your option) any later version.
This library 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
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef HardwareSerial_h
#define HardwareSerial_h
#include <inttypes.h>
#include "Print.h"
struct ring_buffer;
class HardwareSerial : public Print
{
private:
ring_buffer *_rx_buffer;
volatile uint8_t *_ubrrh;
volatile uint8_t *_ubrrl;
volatile uint8_t *_ucsra;
volatile uint8_t *_ucsrb;
volatile uint8_t *_udr;
uint8_t _rxen;
uint8_t _txen;
uint8_t _rxcie;
uint8_t _udre;
public:
HardwareSerial(ring_buffer *rx_buffer,
volatile uint8_t *ubrrh, volatile uint8_t *ubrrl,
volatile uint8_t *ucsra, volatile uint8_t *ucsrb,
volatile uint8_t *udr,
uint8_t rxen, uint8_t txen, uint8_t rxcie, uint8_t udre);
void begin(long);
uint8_t available(void);
int read(void);
void flush(void);
virtual void write(uint8_t);
using Print::write; // pull in write(str) and write(buf, size) from Print
};
extern HardwareSerial Serial;
#if defined(__AVR_ATmega1280__)
extern HardwareSerial Serial1;
extern HardwareSerial Serial2;
extern HardwareSerial Serial3;
#endif
#endif

243
hardware/cores/arduino/Makefile Executable file
View File

@ -0,0 +1,243 @@
# Arduino 0015 Makefile
# Arduino adaptation by mellis, eighthave, oli.keller
#
# This makefile allows you to build sketches from the command line
# without the Arduino environment (or Java).
#
# Detailed instructions for using the makefile:
#
# 1. Copy this file into the folder with your sketch. There should be a
# file with the same name as the folder and with the extension .pde
# (e.g. foo.pde in the foo/ folder).
#
# 2. Modify the line containg "INSTALL_DIR" to point to the directory that
# contains the Arduino installation (for example, under Mac OS X, this
# might be /Applications/arduino-0012).
#
# 3. Modify the line containing "PORT" to refer to the filename
# representing the USB or serial connection to your Arduino board
# (e.g. PORT = /dev/tty.USB0). If the exact name of this file
# changes, you can use * as a wildcard (e.g. PORT = /dev/tty.usb*).
#
# 4. Set the line containing "MCU" to match your board's processor.
# Older one's are atmega8 based, newer ones like Arduino Mini, Bluetooth
# or Diecimila have the atmega168. If you're using a LilyPad Arduino,
# change F_CPU to 8000000.
#
# 5. At the command line, change to the directory containing your
# program's file and the makefile.
#
# 6. Type "make" and press enter to compile/verify your program.
#
# 7. Type "make upload", reset your Arduino board, and press enter to
# upload your program to the Arduino board.
#
# $Id$
TARGET = $(notdir $(CURDIR))
INSTALL_DIR = ../../..
PORT = /dev/tty.usb*
UPLOAD_RATE = 19200
AVRDUDE_PROGRAMMER = stk500v1
MCU = atmega168
F_CPU = 16000000
############################################################################
# Below here nothing should be changed...
ARDUINO = $(INSTALL_DIR)/hardware/cores/arduino
AVR_TOOLS_PATH = $(INSTALL_DIR)/hardware/tools/avr/bin
SRC = $(ARDUINO)/pins_arduino.c $(ARDUINO)/wiring.c \
$(ARDUINO)/wiring_analog.c $(ARDUINO)/wiring_digital.c \
$(ARDUINO)/wiring_pulse.c $(ARDUINO)/wiring_serial.c \
$(ARDUINO)/wiring_shift.c $(ARDUINO)/WInterrupts.c
CXXSRC = $(ARDUINO)/HardwareSerial.cpp $(ARDUINO)/WMath.cpp \
$(ARDUINO)/Print.cpp
FORMAT = ihex
# Name of this Makefile (used for "make depend").
MAKEFILE = Makefile
# Debugging format.
# Native formats for AVR-GCC's -g are stabs [default], or dwarf-2.
# AVR (extended) COFF requires stabs, plus an avr-objcopy run.
DEBUG = stabs
OPT = s
# Place -D or -U options here
CDEFS = -DF_CPU=$(F_CPU)
CXXDEFS = -DF_CPU=$(F_CPU)
# Place -I options here
CINCS = -I$(ARDUINO)
CXXINCS = -I$(ARDUINO)
# Compiler flag to set the C Standard level.
# c89 - "ANSI" C
# gnu89 - c89 plus GCC extensions
# c99 - ISO C99 standard (not yet fully implemented)
# gnu99 - c99 plus GCC extensions
CSTANDARD = -std=gnu99
CDEBUG = -g$(DEBUG)
CWARN = -Wall -Wstrict-prototypes
CTUNING = -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums
#CEXTRA = -Wa,-adhlns=$(<:.c=.lst)
CFLAGS = $(CDEBUG) $(CDEFS) $(CINCS) -O$(OPT) $(CWARN) $(CSTANDARD) $(CEXTRA)
CXXFLAGS = $(CDEFS) $(CINCS) -O$(OPT)
#ASFLAGS = -Wa,-adhlns=$(<:.S=.lst),-gstabs
LDFLAGS = -lm
# Programming support using avrdude. Settings and variables.
AVRDUDE_PORT = $(PORT)
AVRDUDE_WRITE_FLASH = -U flash:w:applet/$(TARGET).hex
AVRDUDE_FLAGS = -V -F -C $(INSTALL_DIR)/hardware/tools/avr/etc/avrdude.conf \
-p $(MCU) -P $(AVRDUDE_PORT) -c $(AVRDUDE_PROGRAMMER) \
-b $(UPLOAD_RATE)
# Program settings
CC = $(AVR_TOOLS_PATH)/avr-gcc
CXX = $(AVR_TOOLS_PATH)/avr-g++
OBJCOPY = $(AVR_TOOLS_PATH)/avr-objcopy
OBJDUMP = $(AVR_TOOLS_PATH)/avr-objdump
AR = $(AVR_TOOLS_PATH)/avr-ar
SIZE = $(AVR_TOOLS_PATH)/avr-size
NM = $(AVR_TOOLS_PATH)/avr-nm
AVRDUDE = $(AVR_TOOLS_PATH)/avrdude
REMOVE = rm -f
MV = mv -f
# Define all object files.
OBJ = $(SRC:.c=.o) $(CXXSRC:.cpp=.o) $(ASRC:.S=.o)
# Define all listing files.
LST = $(ASRC:.S=.lst) $(CXXSRC:.cpp=.lst) $(SRC:.c=.lst)
# Combine all necessary flags and optional flags.
# Add target processor to flags.
ALL_CFLAGS = -mmcu=$(MCU) -I. $(CFLAGS)
ALL_CXXFLAGS = -mmcu=$(MCU) -I. $(CXXFLAGS)
ALL_ASFLAGS = -mmcu=$(MCU) -I. -x assembler-with-cpp $(ASFLAGS)
# Default target.
all: applet_files build sizeafter
build: elf hex
applet_files: $(TARGET).pde
# Here is the "preprocessing".
# It creates a .cpp file based with the same name as the .pde file.
# On top of the new .cpp file comes the WProgram.h header.
# At the end there is a generic main() function attached.
# Then the .cpp file will be compiled. Errors during compile will
# refer to this new, automatically generated, file.
# Not the original .pde file you actually edit...
test -d applet || mkdir applet
echo '#include "WProgram.h"' > applet/$(TARGET).cpp
cat $(TARGET).pde >> applet/$(TARGET).cpp
cat $(ARDUINO)/main.cxx >> applet/$(TARGET).cpp
elf: applet/$(TARGET).elf
hex: applet/$(TARGET).hex
eep: applet/$(TARGET).eep
lss: applet/$(TARGET).lss
sym: applet/$(TARGET).sym
# Program the device.
upload: applet/$(TARGET).hex
$(AVRDUDE) $(AVRDUDE_FLAGS) $(AVRDUDE_WRITE_FLASH)
# Display size of file.
HEXSIZE = $(SIZE) --target=$(FORMAT) applet/$(TARGET).hex
ELFSIZE = $(SIZE) applet/$(TARGET).elf
sizebefore:
@if [ -f applet/$(TARGET).elf ]; then echo; echo $(MSG_SIZE_BEFORE); $(HEXSIZE); echo; fi
sizeafter:
@if [ -f applet/$(TARGET).elf ]; then echo; echo $(MSG_SIZE_AFTER); $(HEXSIZE); echo; fi
# Convert ELF to COFF for use in debugging / simulating in AVR Studio or VMLAB.
COFFCONVERT=$(OBJCOPY) --debugging \
--change-section-address .data-0x800000 \
--change-section-address .bss-0x800000 \
--change-section-address .noinit-0x800000 \
--change-section-address .eeprom-0x810000
coff: applet/$(TARGET).elf
$(COFFCONVERT) -O coff-avr applet/$(TARGET).elf $(TARGET).cof
extcoff: $(TARGET).elf
$(COFFCONVERT) -O coff-ext-avr applet/$(TARGET).elf $(TARGET).cof
.SUFFIXES: .elf .hex .eep .lss .sym
.elf.hex:
$(OBJCOPY) -O $(FORMAT) -R .eeprom $< $@
.elf.eep:
-$(OBJCOPY) -j .eeprom --set-section-flags=.eeprom="alloc,load" \
--change-section-lma .eeprom=0 -O $(FORMAT) $< $@
# Create extended listing file from ELF output file.
.elf.lss:
$(OBJDUMP) -h -S $< > $@
# Create a symbol table from ELF output file.
.elf.sym:
$(NM) -n $< > $@
# Link: create ELF output file from library.
applet/$(TARGET).elf: $(TARGET).pde applet/core.a
$(CC) $(ALL_CFLAGS) -o $@ applet/$(TARGET).cpp -L. applet/core.a $(LDFLAGS)
applet/core.a: $(OBJ)
@for i in $(OBJ); do echo $(AR) rcs applet/core.a $$i; $(AR) rcs applet/core.a $$i; done
# Compile: create object files from C++ source files.
.cpp.o:
$(CXX) -c $(ALL_CXXFLAGS) $< -o $@
# Compile: create object files from C source files.
.c.o:
$(CC) -c $(ALL_CFLAGS) $< -o $@
# Compile: create assembler files from C source files.
.c.s:
$(CC) -S $(ALL_CFLAGS) $< -o $@
# Assemble: create object files from assembler source files.
.S.o:
$(CC) -c $(ALL_ASFLAGS) $< -o $@
# Automatic dependencies
%.d: %.c
$(CC) -M $(ALL_CFLAGS) $< | sed "s;$(notdir $*).o:;$*.o $*.d:;" > $@
%.d: %.cpp
$(CXX) -M $(ALL_CXXFLAGS) $< | sed "s;$(notdir $*).o:;$*.o $*.d:;" > $@
# Target: clean project.
clean:
$(REMOVE) applet/$(TARGET).hex applet/$(TARGET).eep applet/$(TARGET).cof applet/$(TARGET).elf \
applet/$(TARGET).map applet/$(TARGET).sym applet/$(TARGET).lss applet/core.a \
$(OBJ) $(LST) $(SRC:.c=.s) $(SRC:.c=.d) $(CXXSRC:.cpp=.s) $(CXXSRC:.cpp=.d)
.PHONY: all build elf hex eep lss sym program coff extcoff clean applet_files sizebefore sizeafter
include $(SRC:.c=.d)
include $(CXXSRC:.cpp=.d)

215
hardware/cores/arduino/Print.cpp Executable file
View File

@ -0,0 +1,215 @@
/*
Print.cpp - Base class that provides print() and println()
Copyright (c) 2008 David A. Mellis. All right reserved.
This library 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 2.1 of the License, or (at your option) any later version.
This library 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
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
Modified 23 November 2006 by David A. Mellis
*/
#include <stdio.h>
#include <string.h>
#include <math.h>
#include "wiring.h"
#include "Print.h"
// Public Methods //////////////////////////////////////////////////////////////
/* default implementation: may be overridden */
void Print::write(const char *str)
{
while (*str)
write(*str++);
}
/* default implementation: may be overridden */
void Print::write(const uint8_t *buffer, size_t size)
{
while (size--)
write(*buffer++);
}
void Print::print(uint8_t b)
{
this->write(b);
}
void Print::print(char c)
{
print((byte) c);
}
void Print::print(const char str[])
{
write(str);
}
void Print::print(int n)
{
print((long) n);
}
void Print::print(unsigned int n)
{
print((unsigned long) n);
}
void Print::print(long n)
{
if (n < 0) {
print('-');
n = -n;
}
printNumber(n, 10);
}
void Print::print(unsigned long n)
{
printNumber(n, 10);
}
void Print::print(long n, int base)
{
if (base == 0)
print((char) n);
else if (base == 10)
print(n);
else
printNumber(n, base);
}
void Print::print(double n)
{
printFloat(n, 2);
}
void Print::println(void)
{
print('\r');
print('\n');
}
void Print::println(char c)
{
print(c);
println();
}
void Print::println(const char c[])
{
print(c);
println();
}
void Print::println(uint8_t b)
{
print(b);
println();
}
void Print::println(int n)
{
print(n);
println();
}
void Print::println(unsigned int n)
{
print(n);
println();
}
void Print::println(long n)
{
print(n);
println();
}
void Print::println(unsigned long n)
{
print(n);
println();
}
void Print::println(long n, int base)
{
print(n, base);
println();
}
void Print::println(double n)
{
print(n);
println();
}
// Private Methods /////////////////////////////////////////////////////////////
void Print::printNumber(unsigned long n, uint8_t base)
{
unsigned char buf[8 * sizeof(long)]; // Assumes 8-bit chars.
unsigned long i = 0;
if (n == 0) {
print('0');
return;
}
while (n > 0) {
buf[i++] = n % base;
n /= base;
}
for (; i > 0; i--)
print((char) (buf[i - 1] < 10 ?
'0' + buf[i - 1] :
'A' + buf[i - 1] - 10));
}
void Print::printFloat(double number, uint8_t digits)
{
// Handle negative numbers
if (number < 0.0)
{
print('-');
number = -number;
}
// Round correctly so that print(1.999, 2) prints as "2.00"
double rounding = 0.5;
for (uint8_t i=0; i<digits; ++i)
rounding /= 10.0;
number += rounding;
// Extract the integer part of the number and print it
unsigned long int_part = (unsigned long)number;
double remainder = number - (double)int_part;
print(int_part);
// Print the decimal point, but only if there are digits beyond
if (digits > 0)
print(".");
// Extract digits from the remainder one at a time
while (digits-- > 0)
{
remainder *= 10.0;
int toPrint = int(remainder);
print(toPrint);
remainder -= toPrint;
}
}

62
hardware/cores/arduino/Print.h Executable file
View File

@ -0,0 +1,62 @@
/*
Print.h - Base class that provides print() and println()
Copyright (c) 2008 David A. Mellis. All right reserved.
This library 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 2.1 of the License, or (at your option) any later version.
This library 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
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef Print_h
#define Print_h
#include <inttypes.h>
#include <stdio.h> // for size_t
#define DEC 10
#define HEX 16
#define OCT 8
#define BIN 2
#define BYTE 0
class Print
{
private:
void printNumber(unsigned long, uint8_t);
void printFloat(double, uint8_t);
public:
virtual void write(uint8_t) = 0;
virtual void write(const char *str);
virtual void write(const uint8_t *buffer, size_t size);
void print(char);
void print(const char[]);
void print(uint8_t);
void print(int);
void print(unsigned int);
void print(long);
void print(unsigned long);
void print(long, int);
void print(double);
void println(void);
void println(char);
void println(const char[]);
void println(uint8_t);
void println(int);
void println(unsigned int);
void println(long);
void println(unsigned long);
void println(long, int);
void println(double);
};
#endif

View File

@ -0,0 +1 @@
#include "wiring.h"

View File

@ -0,0 +1,215 @@
/* -*- mode: jde; c-basic-offset: 2; indent-tabs-mode: nil -*- */
/*
Part of the Wiring project - http://wiring.uniandes.edu.co
Copyright (c) 2004-05 Hernando Barragan
This library 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 2.1 of the License, or (at your option) any later version.
This library 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
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General
Public License along with this library; if not, write to the
Free Software Foundation, Inc., 59 Temple Place, Suite 330,
Boston, MA 02111-1307 USA
Modified 24 November 2006 by David A. Mellis
*/
#include <inttypes.h>
#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/pgmspace.h>
#include <stdio.h>
#include "WConstants.h"
#include "wiring_private.h"
volatile static voidFuncPtr intFunc[EXTERNAL_NUM_INTERRUPTS];
// volatile static voidFuncPtr twiIntFunc;
#if defined(__AVR_ATmega8__)
#define EICRA MCUCR
#define EIMSK GICR
#endif
void attachInterrupt(uint8_t interruptNum, void (*userFunc)(void), int mode) {
if(interruptNum < EXTERNAL_NUM_INTERRUPTS) {
intFunc[interruptNum] = userFunc;
// Configure the interrupt mode (trigger on low input, any change, rising
// edge, or falling edge). The mode constants were chosen to correspond
// to the configuration bits in the hardware register, so we simply shift
// the mode into place.
// Enable the interrupt.
switch (interruptNum) {
#if defined(__AVR_ATmega1280__)
case 2:
EICRA = (EICRA & ~((1 << ISC00) | (1 << ISC01))) | (mode << ISC00);
EIMSK |= (1 << INT0);
break;
case 3:
EICRA = (EICRA & ~((1 << ISC10) | (1 << ISC11))) | (mode << ISC10);
EIMSK |= (1 << INT1);
break;
case 4:
EICRA = (EICRA & ~((1 << ISC20) | (1 << ISC21))) | (mode << ISC20);
EIMSK |= (1 << INT2);
break;
case 5:
EICRA = (EICRA & ~((1 << ISC30) | (1 << ISC31))) | (mode << ISC30);
EIMSK |= (1 << INT3);
break;
case 0:
EICRB = (EICRB & ~((1 << ISC40) | (1 << ISC41))) | (mode << ISC40);
EIMSK |= (1 << INT4);
break;
case 1:
EICRB = (EICRB & ~((1 << ISC50) | (1 << ISC51))) | (mode << ISC50);
EIMSK |= (1 << INT5);
break;
case 6:
EICRB = (EICRB & ~((1 << ISC60) | (1 << ISC61))) | (mode << ISC60);
EIMSK |= (1 << INT6);
break;
case 7:
EICRB = (EICRB & ~((1 << ISC70) | (1 << ISC71))) | (mode << ISC70);
EIMSK |= (1 << INT7);
break;
#else
case 0:
EICRA = (EICRA & ~((1 << ISC00) | (1 << ISC01))) | (mode << ISC00);
EIMSK |= (1 << INT0);
break;
case 1:
EICRA = (EICRA & ~((1 << ISC10) | (1 << ISC11))) | (mode << ISC10);
EIMSK |= (1 << INT1);
break;
#endif
}
}
}
void detachInterrupt(uint8_t interruptNum) {
if(interruptNum < EXTERNAL_NUM_INTERRUPTS) {
// Disable the interrupt. (We can't assume that interruptNum is equal
// to the number of the EIMSK bit to clear, as this isn't true on the
// ATmega8. There, INT0 is 6 and INT1 is 7.)
switch (interruptNum) {
#if defined(__AVR_ATmega1280__)
case 2:
EIMSK &= ~(1 << INT0);
break;
case 3:
EIMSK &= ~(1 << INT1);
break;
case 4:
EIMSK &= ~(1 << INT2);
break;
case 5:
EIMSK &= ~(1 << INT3);
break;
case 0:
EIMSK &= ~(1 << INT4);
break;
case 1:
EIMSK &= ~(1 << INT5);
break;
case 6:
EIMSK &= ~(1 << INT6);
break;
case 7:
EIMSK &= ~(1 << INT7);
break;
#else
case 0:
EIMSK &= ~(1 << INT0);
break;
case 1:
EIMSK &= ~(1 << INT1);
break;
#endif
}
intFunc[interruptNum] = 0;
}
}
/*
void attachInterruptTwi(void (*userFunc)(void) ) {
twiIntFunc = userFunc;
}
*/
#if defined(__AVR_ATmega1280__)
SIGNAL(INT0_vect) {
if(intFunc[EXTERNAL_INT_2])
intFunc[EXTERNAL_INT_2]();
}
SIGNAL(INT1_vect) {
if(intFunc[EXTERNAL_INT_3])
intFunc[EXTERNAL_INT_3]();
}
SIGNAL(INT2_vect) {
if(intFunc[EXTERNAL_INT_4])
intFunc[EXTERNAL_INT_4]();
}
SIGNAL(INT3_vect) {
if(intFunc[EXTERNAL_INT_5])
intFunc[EXTERNAL_INT_5]();
}
SIGNAL(INT4_vect) {
if(intFunc[EXTERNAL_INT_0])
intFunc[EXTERNAL_INT_0]();
}
SIGNAL(INT5_vect) {
if(intFunc[EXTERNAL_INT_1])
intFunc[EXTERNAL_INT_1]();
}
SIGNAL(INT6_vect) {
if(intFunc[EXTERNAL_INT_6])
intFunc[EXTERNAL_INT_6]();
}
SIGNAL(INT7_vect) {
if(intFunc[EXTERNAL_INT_7])
intFunc[EXTERNAL_INT_7]();
}
#else
SIGNAL(INT0_vect) {
if(intFunc[EXTERNAL_INT_0])
intFunc[EXTERNAL_INT_0]();
}
SIGNAL(INT1_vect) {
if(intFunc[EXTERNAL_INT_1])
intFunc[EXTERNAL_INT_1]();
}
#endif
/*
SIGNAL(SIG_2WIRE_SERIAL) {
if(twiIntFunc)
twiIntFunc();
}
*/

View File

@ -0,0 +1,60 @@
/* -*- mode: jde; c-basic-offset: 2; indent-tabs-mode: nil -*- */
/*
Part of the Wiring project - http://wiring.org.co
Copyright (c) 2004-06 Hernando Barragan
Modified 13 August 2006, David A. Mellis for Arduino - http://www.arduino.cc/
This library 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 2.1 of the License, or (at your option) any later version.
This library 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
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General
Public License along with this library; if not, write to the
Free Software Foundation, Inc., 59 Temple Place, Suite 330,
Boston, MA 02111-1307 USA
$Id$
*/
extern "C" {
#include "stdlib.h"
}
void randomSeed(unsigned int seed)
{
if (seed != 0) {
srandom(seed);
}
}
long random(long howbig)
{
if (howbig == 0) {
return 0;
}
return random() % howbig;
}
long random(long howsmall, long howbig)
{
if (howsmall >= howbig) {
return howsmall;
}
long diff = howbig - howsmall;
return random(diff) + howsmall;
}
long map(long x, long in_min, long in_max, long out_min, long out_max)
{
return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
}
unsigned int makeWord(unsigned int w) { return w; }
unsigned int makeWord(unsigned char h, unsigned char l) { return (h << 8) | l; }

View File

@ -0,0 +1,29 @@
#ifndef WProgram_h
#define WProgram_h
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <avr/interrupt.h>
#include "wiring.h"
#ifdef __cplusplus
#include "HardwareSerial.h"
uint16_t makeWord(uint16_t w);
uint16_t makeWord(byte h, byte l);
#define word(...) makeWord(__VA_ARGS__)
unsigned long pulseIn(uint8_t pin, uint8_t state, unsigned long timeout = 1000000L);
// WMath prototypes
long random(long);
long random(long, long);
void randomSeed(unsigned int);
long map(long, long, long, long, long);
#endif
#endif

View File

@ -0,0 +1,515 @@
#ifndef Binary_h
#define Binary_h
#define B0 0
#define B00 0
#define B000 0
#define B0000 0
#define B00000 0
#define B000000 0
#define B0000000 0
#define B00000000 0
#define B1 1
#define B01 1
#define B001 1
#define B0001 1
#define B00001 1
#define B000001 1
#define B0000001 1
#define B00000001 1
#define B10 2
#define B010 2
#define B0010 2
#define B00010 2
#define B000010 2
#define B0000010 2
#define B00000010 2
#define B11 3
#define B011 3
#define B0011 3
#define B00011 3
#define B000011 3
#define B0000011 3
#define B00000011 3
#define B100 4
#define B0100 4
#define B00100 4
#define B000100 4
#define B0000100 4
#define B00000100 4
#define B101 5
#define B0101 5
#define B00101 5
#define B000101 5
#define B0000101 5
#define B00000101 5
#define B110 6
#define B0110 6
#define B00110 6
#define B000110 6
#define B0000110 6
#define B00000110 6
#define B111 7
#define B0111 7
#define B00111 7
#define B000111 7
#define B0000111 7
#define B00000111 7
#define B1000 8
#define B01000 8
#define B001000 8
#define B0001000 8
#define B00001000 8
#define B1001 9
#define B01001 9
#define B001001 9
#define B0001001 9
#define B00001001 9
#define B1010 10
#define B01010 10
#define B001010 10
#define B0001010 10
#define B00001010 10
#define B1011 11
#define B01011 11
#define B001011 11
#define B0001011 11
#define B00001011 11
#define B1100 12
#define B01100 12
#define B001100 12
#define B0001100 12
#define B00001100 12
#define B1101 13
#define B01101 13
#define B001101 13
#define B0001101 13
#define B00001101 13
#define B1110 14
#define B01110 14
#define B001110 14
#define B0001110 14
#define B00001110 14
#define B1111 15
#define B01111 15
#define B001111 15
#define B0001111 15
#define B00001111 15
#define B10000 16
#define B010000 16
#define B0010000 16
#define B00010000 16
#define B10001 17
#define B010001 17
#define B0010001 17
#define B00010001 17
#define B10010 18
#define B010010 18
#define B0010010 18
#define B00010010 18
#define B10011 19
#define B010011 19
#define B0010011 19
#define B00010011 19
#define B10100 20
#define B010100 20
#define B0010100 20
#define B00010100 20
#define B10101 21
#define B010101 21
#define B0010101 21
#define B00010101 21
#define B10110 22
#define B010110 22
#define B0010110 22
#define B00010110 22
#define B10111 23
#define B010111 23
#define B0010111 23
#define B00010111 23
#define B11000 24
#define B011000 24
#define B0011000 24
#define B00011000 24
#define B11001 25
#define B011001 25
#define B0011001 25
#define B00011001 25
#define B11010 26
#define B011010 26
#define B0011010 26
#define B00011010 26
#define B11011 27
#define B011011 27
#define B0011011 27
#define B00011011 27
#define B11100 28
#define B011100 28
#define B0011100 28
#define B00011100 28
#define B11101 29
#define B011101 29
#define B0011101 29
#define B00011101 29
#define B11110 30
#define B011110 30
#define B0011110 30
#define B00011110 30
#define B11111 31
#define B011111 31
#define B0011111 31
#define B00011111 31
#define B100000 32
#define B0100000 32
#define B00100000 32
#define B100001 33
#define B0100001 33
#define B00100001 33
#define B100010 34
#define B0100010 34
#define B00100010 34
#define B100011 35
#define B0100011 35
#define B00100011 35
#define B100100 36
#define B0100100 36
#define B00100100 36
#define B100101 37
#define B0100101 37
#define B00100101 37
#define B100110 38
#define B0100110 38
#define B00100110 38
#define B100111 39
#define B0100111 39
#define B00100111 39
#define B101000 40
#define B0101000 40
#define B00101000 40
#define B101001 41
#define B0101001 41
#define B00101001 41
#define B101010 42
#define B0101010 42
#define B00101010 42
#define B101011 43
#define B0101011 43
#define B00101011 43
#define B101100 44
#define B0101100 44
#define B00101100 44
#define B101101 45
#define B0101101 45
#define B00101101 45
#define B101110 46
#define B0101110 46
#define B00101110 46
#define B101111 47
#define B0101111 47
#define B00101111 47
#define B110000 48
#define B0110000 48
#define B00110000 48
#define B110001 49
#define B0110001 49
#define B00110001 49
#define B110010 50
#define B0110010 50
#define B00110010 50
#define B110011 51
#define B0110011 51
#define B00110011 51
#define B110100 52
#define B0110100 52
#define B00110100 52
#define B110101 53
#define B0110101 53
#define B00110101 53
#define B110110 54
#define B0110110 54
#define B00110110 54
#define B110111 55
#define B0110111 55
#define B00110111 55
#define B111000 56
#define B0111000 56
#define B00111000 56
#define B111001 57
#define B0111001 57
#define B00111001 57
#define B111010 58
#define B0111010 58
#define B00111010 58
#define B111011 59
#define B0111011 59
#define B00111011 59
#define B111100 60
#define B0111100 60
#define B00111100 60
#define B111101 61
#define B0111101 61
#define B00111101 61
#define B111110 62
#define B0111110 62
#define B00111110 62
#define B111111 63
#define B0111111 63
#define B00111111 63
#define B1000000 64
#define B01000000 64
#define B1000001 65
#define B01000001 65
#define B1000010 66
#define B01000010 66
#define B1000011 67
#define B01000011 67
#define B1000100 68
#define B01000100 68
#define B1000101 69
#define B01000101 69
#define B1000110 70
#define B01000110 70
#define B1000111 71
#define B01000111 71
#define B1001000 72
#define B01001000 72
#define B1001001 73
#define B01001001 73
#define B1001010 74
#define B01001010 74
#define B1001011 75
#define B01001011 75
#define B1001100 76
#define B01001100 76
#define B1001101 77
#define B01001101 77
#define B1001110 78
#define B01001110 78
#define B1001111 79
#define B01001111 79
#define B1010000 80
#define B01010000 80
#define B1010001 81
#define B01010001 81
#define B1010010 82
#define B01010010 82
#define B1010011 83
#define B01010011 83
#define B1010100 84
#define B01010100 84
#define B1010101 85
#define B01010101 85
#define B1010110 86
#define B01010110 86
#define B1010111 87
#define B01010111 87
#define B1011000 88
#define B01011000 88
#define B1011001 89
#define B01011001 89
#define B1011010 90
#define B01011010 90
#define B1011011 91
#define B01011011 91
#define B1011100 92
#define B01011100 92
#define B1011101 93
#define B01011101 93
#define B1011110 94
#define B01011110 94
#define B1011111 95
#define B01011111 95
#define B1100000 96
#define B01100000 96
#define B1100001 97
#define B01100001 97
#define B1100010 98
#define B01100010 98
#define B1100011 99
#define B01100011 99
#define B1100100 100
#define B01100100 100
#define B1100101 101
#define B01100101 101
#define B1100110 102
#define B01100110 102
#define B1100111 103
#define B01100111 103
#define B1101000 104
#define B01101000 104
#define B1101001 105
#define B01101001 105
#define B1101010 106
#define B01101010 106
#define B1101011 107
#define B01101011 107
#define B1101100 108
#define B01101100 108
#define B1101101 109
#define B01101101 109
#define B1101110 110
#define B01101110 110
#define B1101111 111
#define B01101111 111
#define B1110000 112
#define B01110000 112
#define B1110001 113
#define B01110001 113
#define B1110010 114
#define B01110010 114
#define B1110011 115
#define B01110011 115
#define B1110100 116
#define B01110100 116
#define B1110101 117
#define B01110101 117
#define B1110110 118
#define B01110110 118
#define B1110111 119
#define B01110111 119
#define B1111000 120
#define B01111000 120
#define B1111001 121
#define B01111001 121
#define B1111010 122
#define B01111010 122
#define B1111011 123
#define B01111011 123
#define B1111100 124
#define B01111100 124
#define B1111101 125
#define B01111101 125
#define B1111110 126
#define B01111110 126
#define B1111111 127
#define B01111111 127
#define B10000000 128
#define B10000001 129
#define B10000010 130
#define B10000011 131
#define B10000100 132
#define B10000101 133
#define B10000110 134
#define B10000111 135
#define B10001000 136
#define B10001001 137
#define B10001010 138
#define B10001011 139
#define B10001100 140
#define B10001101 141
#define B10001110 142
#define B10001111 143
#define B10010000 144
#define B10010001 145
#define B10010010 146
#define B10010011 147
#define B10010100 148
#define B10010101 149
#define B10010110 150
#define B10010111 151
#define B10011000 152
#define B10011001 153
#define B10011010 154
#define B10011011 155
#define B10011100 156
#define B10011101 157
#define B10011110 158
#define B10011111 159
#define B10100000 160
#define B10100001 161
#define B10100010 162
#define B10100011 163
#define B10100100 164
#define B10100101 165
#define B10100110 166
#define B10100111 167
#define B10101000 168
#define B10101001 169
#define B10101010 170
#define B10101011 171
#define B10101100 172
#define B10101101 173
#define B10101110 174
#define B10101111 175
#define B10110000 176
#define B10110001 177
#define B10110010 178
#define B10110011 179
#define B10110100 180
#define B10110101 181
#define B10110110 182
#define B10110111 183
#define B10111000 184
#define B10111001 185
#define B10111010 186
#define B10111011 187
#define B10111100 188
#define B10111101 189
#define B10111110 190
#define B10111111 191
#define B11000000 192
#define B11000001 193
#define B11000010 194
#define B11000011 195
#define B11000100 196
#define B11000101 197
#define B11000110 198
#define B11000111 199
#define B11001000 200
#define B11001001 201
#define B11001010 202
#define B11001011 203
#define B11001100 204
#define B11001101 205
#define B11001110 206
#define B11001111 207
#define B11010000 208
#define B11010001 209
#define B11010010 210
#define B11010011 211
#define B11010100 212
#define B11010101 213
#define B11010110 214
#define B11010111 215
#define B11011000 216
#define B11011001 217
#define B11011010 218
#define B11011011 219
#define B11011100 220
#define B11011101 221
#define B11011110 222
#define B11011111 223
#define B11100000 224
#define B11100001 225
#define B11100010 226
#define B11100011 227
#define B11100100 228
#define B11100101 229
#define B11100110 230
#define B11100111 231
#define B11101000 232
#define B11101001 233
#define B11101010 234
#define B11101011 235
#define B11101100 236
#define B11101101 237
#define B11101110 238
#define B11101111 239
#define B11110000 240
#define B11110001 241
#define B11110010 242
#define B11110011 243
#define B11110100 244
#define B11110101 245
#define B11110110 246
#define B11110111 247
#define B11111000 248
#define B11111001 249
#define B11111010 250
#define B11111011 251
#define B11111100 252
#define B11111101 253
#define B11111110 254
#define B11111111 255
#endif

12
hardware/cores/arduino/main.cxx Executable file
View File

@ -0,0 +1,12 @@
int main(void)
{
init();
setup();
for (;;)
loop();
return 0;
}

View File

@ -0,0 +1,469 @@
/*
pins_arduino.c - pin definitions for the Arduino board
Part of Arduino / Wiring Lite
Copyright (c) 2005 David A. Mellis
This library 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 2.1 of the License, or (at your option) any later version.
This library 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
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General
Public License along with this library; if not, write to the
Free Software Foundation, Inc., 59 Temple Place, Suite 330,
Boston, MA 02111-1307 USA
$Id$
*/
#include <avr/io.h>
#include "wiring_private.h"
#include "pins_arduino.h"
// On the Arduino board, digital pins are also used
// for the analog output (software PWM). Analog input
// pins are a separate set.
// ATMEL ATMEGA8 & 168 / ARDUINO
//
// +-\/-+
// PC6 1| |28 PC5 (AI 5)
// (D 0) PD0 2| |27 PC4 (AI 4)
// (D 1) PD1 3| |26 PC3 (AI 3)
// (D 2) PD2 4| |25 PC2 (AI 2)
// PWM+ (D 3) PD3 5| |24 PC1 (AI 1)
// (D 4) PD4 6| |23 PC0 (AI 0)
// VCC 7| |22 GND
// GND 8| |21 AREF
// PB6 9| |20 AVCC
// PB7 10| |19 PB5 (D 13)
// PWM+ (D 5) PD5 11| |18 PB4 (D 12)
// PWM+ (D 6) PD6 12| |17 PB3 (D 11) PWM
// (D 7) PD7 13| |16 PB2 (D 10) PWM
// (D 8) PB0 14| |15 PB1 (D 9) PWM
// +----+
//
// (PWM+ indicates the additional PWM pins on the ATmega168.)
// ATMEL ATMEGA1280 / ARDUINO
//
// 0-7 PE0-PE7 works
// 8-13 PB0-PB5 works
// 14-21 PA0-PA7 works
// 22-29 PH0-PH7 works
// 30-35 PG5-PG0 works
// 36-43 PC7-PC0 works
// 44-51 PJ7-PJ0 works
// 52-59 PL7-PL0 works
// 60-67 PD7-PD0 works
// A0-A7 PF0-PF7
// A8-A15 PK0-PK7
#define PA 1
#define PB 2
#define PC 3
#define PD 4
#define PE 5
#define PF 6
#define PG 7
#define PH 8
#define PJ 10
#define PK 11
#define PL 12
#define REPEAT8(x) x, x, x, x, x, x, x, x
#define BV0TO7 _BV(0), _BV(1), _BV(2), _BV(3), _BV(4), _BV(5), _BV(6), _BV(7)
#define BV7TO0 _BV(7), _BV(6), _BV(5), _BV(4), _BV(3), _BV(2), _BV(1), _BV(0)
#if defined(__AVR_ATmega1280__)
const uint16_t PROGMEM port_to_mode_PGM[] = {
NOT_A_PORT,
&DDRA,
&DDRB,
&DDRC,
&DDRD,
&DDRE,
&DDRF,
&DDRG,
&DDRH,
NOT_A_PORT,
&DDRJ,
&DDRK,
&DDRL,
};
const uint16_t PROGMEM port_to_output_PGM[] = {
NOT_A_PORT,
&PORTA,
&PORTB,
&PORTC,
&PORTD,
&PORTE,
&PORTF,
&PORTG,
&PORTH,
NOT_A_PORT,
&PORTJ,
&PORTK,
&PORTL,
};
const uint16_t PROGMEM port_to_input_PGM[] = {
NOT_A_PIN,
&PINA,
&PINB,
&PINC,
&PIND,
&PINE,
&PINF,
&PING,
&PINH,
NOT_A_PIN,
&PINJ,
&PINK,
&PINL,
};
const uint8_t PROGMEM digital_pin_to_port_PGM[] = {
// PORTLIST
// -------------------------------------------
PE , // PE 0 ** 0 ** USART0_RX
PE , // PE 1 ** 1 ** USART0_TX
PE , // PE 4 ** 2 ** PWM2
PE , // PE 5 ** 3 ** PWM3
PG , // PG 5 ** 4 ** PWM4
PE , // PE 3 ** 5 ** PWM5
PH , // PH 3 ** 6 ** PWM6
PH , // PH 4 ** 7 ** PWM7
PH , // PH 5 ** 8 ** PWM8
PH , // PH 6 ** 9 ** PWM9
PB , // PB 4 ** 10 ** PWM10
PB , // PB 5 ** 11 ** PWM11
PB , // PB 6 ** 12 ** PWM12
PB , // PB 7 ** 13 ** PWM13
PJ , // PJ 1 ** 14 ** USART3_TX
PJ , // PJ 0 ** 15 ** USART3_RX
PH , // PH 1 ** 16 ** USART2_TX
PH , // PH 0 ** 17 ** USART2_RX
PD , // PD 3 ** 18 ** USART1_TX
PD , // PD 2 ** 19 ** USART1_RX
PD , // PD 1 ** 20 ** I2C_SDA
PD , // PD 0 ** 21 ** I2C_SCL
PA , // PA 0 ** 22 ** D22
PA , // PA 1 ** 23 ** D23
PA , // PA 2 ** 24 ** D24
PA , // PA 3 ** 25 ** D25
PA , // PA 4 ** 26 ** D26
PA , // PA 5 ** 27 ** D27
PA , // PA 6 ** 28 ** D28
PA , // PA 7 ** 29 ** D29
PC , // PC 7 ** 30 ** D30
PC , // PC 6 ** 31 ** D31
PC , // PC 5 ** 32 ** D32
PC , // PC 4 ** 33 ** D33
PC , // PC 3 ** 34 ** D34
PC , // PC 2 ** 35 ** D35
PC , // PC 1 ** 36 ** D36
PC , // PC 0 ** 37 ** D37
PD , // PD 7 ** 38 ** D38
PG , // PG 2 ** 39 ** D39
PG , // PG 1 ** 40 ** D40
PG , // PG 0 ** 41 ** D41
PL , // PL 7 ** 42 ** D42
PL , // PL 6 ** 43 ** D43
PL , // PL 5 ** 44 ** D44
PL , // PL 4 ** 45 ** D45
PL , // PL 3 ** 46 ** D46
PL , // PL 2 ** 47 ** D47
PL , // PL 1 ** 48 ** D48
PL , // PL 0 ** 49 ** D49
PB , // PB 3 ** 50 ** SPI_MISO
PB , // PB 2 ** 51 ** SPI_MOSI
PB , // PB 1 ** 52 ** SPI_SCK
PB , // PB 0 ** 53 ** SPI_SS
PF , // PF 0 ** 54 ** A0
PF , // PF 1 ** 55 ** A1
PF , // PF 2 ** 56 ** A2
PF , // PF 3 ** 57 ** A3
PF , // PF 4 ** 58 ** A4
PF , // PF 5 ** 59 ** A5
PF , // PF 6 ** 60 ** A6
PF , // PF 7 ** 61 ** A7
PK , // PK 0 ** 62 ** A8
PK , // PK 1 ** 63 ** A9
PK , // PK 2 ** 64 ** A10
PK , // PK 3 ** 65 ** A11
PK , // PK 4 ** 66 ** A12
PK , // PK 5 ** 67 ** A13
PK , // PK 6 ** 68 ** A14
PK , // PK 7 ** 69 ** A15
};
const uint8_t PROGMEM digital_pin_to_bit_mask_PGM[] = {
// PIN IN PORT
// -------------------------------------------
_BV( 0 ) , // PE 0 ** 0 ** USART0_RX
_BV( 1 ) , // PE 1 ** 1 ** USART0_TX
_BV( 4 ) , // PE 4 ** 2 ** PWM2
_BV( 5 ) , // PE 5 ** 3 ** PWM3
_BV( 5 ) , // PG 5 ** 4 ** PWM4
_BV( 3 ) , // PE 3 ** 5 ** PWM5
_BV( 3 ) , // PH 3 ** 6 ** PWM6
_BV( 4 ) , // PH 4 ** 7 ** PWM7
_BV( 5 ) , // PH 5 ** 8 ** PWM8
_BV( 6 ) , // PH 6 ** 9 ** PWM9
_BV( 4 ) , // PB 4 ** 10 ** PWM10
_BV( 5 ) , // PB 5 ** 11 ** PWM11
_BV( 6 ) , // PB 6 ** 12 ** PWM12
_BV( 7 ) , // PB 7 ** 13 ** PWM13
_BV( 1 ) , // PJ 1 ** 14 ** USART3_TX
_BV( 0 ) , // PJ 0 ** 15 ** USART3_RX
_BV( 1 ) , // PH 1 ** 16 ** USART2_TX
_BV( 0 ) , // PH 0 ** 17 ** USART2_RX
_BV( 3 ) , // PD 3 ** 18 ** USART1_TX
_BV( 2 ) , // PD 2 ** 19 ** USART1_RX
_BV( 1 ) , // PD 1 ** 20 ** I2C_SDA
_BV( 0 ) , // PD 0 ** 21 ** I2C_SCL
_BV( 0 ) , // PA 0 ** 22 ** D22
_BV( 1 ) , // PA 1 ** 23 ** D23
_BV( 2 ) , // PA 2 ** 24 ** D24
_BV( 3 ) , // PA 3 ** 25 ** D25
_BV( 4 ) , // PA 4 ** 26 ** D26
_BV( 5 ) , // PA 5 ** 27 ** D27
_BV( 6 ) , // PA 6 ** 28 ** D28
_BV( 7 ) , // PA 7 ** 29 ** D29
_BV( 7 ) , // PC 7 ** 30 ** D30
_BV( 6 ) , // PC 6 ** 31 ** D31
_BV( 5 ) , // PC 5 ** 32 ** D32
_BV( 4 ) , // PC 4 ** 33 ** D33
_BV( 3 ) , // PC 3 ** 34 ** D34
_BV( 2 ) , // PC 2 ** 35 ** D35
_BV( 1 ) , // PC 1 ** 36 ** D36
_BV( 0 ) , // PC 0 ** 37 ** D37
_BV( 7 ) , // PD 7 ** 38 ** D38
_BV( 2 ) , // PG 2 ** 39 ** D39
_BV( 1 ) , // PG 1 ** 40 ** D40
_BV( 0 ) , // PG 0 ** 41 ** D41
_BV( 7 ) , // PL 7 ** 42 ** D42
_BV( 6 ) , // PL 6 ** 43 ** D43
_BV( 5 ) , // PL 5 ** 44 ** D44
_BV( 4 ) , // PL 4 ** 45 ** D45
_BV( 3 ) , // PL 3 ** 46 ** D46
_BV( 2 ) , // PL 2 ** 47 ** D47
_BV( 1 ) , // PL 1 ** 48 ** D48
_BV( 0 ) , // PL 0 ** 49 ** D49
_BV( 3 ) , // PB 3 ** 50 ** SPI_MISO
_BV( 2 ) , // PB 2 ** 51 ** SPI_MOSI
_BV( 1 ) , // PB 1 ** 52 ** SPI_SCK
_BV( 0 ) , // PB 0 ** 53 ** SPI_SS
_BV( 0 ) , // PF 0 ** 54 ** A0
_BV( 1 ) , // PF 1 ** 55 ** A1
_BV( 2 ) , // PF 2 ** 56 ** A2
_BV( 3 ) , // PF 3 ** 57 ** A3
_BV( 4 ) , // PF 4 ** 58 ** A4
_BV( 5 ) , // PF 5 ** 59 ** A5
_BV( 6 ) , // PF 6 ** 60 ** A6
_BV( 7 ) , // PF 7 ** 61 ** A7
_BV( 0 ) , // PK 0 ** 62 ** A8
_BV( 1 ) , // PK 1 ** 63 ** A9
_BV( 2 ) , // PK 2 ** 64 ** A10
_BV( 3 ) , // PK 3 ** 65 ** A11
_BV( 4 ) , // PK 4 ** 66 ** A12
_BV( 5 ) , // PK 5 ** 67 ** A13
_BV( 6 ) , // PK 6 ** 68 ** A14
_BV( 7 ) , // PK 7 ** 69 ** A15
};
const uint8_t PROGMEM digital_pin_to_timer_PGM[] = {
// TIMERS
// -------------------------------------------
NOT_ON_TIMER , // PE 0 ** 0 ** USART0_RX
NOT_ON_TIMER , // PE 1 ** 1 ** USART0_TX
TIMER3B , // PE 4 ** 2 ** PWM2
TIMER3C , // PE 5 ** 3 ** PWM3
TIMER0B , // PG 5 ** 4 ** PWM4
TIMER3A , // PE 3 ** 5 ** PWM5
TIMER4A , // PH 3 ** 6 ** PWM6
TIMER4B , // PH 4 ** 7 ** PWM7
TIMER4C , // PH 5 ** 8 ** PWM8
TIMER2B , // PH 6 ** 9 ** PWM9
TIMER2A , // PB 4 ** 10 ** PWM10
TIMER1A , // PB 5 ** 11 ** PWM11
TIMER1B , // PB 6 ** 12 ** PWM12
TIMER0A , // PB 7 ** 13 ** PWM13
NOT_ON_TIMER , // PJ 1 ** 14 ** USART3_TX
NOT_ON_TIMER , // PJ 0 ** 15 ** USART3_RX
NOT_ON_TIMER , // PH 1 ** 16 ** USART2_TX
NOT_ON_TIMER , // PH 0 ** 17 ** USART2_RX
NOT_ON_TIMER , // PD 3 ** 18 ** USART1_TX
NOT_ON_TIMER , // PD 2 ** 19 ** USART1_RX
NOT_ON_TIMER , // PD 1 ** 20 ** I2C_SDA
NOT_ON_TIMER , // PD 0 ** 21 ** I2C_SCL
NOT_ON_TIMER , // PA 0 ** 22 ** D22
NOT_ON_TIMER , // PA 1 ** 23 ** D23
NOT_ON_TIMER , // PA 2 ** 24 ** D24
NOT_ON_TIMER , // PA 3 ** 25 ** D25
NOT_ON_TIMER , // PA 4 ** 26 ** D26
NOT_ON_TIMER , // PA 5 ** 27 ** D27
NOT_ON_TIMER , // PA 6 ** 28 ** D28
NOT_ON_TIMER , // PA 7 ** 29 ** D29
NOT_ON_TIMER , // PC 7 ** 30 ** D30
NOT_ON_TIMER , // PC 6 ** 31 ** D31
NOT_ON_TIMER , // PC 5 ** 32 ** D32
NOT_ON_TIMER , // PC 4 ** 33 ** D33
NOT_ON_TIMER , // PC 3 ** 34 ** D34
NOT_ON_TIMER , // PC 2 ** 35 ** D35
NOT_ON_TIMER , // PC 1 ** 36 ** D36
NOT_ON_TIMER , // PC 0 ** 37 ** D37
NOT_ON_TIMER , // PD 7 ** 38 ** D38
NOT_ON_TIMER , // PG 2 ** 39 ** D39
NOT_ON_TIMER , // PG 1 ** 40 ** D40
NOT_ON_TIMER , // PG 0 ** 41 ** D41
NOT_ON_TIMER , // PL 7 ** 42 ** D42
NOT_ON_TIMER , // PL 6 ** 43 ** D43
TIMER5C , // PL 5 ** 44 ** D44
TIMER5B , // PL 4 ** 45 ** D45
TIMER5A , // PL 3 ** 46 ** D46
NOT_ON_TIMER , // PL 2 ** 47 ** D47
NOT_ON_TIMER , // PL 1 ** 48 ** D48
NOT_ON_TIMER , // PL 0 ** 49 ** D49
NOT_ON_TIMER , // PB 3 ** 50 ** SPI_MISO
NOT_ON_TIMER , // PB 2 ** 51 ** SPI_MOSI
NOT_ON_TIMER , // PB 1 ** 52 ** SPI_SCK
NOT_ON_TIMER , // PB 0 ** 53 ** SPI_SS
NOT_ON_TIMER , // PF 0 ** 54 ** A0
NOT_ON_TIMER , // PF 1 ** 55 ** A1
NOT_ON_TIMER , // PF 2 ** 56 ** A2
NOT_ON_TIMER , // PF 3 ** 57 ** A3
NOT_ON_TIMER , // PF 4 ** 58 ** A4
NOT_ON_TIMER , // PF 5 ** 59 ** A5
NOT_ON_TIMER , // PF 6 ** 60 ** A6
NOT_ON_TIMER , // PF 7 ** 61 ** A7
NOT_ON_TIMER , // PK 0 ** 62 ** A8
NOT_ON_TIMER , // PK 1 ** 63 ** A9
NOT_ON_TIMER , // PK 2 ** 64 ** A10
NOT_ON_TIMER , // PK 3 ** 65 ** A11
NOT_ON_TIMER , // PK 4 ** 66 ** A12
NOT_ON_TIMER , // PK 5 ** 67 ** A13
NOT_ON_TIMER , // PK 6 ** 68 ** A14
NOT_ON_TIMER , // PK 7 ** 69 ** A15
};
#else
// these arrays map port names (e.g. port B) to the
// appropriate addresses for various functions (e.g. reading
// and writing)
const uint16_t PROGMEM port_to_mode_PGM[] = {
NOT_A_PORT,
NOT_A_PORT,
&DDRB,
&DDRC,
&DDRD,
};
const uint16_t PROGMEM port_to_output_PGM[] = {
NOT_A_PORT,
NOT_A_PORT,
&PORTB,
&PORTC,
&PORTD,
};
const uint16_t PROGMEM port_to_input_PGM[] = {
NOT_A_PORT,
NOT_A_PORT,
&PINB,
&PINC,
&PIND,
};
const uint8_t PROGMEM digital_pin_to_port_PGM[] = {
PD, /* 0 */
PD,
PD,
PD,
PD,
PD,
PD,
PD,
PB, /* 8 */
PB,
PB,
PB,
PB,
PB,
PC, /* 14 */
PC,
PC,
PC,
PC,
PC,
};
const uint8_t PROGMEM digital_pin_to_bit_mask_PGM[] = {
_BV(0), /* 0, port D */
_BV(1),
_BV(2),
_BV(3),
_BV(4),
_BV(5),
_BV(6),
_BV(7),
_BV(0), /* 8, port B */
_BV(1),
_BV(2),
_BV(3),
_BV(4),
_BV(5),
_BV(0), /* 14, port C */
_BV(1),
_BV(2),
_BV(3),
_BV(4),
_BV(5),
};
const uint8_t PROGMEM digital_pin_to_timer_PGM[] = {
NOT_ON_TIMER, /* 0 - port D */
NOT_ON_TIMER,
NOT_ON_TIMER,
// on the ATmega168, digital pin 3 has hardware pwm
#if defined(__AVR_ATmega8__)
NOT_ON_TIMER,
#else
TIMER2B,
#endif
NOT_ON_TIMER,
// on the ATmega168, digital pins 5 and 6 have hardware pwm
#if defined(__AVR_ATmega8__)
NOT_ON_TIMER,
NOT_ON_TIMER,
#else
TIMER0B,
TIMER0A,
#endif
NOT_ON_TIMER,
NOT_ON_TIMER, /* 8 - port B */
TIMER1A,
TIMER1B,
#if defined(__AVR_ATmega8__)
TIMER2,
#else
TIMER2A,
#endif
NOT_ON_TIMER,
NOT_ON_TIMER,
NOT_ON_TIMER,
NOT_ON_TIMER, /* 14 - port C */
NOT_ON_TIMER,
NOT_ON_TIMER,
NOT_ON_TIMER,
NOT_ON_TIMER,
};
#endif

View File

@ -0,0 +1,76 @@
/*
pins_arduino.h - Pin definition functions for Arduino
Part of Arduino - http://www.arduino.cc/
Copyright (c) 2007 David A. Mellis
This library 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 2.1 of the License, or (at your option) any later version.
This library 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
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General
Public License along with this library; if not, write to the
Free Software Foundation, Inc., 59 Temple Place, Suite 330,
Boston, MA 02111-1307 USA
$Id: wiring.h 249 2007-02-03 16:52:51Z mellis $
*/
#ifndef Pins_Arduino_h
#define Pins_Arduino_h
#include <avr/pgmspace.h>
#define NOT_A_PIN 0
#define NOT_A_PORT 0
#define NOT_ON_TIMER 0
#define TIMER0A 1
#define TIMER0B 2
#define TIMER1A 3
#define TIMER1B 4
#define TIMER2 5
#define TIMER2A 6
#define TIMER2B 7
#define TIMER3A 8
#define TIMER3B 9
#define TIMER3C 10
#define TIMER4A 11
#define TIMER4B 12
#define TIMER4C 13
#define TIMER5A 14
#define TIMER5B 15
#define TIMER5C 16
// On the ATmega1280, the addresses of some of the port registers are
// greater than 255, so we can't store them in uint8_t's.
extern const uint16_t PROGMEM port_to_mode_PGM[];
extern const uint16_t PROGMEM port_to_input_PGM[];
extern const uint16_t PROGMEM port_to_output_PGM[];
extern const uint8_t PROGMEM digital_pin_to_port_PGM[];
// extern const uint8_t PROGMEM digital_pin_to_bit_PGM[];
extern const uint8_t PROGMEM digital_pin_to_bit_mask_PGM[];
extern const uint8_t PROGMEM digital_pin_to_timer_PGM[];
// Get the bit location within the hardware port of the given virtual pin.
// This comes from the pins_*.c file for the active board configuration.
//
// These perform slightly better as macros compared to inline functions
//
#define digitalPinToPort(P) ( pgm_read_byte( digital_pin_to_port_PGM + (P) ) )
#define digitalPinToBitMask(P) ( pgm_read_byte( digital_pin_to_bit_mask_PGM + (P) ) )
#define digitalPinToTimer(P) ( pgm_read_byte( digital_pin_to_timer_PGM + (P) ) )
#define analogInPinToBit(P) (P)
#define portOutputRegister(P) ( (volatile uint8_t *)( pgm_read_word( port_to_output_PGM + (P))) )
#define portInputRegister(P) ( (volatile uint8_t *)( pgm_read_word( port_to_input_PGM + (P))) )
#define portModeRegister(P) ( (volatile uint8_t *)( pgm_read_word( port_to_mode_PGM + (P))) )
#endif

250
hardware/cores/arduino/wiring.c Executable file
View File

@ -0,0 +1,250 @@
/*
wiring.c - Partial implementation of the Wiring API for the ATmega8.
Part of Arduino - http://www.arduino.cc/
Copyright (c) 2005-2006 David A. Mellis
This library 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 2.1 of the License, or (at your option) any later version.
This library 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
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General
Public License along with this library; if not, write to the
Free Software Foundation, Inc., 59 Temple Place, Suite 330,
Boston, MA 02111-1307 USA
$Id$
*/
#include "wiring_private.h"
// the prescaler is set so that timer0 ticks every 64 clock cycles, and the
// the overflow handler is called every 256 ticks.
#define MICROSECONDS_PER_TIMER0_OVERFLOW (clockCyclesToMicroseconds(64 * 256))
// the whole number of milliseconds per timer0 overflow
#define MILLIS_INC (MICROSECONDS_PER_TIMER0_OVERFLOW / 1000)
// the fractional number of milliseconds per timer0 overflow. we shift right
// by three to fit these numbers into a byte. (for the clock speeds we care
// about - 8 and 16 MHz - this doesn't lose precision.)
#define FRACT_INC ((MICROSECONDS_PER_TIMER0_OVERFLOW % 1000) >> 3)
#define FRACT_MAX (1000 >> 3)
volatile unsigned long timer0_overflow_count = 0;
volatile unsigned long timer0_millis = 0;
static unsigned char timer0_fract = 0;
SIGNAL(TIMER0_OVF_vect)
{
// copy these to local variables so they can be stored in registers
// (volatile variables must be read from memory on every access)
unsigned long m = timer0_millis;
unsigned char f = timer0_fract;
m += MILLIS_INC;
f += FRACT_INC;
if (f >= FRACT_MAX) {
f -= FRACT_MAX;
m += 1;
}
timer0_fract = f;
timer0_millis = m;
timer0_overflow_count++;
}
unsigned long millis()
{
unsigned long m;
uint8_t oldSREG = SREG;
// disable interrupts while we read timer0_millis or we might get an
// inconsistent value (e.g. in the middle of a write to timer0_millis)
cli();
m = timer0_millis;
SREG = oldSREG;
return m;
}
unsigned long micros() {
unsigned long m, t;
uint8_t oldSREG = SREG;
cli();
t = TCNT0;
#ifdef TIFR0
if ((TIFR0 & _BV(TOV0)) && (t == 0))
t = 256;
#else
if ((TIFR & _BV(TOV0)) && (t == 0))
t = 256;
#endif
m = timer0_overflow_count;
SREG = oldSREG;
return ((m << 8) + t) * (64 / clockCyclesPerMicrosecond());
}
void delay(unsigned long ms)
{
unsigned long start = millis();
while (millis() - start <= ms)
;
}
/* Delay for the given number of microseconds. Assumes a 8 or 16 MHz clock.
* Disables interrupts, which will disrupt the millis() function if used
* too frequently. */
void delayMicroseconds(unsigned int us)
{
uint8_t oldSREG;
// calling avrlib's delay_us() function with low values (e.g. 1 or
// 2 microseconds) gives delays longer than desired.
//delay_us(us);
#if F_CPU >= 16000000L
// for the 16 MHz clock on most Arduino boards
// for a one-microsecond delay, simply return. the overhead
// of the function call yields a delay of approximately 1 1/8 us.
if (--us == 0)
return;
// the following loop takes a quarter of a microsecond (4 cycles)
// per iteration, so execute it four times for each microsecond of
// delay requested.
us <<= 2;
// account for the time taken in the preceeding commands.
us -= 2;
#else
// for the 8 MHz internal clock on the ATmega168
// for a one- or two-microsecond delay, simply return. the overhead of
// the function calls takes more than two microseconds. can't just
// subtract two, since us is unsigned; we'd overflow.
if (--us == 0)
return;
if (--us == 0)
return;
// the following loop takes half of a microsecond (4 cycles)
// per iteration, so execute it twice for each microsecond of
// delay requested.
us <<= 1;
// partially compensate for the time taken by the preceeding commands.
// we can't subtract any more than this or we'd overflow w/ small delays.
us--;
#endif
// disable interrupts, otherwise the timer 0 overflow interrupt that
// tracks milliseconds will make us delay longer than we want.
oldSREG = SREG;
cli();
// busy wait
__asm__ __volatile__ (
"1: sbiw %0,1" "\n\t" // 2 cycles
"brne 1b" : "=w" (us) : "0" (us) // 2 cycles
);
// reenable interrupts.
SREG = oldSREG;
}
void init()
{
// this needs to be called before setup() or some functions won't
// work there
sei();
// on the ATmega168, timer 0 is also used for fast hardware pwm
// (using phase-correct PWM would mean that timer 0 overflowed half as often
// resulting in different millis() behavior on the ATmega8 and ATmega168)
#if !defined(__AVR_ATmega8__)
sbi(TCCR0A, WGM01);
sbi(TCCR0A, WGM00);
#endif
// set timer 0 prescale factor to 64
#if defined(__AVR_ATmega8__)
sbi(TCCR0, CS01);
sbi(TCCR0, CS00);
#else
sbi(TCCR0B, CS01);
sbi(TCCR0B, CS00);
#endif
// enable timer 0 overflow interrupt
#if defined(__AVR_ATmega8__)
sbi(TIMSK, TOIE0);
#else
sbi(TIMSK0, TOIE0);
#endif
// timers 1 and 2 are used for phase-correct hardware pwm
// this is better for motors as it ensures an even waveform
// note, however, that fast pwm mode can achieve a frequency of up
// 8 MHz (with a 16 MHz clock) at 50% duty cycle
// set timer 1 prescale factor to 64
sbi(TCCR1B, CS11);
sbi(TCCR1B, CS10);
// put timer 1 in 8-bit phase correct pwm mode
sbi(TCCR1A, WGM10);
// set timer 2 prescale factor to 64
#if defined(__AVR_ATmega8__)
sbi(TCCR2, CS22);
#else
sbi(TCCR2B, CS22);
#endif
// configure timer 2 for phase correct pwm (8-bit)
#if defined(__AVR_ATmega8__)
sbi(TCCR2, WGM20);
#else
sbi(TCCR2A, WGM20);
#endif
#if defined(__AVR_ATmega1280__)
// set timer 3, 4, 5 prescale factor to 64
sbi(TCCR3B, CS31); sbi(TCCR3B, CS30);
sbi(TCCR4B, CS41); sbi(TCCR4B, CS40);
sbi(TCCR5B, CS51); sbi(TCCR5B, CS50);
// put timer 3, 4, 5 in 8-bit phase correct pwm mode
sbi(TCCR3A, WGM30);
sbi(TCCR4A, WGM40);
sbi(TCCR5A, WGM50);
#endif
// set a2d prescale factor to 128
// 16 MHz / 128 = 125 KHz, inside the desired 50-200 KHz range.
// XXX: this will not work properly for other clock speeds, and
// this code should use F_CPU to determine the prescale factor.
sbi(ADCSRA, ADPS2);
sbi(ADCSRA, ADPS1);
sbi(ADCSRA, ADPS0);
// enable a2d conversions
sbi(ADCSRA, ADEN);
// the bootloader connects pins 0 and 1 to the USART; disconnect them
// here so they can be used as normal digital i/o; they will be
// reconnected in Serial.begin()
#if defined(__AVR_ATmega8__)
UCSRB = 0;
#else
UCSR0B = 0;
#endif
}

137
hardware/cores/arduino/wiring.h Executable file
View File

@ -0,0 +1,137 @@
/*
wiring.h - Partial implementation of the Wiring API for the ATmega8.
Part of Arduino - http://www.arduino.cc/
Copyright (c) 2005-2006 David A. Mellis
This library 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 2.1 of the License, or (at your option) any later version.
This library 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
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General
Public License along with this library; if not, write to the
Free Software Foundation, Inc., 59 Temple Place, Suite 330,
Boston, MA 02111-1307 USA
$Id$
*/
#ifndef Wiring_h
#define Wiring_h
#include <avr/io.h>
#include "binary.h"
#ifdef __cplusplus
extern "C"{
#endif
#ifndef ARDUINO
#define ARDUINO 16
#endif
#define HIGH 0x1
#define LOW 0x0
#define INPUT 0x0
#define OUTPUT 0x1
#define true 0x1
#define false 0x0
#define PI 3.1415926535897932384626433832795
#define HALF_PI 1.5707963267948966192313216916398
#define TWO_PI 6.283185307179586476925286766559
#define DEG_TO_RAD 0.017453292519943295769236907684886
#define RAD_TO_DEG 57.295779513082320876798154814105
#define SERIAL 0x0
#define DISPLAY 0x1
#define LSBFIRST 0
#define MSBFIRST 1
#define CHANGE 1
#define FALLING 2
#define RISING 3
#define INTERNAL 3
#define DEFAULT 1
#define EXTERNAL 0
// undefine stdlib's abs if encountered
#ifdef abs
#undef abs
#endif
#define min(a,b) ((a)<(b)?(a):(b))
#define max(a,b) ((a)>(b)?(a):(b))
#define abs(x) ((x)>0?(x):-(x))
#define constrain(amt,low,high) ((amt)<(low)?(low):((amt)>(high)?(high):(amt)))
#define round(x) ((x)>=0?(long)((x)+0.5):(long)((x)-0.5))
#define radians(deg) ((deg)*DEG_TO_RAD)
#define degrees(rad) ((rad)*RAD_TO_DEG)
#define sq(x) ((x)*(x))
#define interrupts() sei()
#define noInterrupts() cli()
#define clockCyclesPerMicrosecond() ( F_CPU / 1000000L )
#define clockCyclesToMicroseconds(a) ( (a) / clockCyclesPerMicrosecond() )
#define microsecondsToClockCycles(a) ( (a) * clockCyclesPerMicrosecond() )
#define lowByte(w) ((uint8_t) ((w) & 0xff))
#define highByte(w) ((uint8_t) ((w) >> 8))
#define bitRead(value, bit) (((value) >> (bit)) & 0x01)
#define bitSet(value, bit) ((value) |= (1UL << (bit)))
#define bitClear(value, bit) ((value) &= ~(1UL << (bit)))
#define bitWrite(value, bit, bitvalue) (bitvalue ? bitSet(value, bit) : bitClear(value, bit))
typedef unsigned int word;
#define bit(b) (1UL << (b))
typedef uint8_t boolean;
typedef uint8_t byte;
void init(void);
void pinMode(uint8_t, uint8_t);
void digitalWrite(uint8_t, uint8_t);
int digitalRead(uint8_t);
int analogRead(uint8_t);
void analogReference(uint8_t mode);
void analogWrite(uint8_t, int);
void beginSerial(long);
void serialWrite(unsigned char);
int serialAvailable(void);
int serialRead(void);
void serialFlush(void);
unsigned long millis(void);
unsigned long micros(void);
void delay(unsigned long);
void delayMicroseconds(unsigned int us);
unsigned long pulseIn(uint8_t pin, uint8_t state, unsigned long timeout);
void shiftOut(uint8_t dataPin, uint8_t clockPin, uint8_t bitOrder, byte val);
void attachInterrupt(uint8_t, void (*)(void), int mode);
void detachInterrupt(uint8_t);
void setup(void);
void loop(void);
#ifdef __cplusplus
} // extern "C"
#endif
#endif

View File

@ -0,0 +1,179 @@
/*
wiring_analog.c - analog input and output
Part of Arduino - http://www.arduino.cc/
Copyright (c) 2005-2006 David A. Mellis
This library 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 2.1 of the License, or (at your option) any later version.
This library 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
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General
Public License along with this library; if not, write to the
Free Software Foundation, Inc., 59 Temple Place, Suite 330,
Boston, MA 02111-1307 USA
$Id: wiring.c 248 2007-02-03 15:36:30Z mellis $
*/
#include "wiring_private.h"
#include "pins_arduino.h"
uint8_t analog_reference = DEFAULT;
void analogReference(uint8_t mode)
{
// can't actually set the register here because the default setting
// will connect AVCC and the AREF pin, which would cause a short if
// there's something connected to AREF.
analog_reference = mode;
}
int analogRead(uint8_t pin)
{
uint8_t low, high;
// set the analog reference (high two bits of ADMUX) and select the
// channel (low 4 bits). this also sets ADLAR (left-adjust result)
// to 0 (the default).
ADMUX = (analog_reference << 6) | (pin & 0x07);
#if defined(__AVR_ATmega1280__)
// the MUX5 bit of ADCSRB selects whether we're reading from channels
// 0 to 7 (MUX5 low) or 8 to 15 (MUX5 high).
ADCSRB = (ADCSRB & ~(1 << MUX5)) | (((pin >> 3) & 0x01) << MUX5);
#endif
// without a delay, we seem to read from the wrong channel
//delay(1);
// start the conversion
sbi(ADCSRA, ADSC);
// ADSC is cleared when the conversion finishes
while (bit_is_set(ADCSRA, ADSC));
// we have to read ADCL first; doing so locks both ADCL
// and ADCH until ADCH is read. reading ADCL second would
// cause the results of each conversion to be discarded,
// as ADCL and ADCH would be locked when it completed.
low = ADCL;
high = ADCH;
// combine the two bytes
return (high << 8) | low;
}
// Right now, PWM output only works on the pins with
// hardware support. These are defined in the appropriate
// pins_*.c file. For the rest of the pins, we default
// to digital output.
void analogWrite(uint8_t pin, int val)
{
// We need to make sure the PWM output is enabled for those pins
// that support it, as we turn it off when digitally reading or
// writing with them. Also, make sure the pin is in output mode
// for consistenty with Wiring, which doesn't require a pinMode
// call for the analog output pins.
pinMode(pin, OUTPUT);
if (digitalPinToTimer(pin) == TIMER1A) {
// connect pwm to pin on timer 1, channel A
sbi(TCCR1A, COM1A1);
// set pwm duty
OCR1A = val;
} else if (digitalPinToTimer(pin) == TIMER1B) {
// connect pwm to pin on timer 1, channel B
sbi(TCCR1A, COM1B1);
// set pwm duty
OCR1B = val;
#if defined(__AVR_ATmega8__)
} else if (digitalPinToTimer(pin) == TIMER2) {
// connect pwm to pin on timer 2, channel B
sbi(TCCR2, COM21);
// set pwm duty
OCR2 = val;
#else
} else if (digitalPinToTimer(pin) == TIMER0A) {
if (val == 0) {
digitalWrite(pin, LOW);
} else {
// connect pwm to pin on timer 0, channel A
sbi(TCCR0A, COM0A1);
// set pwm duty
OCR0A = val;
}
} else if (digitalPinToTimer(pin) == TIMER0B) {
if (val == 0) {
digitalWrite(pin, LOW);
} else {
// connect pwm to pin on timer 0, channel B
sbi(TCCR0A, COM0B1);
// set pwm duty
OCR0B = val;
}
} else if (digitalPinToTimer(pin) == TIMER2A) {
// connect pwm to pin on timer 2, channel A
sbi(TCCR2A, COM2A1);
// set pwm duty
OCR2A = val;
} else if (digitalPinToTimer(pin) == TIMER2B) {
// connect pwm to pin on timer 2, channel B
sbi(TCCR2A, COM2B1);
// set pwm duty
OCR2B = val;
#endif
#if defined(__AVR_ATmega1280__)
// XXX: need to handle other timers here
} else if (digitalPinToTimer(pin) == TIMER3A) {
// connect pwm to pin on timer 3, channel A
sbi(TCCR3A, COM3A1);
// set pwm duty
OCR3A = val;
} else if (digitalPinToTimer(pin) == TIMER3B) {
// connect pwm to pin on timer 3, channel B
sbi(TCCR3A, COM3B1);
// set pwm duty
OCR3B = val;
} else if (digitalPinToTimer(pin) == TIMER3C) {
// connect pwm to pin on timer 3, channel C
sbi(TCCR3A, COM3C1);
// set pwm duty
OCR3C = val;
} else if (digitalPinToTimer(pin) == TIMER4A) {
// connect pwm to pin on timer 4, channel A
sbi(TCCR4A, COM4A1);
// set pwm duty
OCR4A = val;
} else if (digitalPinToTimer(pin) == TIMER4B) {
// connect pwm to pin on timer 4, channel B
sbi(TCCR4A, COM4B1);
// set pwm duty
OCR4B = val;
} else if (digitalPinToTimer(pin) == TIMER4C) {
// connect pwm to pin on timer 4, channel C
sbi(TCCR4A, COM4C1);
// set pwm duty
OCR4C = val;
} else if (digitalPinToTimer(pin) == TIMER5A) {
// connect pwm to pin on timer 5, channel A
sbi(TCCR5A, COM5A1);
// set pwm duty
OCR5A = val;
} else if (digitalPinToTimer(pin) == TIMER5B) {
// connect pwm to pin on timer 5, channel B
sbi(TCCR5A, COM5B1);
// set pwm duty
OCR5B = val;
#endif
} else if (val < 128)
digitalWrite(pin, LOW);
else
digitalWrite(pin, HIGH);
}

View File

@ -0,0 +1,111 @@
/*
wiring_digital.c - digital input and output functions
Part of Arduino - http://www.arduino.cc/
Copyright (c) 2005-2006 David A. Mellis
This library 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 2.1 of the License, or (at your option) any later version.
This library 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
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General
Public License along with this library; if not, write to the
Free Software Foundation, Inc., 59 Temple Place, Suite 330,
Boston, MA 02111-1307 USA
$Id: wiring.c 248 2007-02-03 15:36:30Z mellis $
*/
#include "wiring_private.h"
#include "pins_arduino.h"
void pinMode(uint8_t pin, uint8_t mode)
{
uint8_t bit = digitalPinToBitMask(pin);
uint8_t port = digitalPinToPort(pin);
volatile uint8_t *reg;
if (port == NOT_A_PIN) return;
// JWS: can I let the optimizer do this?
reg = portModeRegister(port);
if (mode == INPUT) *reg &= ~bit;
else *reg |= bit;
}
// Forcing this inline keeps the callers from having to push their own stuff
// on the stack. It is a good performance win and only takes 1 more byte per
// user than calling. (It will take more bytes on the 168.)
//
// But shouldn't this be moved into pinMode? Seems silly to check and do on
// each digitalread or write.
//
static inline void turnOffPWM(uint8_t timer) __attribute__ ((always_inline));
static inline void turnOffPWM(uint8_t timer)
{
if (timer == TIMER1A) cbi(TCCR1A, COM1A1);
if (timer == TIMER1B) cbi(TCCR1A, COM1B1);
#if defined(__AVR_ATmega8__)
if (timer == TIMER2) cbi(TCCR2, COM21);
#else
if (timer == TIMER0A) cbi(TCCR0A, COM0A1);
if (timer == TIMER0B) cbi(TCCR0A, COM0B1);
if (timer == TIMER2A) cbi(TCCR2A, COM2A1);
if (timer == TIMER2B) cbi(TCCR2A, COM2B1);
#endif
#if defined(__AVR_ATmega1280__)
if (timer == TIMER3A) cbi(TCCR3A, COM3A1);
if (timer == TIMER3B) cbi(TCCR3A, COM3B1);
if (timer == TIMER3C) cbi(TCCR3A, COM3C1);
if (timer == TIMER4A) cbi(TCCR4A, COM4A1);
if (timer == TIMER4B) cbi(TCCR4A, COM4B1);
if (timer == TIMER4C) cbi(TCCR4A, COM4C1);
if (timer == TIMER5A) cbi(TCCR5A, COM5A1);
if (timer == TIMER5B) cbi(TCCR5A, COM5B1);
if (timer == TIMER5C) cbi(TCCR5A, COM5C1);
#endif
}
void digitalWrite(uint8_t pin, uint8_t val)
{
uint8_t timer = digitalPinToTimer(pin);
uint8_t bit = digitalPinToBitMask(pin);
uint8_t port = digitalPinToPort(pin);
volatile uint8_t *out;
if (port == NOT_A_PIN) return;
// If the pin that support PWM output, we need to turn it off
// before doing a digital write.
if (timer != NOT_ON_TIMER) turnOffPWM(timer);
out = portOutputRegister(port);
if (val == LOW) *out &= ~bit;
else *out |= bit;
}
int digitalRead(uint8_t pin)
{
uint8_t timer = digitalPinToTimer(pin);
uint8_t bit = digitalPinToBitMask(pin);
uint8_t port = digitalPinToPort(pin);
if (port == NOT_A_PIN) return LOW;
// If the pin that support PWM output, we need to turn it off
// before getting a digital reading.
if (timer != NOT_ON_TIMER) turnOffPWM(timer);
if (*portInputRegister(port) & bit) return HIGH;
return LOW;
}

View File

@ -0,0 +1,68 @@
/*
wiring_private.h - Internal header file.
Part of Arduino - http://www.arduino.cc/
Copyright (c) 2005-2006 David A. Mellis
This library 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 2.1 of the License, or (at your option) any later version.
This library 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
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General
Public License along with this library; if not, write to the
Free Software Foundation, Inc., 59 Temple Place, Suite 330,
Boston, MA 02111-1307 USA
$Id: wiring.h 239 2007-01-12 17:58:39Z mellis $
*/
#ifndef WiringPrivate_h
#define WiringPrivate_h
#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/delay.h>
#include <stdio.h>
#include <stdarg.h>
#include "wiring.h"
#ifdef __cplusplus
extern "C"{
#endif
#ifndef cbi
#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit))
#endif
#ifndef sbi
#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))
#endif
#define EXTERNAL_INT_0 0
#define EXTERNAL_INT_1 1
#define EXTERNAL_INT_2 2
#define EXTERNAL_INT_3 3
#define EXTERNAL_INT_4 4
#define EXTERNAL_INT_5 5
#define EXTERNAL_INT_6 6
#define EXTERNAL_INT_7 7
#if defined(__AVR_ATmega1280__)
#define EXTERNAL_NUM_INTERRUPTS 8
#else
#define EXTERNAL_NUM_INTERRUPTS 2
#endif
typedef void (*voidFuncPtr)(void);
#ifdef __cplusplus
} // extern "C"
#endif
#endif

View File

@ -0,0 +1,66 @@
/*
wiring_pulse.c - pulseIn() function
Part of Arduino - http://www.arduino.cc/
Copyright (c) 2005-2006 David A. Mellis
This library 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 2.1 of the License, or (at your option) any later version.
This library 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
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General
Public License along with this library; if not, write to the
Free Software Foundation, Inc., 59 Temple Place, Suite 330,
Boston, MA 02111-1307 USA
$Id: wiring.c 248 2007-02-03 15:36:30Z mellis $
*/
#include "wiring_private.h"
#include "pins_arduino.h"
/* Measures the length (in microseconds) of a pulse on the pin; state is HIGH
* or LOW, the type of pulse to measure. Works on pulses from 2-3 microseconds
* to 3 minutes in length, but must be called at least a few dozen microseconds
* before the start of the pulse. */
unsigned long pulseIn(uint8_t pin, uint8_t state, unsigned long timeout)
{
// cache the port and bit of the pin in order to speed up the
// pulse width measuring loop and achieve finer resolution. calling
// digitalRead() instead yields much coarser resolution.
uint8_t bit = digitalPinToBitMask(pin);
uint8_t port = digitalPinToPort(pin);
uint8_t stateMask = (state ? bit : 0);
unsigned long width = 0; // keep initialization out of time critical area
// convert the timeout from microseconds to a number of times through
// the initial loop; it takes 16 clock cycles per iteration.
unsigned long numloops = 0;
unsigned long maxloops = microsecondsToClockCycles(timeout) / 16;
// wait for any previous pulse to end
while ((*portInputRegister(port) & bit) == stateMask)
if (numloops++ == maxloops)
return 0;
// wait for the pulse to start
while ((*portInputRegister(port) & bit) != stateMask)
if (numloops++ == maxloops)
return 0;
// wait for the pulse to stop
while ((*portInputRegister(port) & bit) == stateMask)
width++;
// convert the reading to microseconds. The loop has been determined
// to be 10 clock cycles long and have about 16 clocks between the edge
// and the start of the loop. There will be some error introduced by
// the interrupt handlers.
return clockCyclesToMicroseconds(width * 10 + 16);
}

View File

@ -0,0 +1,40 @@
/*
wiring_shift.c - shiftOut() function
Part of Arduino - http://www.arduino.cc/
Copyright (c) 2005-2006 David A. Mellis
This library 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 2.1 of the License, or (at your option) any later version.
This library 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
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General
Public License along with this library; if not, write to the
Free Software Foundation, Inc., 59 Temple Place, Suite 330,
Boston, MA 02111-1307 USA
$Id: wiring.c 248 2007-02-03 15:36:30Z mellis $
*/
#include "wiring_private.h"
void shiftOut(uint8_t dataPin, uint8_t clockPin, uint8_t bitOrder, byte val)
{
int i;
for (i = 0; i < 8; i++) {
if (bitOrder == LSBFIRST)
digitalWrite(dataPin, !!(val & (1 << i)));
else
digitalWrite(dataPin, !!(val & (1 << (7 - i))));
digitalWrite(clockPin, HIGH);
digitalWrite(clockPin, LOW);
}
}

View File

@ -0,0 +1,119 @@
/*
pin_atmega8.c - pin definitions for the atmega8
Part of Arduino / Wiring Lite
Copyright (c) 2005 David A. Mellis
This library 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 2.1 of the License, or (at your option) any later version.
This library 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
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General
Public License along with this library; if not, write to the
Free Software Foundation, Inc., 59 Temple Place, Suite 330,
Boston, MA 02111-1307 USA
$Id$
*/
#include <avr/io.h>
#include "wiring.h"
// We map the pin numbers passed to digitalRead() or
// analogRead() directly to the corresponding pin
// numbers on the Atmega8. No distinction is made
// between analog and digital pins.
// ATMEL ATMEGA8
//
// +-\/-+
// PC6 1| |28 PC5
// PD0 2| |27 PC4
// PD1 3| |26 PC3
// PD2 4| |25 PC2
// PD3 5| |24 PC1
// PD4 6| |23 PC0
// VCC 7| |22 GND
// GND 8| |21 AREF
// PB6 9| |20 AVCC
// PB7 10| |19 PB5
// PD5 11| |18 PB4
// PD6 12| |17 PB3
// PD7 13| |16 PB2
// PB0 14| |15 PB1
// +----+
#define NUM_PINS 28
#define NUM_PORTS 4
#define PB 2
#define PC 3
#define PD 4
int port_to_mode[NUM_PORTS + 1] = {
NOT_A_PORT,
NOT_A_PORT,
_SFR_IO_ADDR(DDRB),
_SFR_IO_ADDR(DDRC),
_SFR_IO_ADDR(DDRD),
};
int port_to_output[NUM_PORTS + 1] = {
NOT_A_PORT,
NOT_A_PORT,
_SFR_IO_ADDR(PORTB),
_SFR_IO_ADDR(PORTC),
_SFR_IO_ADDR(PORTD),
};
int port_to_input[NUM_PORTS + 1] = {
NOT_A_PORT,
NOT_A_PORT,
_SFR_IO_ADDR(PINB),
_SFR_IO_ADDR(PINC),
_SFR_IO_ADDR(PIND),
};
pin_t digital_pin_to_port_array[] = {
{ NOT_A_PIN, NOT_A_PIN },
{ PC, 6 },
{ PD, 0 },
{ PD, 1 },
{ PD, 2 },
{ PD, 3 },
{ PD, 4 },
{ NOT_A_PIN, NOT_A_PIN },
{ NOT_A_PIN, NOT_A_PIN },
{ PB, 6 },
{ PB, 7 },
{ PD, 5 },
{ PD, 6 },
{ PD, 7 },
{ PB, 0 },
{ PB, 1 },
{ PB, 2 },
{ PB, 3 },
{ PB, 4 },
{ PB, 5 },
{ NOT_A_PIN, NOT_A_PIN },
{ NOT_A_PIN, NOT_A_PIN },
{ NOT_A_PIN, NOT_A_PIN },
{ PC, 0 },
{ PC, 1 },
{ PC, 2 },
{ PC, 3 },
{ PC, 4 },
{ PC, 5 },
};
pin_t *digital_pin_to_port = digital_pin_to_port_array;
pin_t *analog_in_pin_to_port = digital_pin_to_port_array;
pin_t *analog_out_pin_to_port = digital_pin_to_port_array;

View File

View File

View File

@ -0,0 +1,50 @@
/*
EEPROM.cpp - EEPROM library
Copyright (c) 2006 David A. Mellis. All right reserved.
This library 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 2.1 of the License, or (at your option) any later version.
This library 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
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
/******************************************************************************
* Includes
******************************************************************************/
#include <avr/eeprom.h>
#include "WConstants.h"
#include "EEPROM.h"
/******************************************************************************
* Definitions
******************************************************************************/
/******************************************************************************
* Constructors
******************************************************************************/
/******************************************************************************
* User API
******************************************************************************/
uint8_t EEPROMClass::read(int address)
{
return eeprom_read_byte((unsigned char *) address);
}
void EEPROMClass::write(int address, uint8_t value)
{
eeprom_write_byte((unsigned char *) address, value);
}
EEPROMClass EEPROM;

View File

@ -0,0 +1,35 @@
/*
EEPROM.h - EEPROM library
Copyright (c) 2006 David A. Mellis. All right reserved.
This library 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 2.1 of the License, or (at your option) any later version.
This library 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
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef EEPROM_h
#define EEPROM_h
#include <inttypes.h>
class EEPROMClass
{
public:
uint8_t read(int);
void write(int, uint8_t);
};
extern EEPROMClass EEPROM;
#endif

View File

@ -0,0 +1,21 @@
/*
* EEPROM Clear
*
* Sets all of the bytes of the EEPROM to 0.
*/
#include <EEPROM.h>
void setup()
{
// write a 0 to all 512 bytes of the EEPROM
for (int i = 0; i < 512; i++)
EEPROM.write(i, 0);
// turn the LED on when we're done
digitalWrite(13, HIGH);
}
void loop()
{
}

View File

@ -0,0 +1,38 @@
/*
* EEPROM Read
*
* Reads the value of each byte of the EEPROM and prints it
* to the computer.
*/
#include <EEPROM.h>
// start reading from the first byte (address 0) of the EEPROM
int address = 0;
byte value;
void setup()
{
Serial.begin(9600);
}
void loop()
{
// read a byte from the current address of the EEPROM
value = EEPROM.read(address);
Serial.print(address);
Serial.print("\t");
Serial.print(value, DEC);
Serial.println();
// advance to the next address of the EEPROM
address = address + 1;
// there are only 512 bytes of EEPROM, from 0 to 511, so if we're
// on address 512, wrap around to address 0
if (address == 512)
address = 0;
delay(500);
}

View File

@ -0,0 +1,38 @@
/*
* EEPROM Write
*
* Stores values read from analog input 0 into the EEPROM.
* These values will stay in the EEPROM when the board is
* turned off and may be retrieved later by another sketch.
*/
#include <EEPROM.h>
// the current address in the EEPROM (i.e. which byte
// we're going to write to next)
int addr = 0;
void setup()
{
}
void loop()
{
// need to divide by 4 because analog inputs range from
// 0 to 1023 and each byte of the EEPROM can only hold a
// value from 0 to 255.
int val = analogRead(0) / 4;
// write the value to the appropriate byte of the EEPROM.
// these values will remain there when the board is
// turned off.
EEPROM.write(addr, val);
// advance to the next address. there are 512 bytes in
// the EEPROM, so go back to 0 when we hit 512.
addr = addr + 1;
if (addr == 512)
addr = 0;
delay(100);
}

View File

@ -0,0 +1,18 @@
#######################################
# Syntax Coloring Map For Ultrasound
#######################################
#######################################
# Datatypes (KEYWORD1)
#######################################
EEPROM KEYWORD1
#######################################
# Methods and Functions (KEYWORD2)
#######################################
#######################################
# Constants (LITERAL1)
#######################################

View File

@ -0,0 +1,140 @@
extern "C" {
#include "types.h"
#include "w5100.h"
#include "socket.h"
#include "string.h"
}
#include "WProgram.h"
#include "Ethernet.h"
#include "Client.h"
#include "Server.h"
uint16_t Client::_srcport = 0;
Client::Client(uint8_t sock) {
_sock = sock;
}
Client::Client(uint8_t *ip, uint16_t port) {
_ip = ip;
_port = port;
_sock = 255;
}
uint8_t Client::connect() {
if (_sock != 255)
return 0;
for (int i = 0; i < MAX_SOCK_NUM; i++) {
uint8_t s = getSn_SR(i);
if (s == SOCK_CLOSED || s == SOCK_FIN_WAIT) {
_sock = i;
break;
}
}
if (_sock == 255)
return 0;
_srcport++;
if (_srcport + 1024 == 0) _srcport = 0;
socket(_sock, Sn_MR_TCP, _srcport + 1024, 0);
if (!::connect(_sock, _ip, _port)) {
_sock = 255;
return 0;
}
while (status() != SOCK_ESTABLISHED) {
delay(1);
if (status() == SOCK_CLOSED) {
_sock = 255;
return 0;
}
}
return 1;
}
void Client::write(uint8_t b) {
if (_sock != 255)
send(_sock, &b, 1);
}
void Client::write(const char *str) {
if (_sock != 255)
send(_sock, (const uint8_t *)str, strlen(str));
}
void Client::write(const uint8_t *buf, size_t size) {
if (_sock != 255)
send(_sock, buf, size);
}
int Client::available() {
if (_sock != 255)
return getSn_RX_RSR(_sock);
return 0;
}
int Client::read() {
uint8_t b;
if (!available())
return -1;
recv(_sock, &b, 1);
return b;
}
void Client::flush() {
while (available())
read();
}
void Client::stop() {
if (_sock == 255)
return;
// attempt to close the connection gracefully (send a FIN to other side)
disconnect(_sock);
unsigned long start = millis();
// wait a second for the connection to close
while (status() != SOCK_CLOSED && millis() - start < 1000)
delay(1);
// if it hasn't closed, close it forcefully
if (status() != SOCK_CLOSED)
close(_sock);
EthernetClass::_server_port[_sock] = 0;
_sock = 255;
}
uint8_t Client::connected() {
uint8_t s = status();
return !(s == SOCK_LISTEN || s == SOCK_CLOSED || s == SOCK_FIN_WAIT ||
(s == SOCK_CLOSE_WAIT && !available()));
}
uint8_t Client::status() {
return getSn_SR(_sock);
}
// the next three functions are a hack so we can compare the client returned
// by Server::available() to null, or use it as the condition in an
// if-statement. this lets us stay compatible with the Processing network
// library.
uint8_t Client::operator==(int p) {
return _sock == 255;
}
uint8_t Client::operator!=(int p) {
return _sock != 255;
}
Client::operator bool() {
return _sock != 255;
}

View File

@ -0,0 +1,31 @@
#ifndef Client_h
#define Client_h
#include "Print.h"
class Client : public Print {
private:
static uint16_t _srcport;
uint8_t _sock;
uint8_t *_ip;
uint16_t _port;
public:
Client(uint8_t);
Client(uint8_t *, uint16_t);
uint8_t status();
uint8_t connect();
virtual void write(uint8_t);
virtual void write(const char *str);
virtual void write(const uint8_t *buf, size_t size);
int available();
int read();
void flush();
void stop();
uint8_t connected();
uint8_t operator==(int);
uint8_t operator!=(int);
operator bool();
friend class Server;
};
#endif

View File

@ -0,0 +1,38 @@
extern "C" {
#include "types.h"
#include "w5100.h"
}
#include "Ethernet.h"
// XXX: don't make assumptions about the value of MAX_SOCK_NUM.
uint8_t EthernetClass::_state[MAX_SOCK_NUM] = { 0, 0, 0, 0 };
uint16_t EthernetClass::_server_port[MAX_SOCK_NUM] = { 0, 0, 0, 0 };
void EthernetClass::begin(uint8_t *mac, uint8_t *ip)
{
uint8_t gateway[4];
gateway[0] = ip[0];
gateway[1] = ip[1];
gateway[2] = ip[2];
gateway[3] = 1;
begin(mac, ip, gateway);
}
void EthernetClass::begin(uint8_t *mac, uint8_t *ip, uint8_t *gateway)
{
uint8_t subnet[] = { 255, 255, 255, 0 };
begin(mac, ip, gateway, subnet);
}
void EthernetClass::begin(uint8_t *mac, uint8_t *ip, uint8_t *gateway, uint8_t *subnet)
{
iinchip_init();
sysinit(0x55, 0x55);
setSHAR(mac);
setSIPR(ip);
setGAR(gateway);
setSUBR(subnet);
}
EthernetClass Ethernet;

View File

@ -0,0 +1,22 @@
#ifndef Ethernet_h
#define Ethernet_h
#include <inttypes.h>
#include "Client.h"
#include "Server.h"
class EthernetClass {
private:
public:
static uint8_t _state[MAX_SOCK_NUM];
static uint16_t _server_port[MAX_SOCK_NUM];
void begin(uint8_t *, uint8_t *);
void begin(uint8_t *, uint8_t *, uint8_t *);
void begin(uint8_t *, uint8_t *, uint8_t *, uint8_t *);
friend class Client;
friend class Server;
};
extern EthernetClass Ethernet;
#endif

View File

@ -0,0 +1,91 @@
extern "C" {
#include "types.h"
#include "w5100.h"
#include "socket.h"
#include "string.h"
}
#include "Ethernet.h"
#include "Client.h"
#include "Server.h"
Server::Server(uint16_t port)
{
_port = port;
}
void Server::begin()
{
for (int sock = 0; sock < MAX_SOCK_NUM; sock++) {
Client client(sock);
if (client.status() == SOCK_CLOSED) {
socket(sock, Sn_MR_TCP, _port, 0);
listen(sock);
EthernetClass::_server_port[sock] = _port;
break;
}
}
}
void Server::accept()
{
int listening = 0;
for (int sock = 0; sock < MAX_SOCK_NUM; sock++) {
Client client(sock);
if (EthernetClass::_server_port[sock] == _port) {
if (client.status() == SOCK_LISTEN) {
listening = 1;
} else if (client.status() == SOCK_CLOSE_WAIT && !client.available()) {
client.stop();
}
}
}
if (!listening) {
begin();
}
}
Client Server::available()
{
accept();
for (int sock = 0; sock < MAX_SOCK_NUM; sock++) {
Client client(sock);
if (EthernetClass::_server_port[sock] == _port &&
client.status() == SOCK_ESTABLISHED) {
if (client.available()) {
// XXX: don't always pick the lowest numbered socket.
return client;
}
}
}
return Client(255);
}
void Server::write(uint8_t b)
{
write(&b, 1);
}
void Server::write(const char *str)
{
write((const uint8_t *)str, strlen(str));
}
void Server::write(const uint8_t *buffer, size_t size)
{
accept();
for (int sock = 0; sock < MAX_SOCK_NUM; sock++) {
Client client(sock);
if (EthernetClass::_server_port[sock] == _port &&
client.status() == SOCK_ESTABLISHED) {
client.write(buffer, size);
}
}
}

View File

@ -0,0 +1,25 @@
#ifndef Server_h
#define Server_h
extern "C" {
#include "utility/types.h"
}
#include "Print.h"
class Client;
class Server : public Print {
private:
uint16_t _port;
void accept();
public:
Server(uint16_t);
Client available();
void begin();
virtual void write(uint8_t);
virtual void write(const char *str);
virtual void write(const uint8_t *buf, size_t size);
};
#endif

View File

@ -0,0 +1,34 @@
/*
* Chat Server
*
* A simple server that distributes any incoming messages to all
* connected clients. To use telnet to 10.0.0.177 and type!
*/
#include <Ethernet.h>
// network configuration. gateway and subnet are optional.
byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
byte ip[] = { 10, 0, 0, 177 };
byte gateway[] = { 10, 0, 0, 1 };
byte subnet[] = { 255, 255, 0, 0 };
// telnet defaults to port 23
Server server(23);
void setup()
{
// initialize the ethernet device
Ethernet.begin(mac, ip, gateway, subnet);
// start listening for clients
server.begin();
}
void loop()
{
Client client = server.available();
if (client) {
server.write(client.read());
}
}

View File

@ -0,0 +1,41 @@
#include <Ethernet.h>
byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
byte ip[] = { 10, 0, 0, 177 };
byte server[] = { 64, 233, 187, 99 }; // Google
Client client(server, 80);
void setup()
{
Ethernet.begin(mac, ip);
Serial.begin(9600);
delay(1000);
Serial.println("connecting...");
if (client.connect()) {
Serial.println("connected");
client.println("GET /search?q=arduino HTTP/1.0");
client.println();
} else {
Serial.println("connection failed");
}
}
void loop()
{
if (client.available()) {
char c = client.read();
Serial.print(c);
}
if (!client.connected()) {
Serial.println();
Serial.println("disconnecting.");
client.stop();
for(;;)
;
}
}

Some files were not shown because too many files have changed in this diff Show More