Merge branch 'new-extension' of git@github.com:arduino/Arduino
|
@ -545,7 +545,7 @@ public class Base {
|
||||||
newbieDir.mkdirs();
|
newbieDir.mkdirs();
|
||||||
|
|
||||||
// Make an empty pde file
|
// Make an empty pde file
|
||||||
File newbieFile = new File(newbieDir, newbieName + ".pde");
|
File newbieFile = new File(newbieDir, newbieName + ".ino");
|
||||||
new FileOutputStream(newbieFile); // create the file
|
new FileOutputStream(newbieFile); // create the file
|
||||||
return newbieFile.getAbsolutePath();
|
return newbieFile.getAbsolutePath();
|
||||||
}
|
}
|
||||||
|
@ -637,7 +637,8 @@ public class Base {
|
||||||
public boolean accept(File dir, String name) {
|
public boolean accept(File dir, String name) {
|
||||||
// TODO this doesn't seem to ever be used. AWESOME.
|
// TODO this doesn't seem to ever be used. AWESOME.
|
||||||
//System.out.println("check filter on " + dir + " " + name);
|
//System.out.println("check filter on " + dir + " " + name);
|
||||||
return name.toLowerCase().endsWith(".pde");
|
return name.toLowerCase().endsWith(".ino")
|
||||||
|
|| name.toLowerCase().endsWith(".pde");
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -1016,22 +1017,28 @@ public class Base {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public void rebuildBurnBootloaderMenu(JMenu menu) {
|
public void rebuildProgrammerMenu(JMenu menu) {
|
||||||
//System.out.println("rebuilding burn bootloader menu");
|
//System.out.println("rebuilding programmer menu");
|
||||||
menu.removeAll();
|
menu.removeAll();
|
||||||
|
ButtonGroup group = new ButtonGroup();
|
||||||
for (Target target : targetsTable.values()) {
|
for (Target target : targetsTable.values()) {
|
||||||
for (String programmer : target.getProgrammers().keySet()) {
|
for (String programmer : target.getProgrammers().keySet()) {
|
||||||
AbstractAction action =
|
AbstractAction action =
|
||||||
new AbstractAction(
|
new AbstractAction(
|
||||||
"w/ " + target.getProgrammers().get(programmer).get("name")) {
|
target.getProgrammers().get(programmer).get("name")) {
|
||||||
public void actionPerformed(ActionEvent actionevent) {
|
public void actionPerformed(ActionEvent actionevent) {
|
||||||
activeEditor.handleBurnBootloader((String) getValue("target"),
|
Preferences.set("programmer", getValue("target") + ":" +
|
||||||
(String) getValue("programmer"));
|
getValue("programmer"));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
action.putValue("target", target.getName());
|
action.putValue("target", target.getName());
|
||||||
action.putValue("programmer", programmer);
|
action.putValue("programmer", programmer);
|
||||||
JMenuItem item = new JMenuItem(action);
|
JMenuItem item = new JRadioButtonMenuItem(action);
|
||||||
|
if (Preferences.get("programmer").equals(target.getName() + ":" +
|
||||||
|
programmer)) {
|
||||||
|
item.setSelected(true);
|
||||||
|
}
|
||||||
|
group.add(item);
|
||||||
menu.add(item);
|
menu.add(item);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1091,7 +1098,10 @@ public class Base {
|
||||||
File subfolder = new File(folder, list[i]);
|
File subfolder = new File(folder, list[i]);
|
||||||
if (!subfolder.isDirectory()) continue;
|
if (!subfolder.isDirectory()) continue;
|
||||||
|
|
||||||
File entry = new File(subfolder, list[i] + ".pde");
|
File entry = new File(subfolder, list[i] + ".ino");
|
||||||
|
if (!entry.exists() && (new File(subfolder, list[i] + ".pde")).exists()) {
|
||||||
|
entry = new File(subfolder, list[i] + ".pde");
|
||||||
|
}
|
||||||
// if a .pde file of the same prefix as the folder exists..
|
// if a .pde file of the same prefix as the folder exists..
|
||||||
if (entry.exists()) {
|
if (entry.exists()) {
|
||||||
//String sanityCheck = sanitizedName(list[i]);
|
//String sanityCheck = sanitizedName(list[i]);
|
||||||
|
|
|
@ -538,7 +538,7 @@ public class Editor extends JFrame implements RunnerListener {
|
||||||
});
|
});
|
||||||
fileMenu.add(saveAsMenuItem);
|
fileMenu.add(saveAsMenuItem);
|
||||||
|
|
||||||
item = newJMenuItem("Upload to I/O Board", 'U');
|
item = newJMenuItem("Upload", 'U');
|
||||||
item.addActionListener(new ActionListener() {
|
item.addActionListener(new ActionListener() {
|
||||||
public void actionPerformed(ActionEvent e) {
|
public void actionPerformed(ActionEvent e) {
|
||||||
handleExport(false);
|
handleExport(false);
|
||||||
|
@ -546,13 +546,13 @@ public class Editor extends JFrame implements RunnerListener {
|
||||||
});
|
});
|
||||||
fileMenu.add(item);
|
fileMenu.add(item);
|
||||||
|
|
||||||
// item = newJMenuItemShift("Upload to I/O Board (verbose)", 'U');
|
item = newJMenuItemShift("Upload Using Programmer", 'U');
|
||||||
// item.addActionListener(new ActionListener() {
|
item.addActionListener(new ActionListener() {
|
||||||
// public void actionPerformed(ActionEvent e) {
|
public void actionPerformed(ActionEvent e) {
|
||||||
// handleExport(true);
|
handleExport(true);
|
||||||
// }
|
}
|
||||||
// });
|
});
|
||||||
// fileMenu.add(item);
|
fileMenu.add(item);
|
||||||
|
|
||||||
fileMenu.addSeparator();
|
fileMenu.addSeparator();
|
||||||
|
|
||||||
|
@ -618,13 +618,13 @@ public class Editor extends JFrame implements RunnerListener {
|
||||||
// });
|
// });
|
||||||
// sketchMenu.add(item);
|
// sketchMenu.add(item);
|
||||||
|
|
||||||
item = new JMenuItem("Stop");
|
// item = new JMenuItem("Stop");
|
||||||
item.addActionListener(new ActionListener() {
|
// item.addActionListener(new ActionListener() {
|
||||||
public void actionPerformed(ActionEvent e) {
|
// public void actionPerformed(ActionEvent e) {
|
||||||
handleStop();
|
// handleStop();
|
||||||
}
|
// }
|
||||||
});
|
// });
|
||||||
sketchMenu.add(item);
|
// sketchMenu.add(item);
|
||||||
|
|
||||||
sketchMenu.addSeparator();
|
sketchMenu.addSeparator();
|
||||||
|
|
||||||
|
@ -696,9 +696,17 @@ public class Editor extends JFrame implements RunnerListener {
|
||||||
|
|
||||||
menu.addSeparator();
|
menu.addSeparator();
|
||||||
|
|
||||||
JMenu bootloaderMenu = new JMenu("Burn Bootloader");
|
JMenu programmerMenu = new JMenu("Programmer");
|
||||||
base.rebuildBurnBootloaderMenu(bootloaderMenu);
|
base.rebuildProgrammerMenu(programmerMenu);
|
||||||
menu.add(bootloaderMenu);
|
menu.add(programmerMenu);
|
||||||
|
|
||||||
|
item = new JMenuItem("Burn Bootloader");
|
||||||
|
item.addActionListener(new ActionListener() {
|
||||||
|
public void actionPerformed(ActionEvent e) {
|
||||||
|
handleBurnBootloader();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
menu.add(item);
|
||||||
|
|
||||||
menu.addMenuListener(new MenuListener() {
|
menu.addMenuListener(new MenuListener() {
|
||||||
public void menuCanceled(MenuEvent e) {}
|
public void menuCanceled(MenuEvent e) {}
|
||||||
|
@ -1887,12 +1895,12 @@ public class Editor extends JFrame implements RunnerListener {
|
||||||
* Implements Sketch → Stop, or pressing Stop on the toolbar.
|
* Implements Sketch → Stop, or pressing Stop on the toolbar.
|
||||||
*/
|
*/
|
||||||
public void handleStop() { // called by menu or buttons
|
public void handleStop() { // called by menu or buttons
|
||||||
toolbar.activate(EditorToolbar.STOP);
|
// toolbar.activate(EditorToolbar.STOP);
|
||||||
|
|
||||||
internalCloseRunner();
|
internalCloseRunner();
|
||||||
|
|
||||||
toolbar.deactivate(EditorToolbar.RUN);
|
toolbar.deactivate(EditorToolbar.RUN);
|
||||||
toolbar.deactivate(EditorToolbar.STOP);
|
// toolbar.deactivate(EditorToolbar.STOP);
|
||||||
|
|
||||||
// focus the PDE again after quitting presentation mode [toxi 030903]
|
// focus the PDE again after quitting presentation mode [toxi 030903]
|
||||||
toFront();
|
toFront();
|
||||||
|
@ -2032,12 +2040,63 @@ public class Editor extends JFrame implements RunnerListener {
|
||||||
* modifications (if any) to the previous sketch need to be saved.
|
* modifications (if any) to the previous sketch need to be saved.
|
||||||
*/
|
*/
|
||||||
protected boolean handleOpenInternal(String path) {
|
protected boolean handleOpenInternal(String path) {
|
||||||
|
// rename .pde files to .ino
|
||||||
|
File[] oldFiles = (new File(path)).getParentFile().listFiles(new FilenameFilter() {
|
||||||
|
public boolean accept(File dir, String name) {
|
||||||
|
return (name.toLowerCase().endsWith(".pde"));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
if (oldFiles != null && oldFiles.length > 0) {
|
||||||
|
if (!Preferences.getBoolean("editor.update_extension")) {
|
||||||
|
Object[] options = { "OK", "Cancel" };
|
||||||
|
String prompt =
|
||||||
|
"In Arduino 1.0, the file extension for sketches changed\n" +
|
||||||
|
"from \".pde\" to \".ino\". This version of the software only\n" +
|
||||||
|
"supports the new extension. Rename the files in this sketch\n" +
|
||||||
|
"(and future sketches) and continue?";
|
||||||
|
|
||||||
|
int result = JOptionPane.showOptionDialog(this,
|
||||||
|
prompt,
|
||||||
|
"New extension",
|
||||||
|
JOptionPane.YES_NO_OPTION,
|
||||||
|
JOptionPane.QUESTION_MESSAGE,
|
||||||
|
null,
|
||||||
|
options,
|
||||||
|
options[0]);
|
||||||
|
if (result != JOptionPane.YES_OPTION) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
Preferences.setBoolean("editor.update_extension", true);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < oldFiles.length; i++) {
|
||||||
|
String oldPath = oldFiles[i].getPath();
|
||||||
|
File newFile = new File(oldPath.substring(0, oldPath.length() - 4) + ".ino");
|
||||||
|
try {
|
||||||
|
Base.copyFile(oldFiles[i], newFile);
|
||||||
|
} catch (IOException e) {
|
||||||
|
Base.showWarning("Error", "Could not copy to a proper location.", e);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// remove the original file, so user doesn't get confused
|
||||||
|
oldFiles[i].delete();
|
||||||
|
|
||||||
|
// update with the new path
|
||||||
|
if (oldFiles[i].compareTo(new File(path)) == 0) {
|
||||||
|
path = newFile.getAbsolutePath();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// check to make sure that this .pde file is
|
// check to make sure that this .pde file is
|
||||||
// in a folder of the same name
|
// in a folder of the same name
|
||||||
File file = new File(path);
|
File file = new File(path);
|
||||||
File parentFile = new File(file.getParent());
|
File parentFile = new File(file.getParent());
|
||||||
String parentName = parentFile.getName();
|
String parentName = parentFile.getName();
|
||||||
String pdeName = parentName + ".pde";
|
String pdeName = parentName + ".ino";
|
||||||
File altFile = new File(file.getParent(), pdeName);
|
File altFile = new File(file.getParent(), pdeName);
|
||||||
|
|
||||||
if (pdeName.equals(file.getName())) {
|
if (pdeName.equals(file.getName())) {
|
||||||
|
@ -2049,10 +2108,10 @@ public class Editor extends JFrame implements RunnerListener {
|
||||||
path = altFile.getAbsolutePath();
|
path = altFile.getAbsolutePath();
|
||||||
//System.out.println("found alt file in same folder");
|
//System.out.println("found alt file in same folder");
|
||||||
|
|
||||||
} else if (!path.endsWith(".pde")) {
|
} else if (!path.endsWith(".ino")) {
|
||||||
Base.showWarning("Bad file selected",
|
Base.showWarning("Bad file selected",
|
||||||
"Processing can only open its own sketches\n" +
|
"Processing can only open its own sketches\n" +
|
||||||
"and other files ending in .pde", null);
|
"and other files ending in .ino", null);
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
@ -2271,13 +2330,13 @@ public class Editor extends JFrame implements RunnerListener {
|
||||||
* Made synchronized to (hopefully) avoid problems of people
|
* Made synchronized to (hopefully) avoid problems of people
|
||||||
* hitting export twice, quickly, and horking things up.
|
* hitting export twice, quickly, and horking things up.
|
||||||
*/
|
*/
|
||||||
synchronized public void handleExport(final boolean verbose) {
|
synchronized public void handleExport(final boolean usingProgrammer) {
|
||||||
//if (!handleExportCheckModified()) return;
|
//if (!handleExportCheckModified()) return;
|
||||||
toolbar.activate(EditorToolbar.EXPORT);
|
toolbar.activate(EditorToolbar.EXPORT);
|
||||||
console.clear();
|
console.clear();
|
||||||
statusNotice("Uploading to I/O Board...");
|
statusNotice("Uploading to I/O Board...");
|
||||||
|
|
||||||
new Thread(verbose ? exportAppHandler : exportHandler).start();
|
new Thread(usingProgrammer ? exportAppHandler : exportHandler).start();
|
||||||
}
|
}
|
||||||
|
|
||||||
// DAM: in Arduino, this is upload
|
// DAM: in Arduino, this is upload
|
||||||
|
@ -2395,14 +2454,14 @@ public class Editor extends JFrame implements RunnerListener {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
protected void handleBurnBootloader(final String target, final String programmer) {
|
protected void handleBurnBootloader() {
|
||||||
console.clear();
|
console.clear();
|
||||||
statusNotice("Burning bootloader to I/O Board (this may take a minute)...");
|
statusNotice("Burning bootloader to I/O Board (this may take a minute)...");
|
||||||
SwingUtilities.invokeLater(new Runnable() {
|
SwingUtilities.invokeLater(new Runnable() {
|
||||||
public void run() {
|
public void run() {
|
||||||
try {
|
try {
|
||||||
Uploader uploader = new AvrdudeUploader();
|
Uploader uploader = new AvrdudeUploader();
|
||||||
if (uploader.burnBootloader(target, programmer)) {
|
if (uploader.burnBootloader()) {
|
||||||
statusNotice("Done burning bootloader.");
|
statusNotice("Done burning bootloader.");
|
||||||
} else {
|
} else {
|
||||||
statusError("Error while burning bootloader.");
|
statusError("Error while burning bootloader.");
|
||||||
|
|
|
@ -37,12 +37,12 @@ public class EditorToolbar extends JComponent implements MouseInputListener, Key
|
||||||
|
|
||||||
/** Rollover titles for each button. */
|
/** Rollover titles for each button. */
|
||||||
static final String title[] = {
|
static final String title[] = {
|
||||||
"Verify", "Stop", "New", "Open", "Save", "Upload", "Serial Monitor"
|
"Verify", "Upload", "New", "Open", "Save", "Serial Monitor"
|
||||||
};
|
};
|
||||||
|
|
||||||
/** Titles for each button when the shift key is pressed. */
|
/** Titles for each button when the shift key is pressed. */
|
||||||
static final String titleShift[] = {
|
static final String titleShift[] = {
|
||||||
"Verify (w/ Verbose Output)", "Stop", "New Editor Window", "Open in Another Window", "Save", "Upload (w/ Verbose Output)", "Serial Monitor"
|
"Verify", "Upload Using Programmer", "New Editor Window", "Open in Another Window", "Save", "Serial Monitor"
|
||||||
};
|
};
|
||||||
|
|
||||||
static final int BUTTON_COUNT = title.length;
|
static final int BUTTON_COUNT = title.length;
|
||||||
|
@ -57,14 +57,13 @@ public class EditorToolbar extends JComponent implements MouseInputListener, Key
|
||||||
|
|
||||||
|
|
||||||
static final int RUN = 0;
|
static final int RUN = 0;
|
||||||
static final int STOP = 1;
|
static final int EXPORT = 1;
|
||||||
|
|
||||||
static final int NEW = 2;
|
static final int NEW = 2;
|
||||||
static final int OPEN = 3;
|
static final int OPEN = 3;
|
||||||
static final int SAVE = 4;
|
static final int SAVE = 4;
|
||||||
static final int EXPORT = 5;
|
|
||||||
|
|
||||||
static final int SERIAL = 6;
|
static final int SERIAL = 5;
|
||||||
|
|
||||||
static final int INACTIVE = 0;
|
static final int INACTIVE = 0;
|
||||||
static final int ROLLOVER = 1;
|
static final int ROLLOVER = 1;
|
||||||
|
@ -105,11 +104,10 @@ public class EditorToolbar extends JComponent implements MouseInputListener, Key
|
||||||
|
|
||||||
//which[buttonCount++] = NOTHING;
|
//which[buttonCount++] = NOTHING;
|
||||||
which[buttonCount++] = RUN;
|
which[buttonCount++] = RUN;
|
||||||
which[buttonCount++] = STOP;
|
which[buttonCount++] = EXPORT;
|
||||||
which[buttonCount++] = NEW;
|
which[buttonCount++] = NEW;
|
||||||
which[buttonCount++] = OPEN;
|
which[buttonCount++] = OPEN;
|
||||||
which[buttonCount++] = SAVE;
|
which[buttonCount++] = SAVE;
|
||||||
which[buttonCount++] = EXPORT;
|
|
||||||
which[buttonCount++] = SERIAL;
|
which[buttonCount++] = SERIAL;
|
||||||
|
|
||||||
currentRollover = -1;
|
currentRollover = -1;
|
||||||
|
@ -312,13 +310,13 @@ public class EditorToolbar extends JComponent implements MouseInputListener, Key
|
||||||
|
|
||||||
switch (sel) {
|
switch (sel) {
|
||||||
case RUN:
|
case RUN:
|
||||||
editor.handleRun(e.isShiftDown());
|
editor.handleRun(false);
|
||||||
break;
|
|
||||||
|
|
||||||
case STOP:
|
|
||||||
editor.handleStop();
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
// case STOP:
|
||||||
|
// editor.handleStop();
|
||||||
|
// break;
|
||||||
|
//
|
||||||
case OPEN:
|
case OPEN:
|
||||||
popup = menu.getPopupMenu();
|
popup = menu.getPopupMenu();
|
||||||
popup.show(EditorToolbar.this, x, y);
|
popup.show(EditorToolbar.this, x, y);
|
||||||
|
|
|
@ -113,6 +113,8 @@ public class Preferences {
|
||||||
|
|
||||||
JTextField sketchbookLocationField;
|
JTextField sketchbookLocationField;
|
||||||
JCheckBox exportSeparateBox;
|
JCheckBox exportSeparateBox;
|
||||||
|
JCheckBox verboseCompilationBox;
|
||||||
|
JCheckBox verboseUploadBox;
|
||||||
JCheckBox deletePreviousBox;
|
JCheckBox deletePreviousBox;
|
||||||
JCheckBox externalEditorBox;
|
JCheckBox externalEditorBox;
|
||||||
JCheckBox memoryOverrideBox;
|
JCheckBox memoryOverrideBox;
|
||||||
|
@ -279,6 +281,21 @@ public class Preferences {
|
||||||
top += d.height + GUI_BETWEEN;
|
top += d.height + GUI_BETWEEN;
|
||||||
|
|
||||||
|
|
||||||
|
// Show verbose output during: [ ] compilation [ ] upload
|
||||||
|
|
||||||
|
box = Box.createHorizontalBox();
|
||||||
|
label = new JLabel("Show verbose output during: ");
|
||||||
|
box.add(label);
|
||||||
|
verboseCompilationBox = new JCheckBox("compilation ");
|
||||||
|
box.add(verboseCompilationBox);
|
||||||
|
verboseUploadBox = new JCheckBox("upload");
|
||||||
|
box.add(verboseUploadBox);
|
||||||
|
pain.add(box);
|
||||||
|
d = box.getPreferredSize();
|
||||||
|
box.setBounds(left, top, d.width, d.height);
|
||||||
|
top += d.height + GUI_BETWEEN;
|
||||||
|
|
||||||
|
|
||||||
// [ ] Delete previous applet or application folder on export
|
// [ ] Delete previous applet or application folder on export
|
||||||
|
|
||||||
deletePreviousBox =
|
deletePreviousBox =
|
||||||
|
@ -461,6 +478,8 @@ public class Preferences {
|
||||||
*/
|
*/
|
||||||
protected void applyFrame() {
|
protected void applyFrame() {
|
||||||
// put each of the settings into the table
|
// put each of the settings into the table
|
||||||
|
setBoolean("build.verbose", verboseCompilationBox.isSelected());
|
||||||
|
setBoolean("upload.verbose", verboseUploadBox.isSelected());
|
||||||
setBoolean("export.delete_target_folder",
|
setBoolean("export.delete_target_folder",
|
||||||
deletePreviousBox.isSelected());
|
deletePreviousBox.isSelected());
|
||||||
|
|
||||||
|
@ -516,6 +535,8 @@ public class Preferences {
|
||||||
this.editor = editor;
|
this.editor = editor;
|
||||||
|
|
||||||
// set all settings entry boxes to their actual status
|
// set all settings entry boxes to their actual status
|
||||||
|
verboseCompilationBox.setSelected(getBoolean("build.verbose"));
|
||||||
|
verboseUploadBox.setSelected(getBoolean("upload.verbose"));
|
||||||
deletePreviousBox.
|
deletePreviousBox.
|
||||||
setSelected(getBoolean("export.delete_target_folder"));
|
setSelected(getBoolean("export.delete_target_folder"));
|
||||||
|
|
||||||
|
|
|
@ -315,7 +315,7 @@ public class Sketch {
|
||||||
renamingCode = true;
|
renamingCode = true;
|
||||||
String prompt = (currentIndex == 0) ?
|
String prompt = (currentIndex == 0) ?
|
||||||
"New name for sketch:" : "New name for file:";
|
"New name for sketch:" : "New name for file:";
|
||||||
String oldName = (current.isExtension("pde")) ?
|
String oldName = (current.isExtension("ino")) ?
|
||||||
current.getPrettyName() : current.getFileName();
|
current.getPrettyName() : current.getFileName();
|
||||||
editor.status.edit(prompt, oldName);
|
editor.status.edit(prompt, oldName);
|
||||||
}
|
}
|
||||||
|
@ -495,7 +495,7 @@ public class Sketch {
|
||||||
}
|
}
|
||||||
// if successful, set base properties for the sketch
|
// if successful, set base properties for the sketch
|
||||||
|
|
||||||
File newMainFile = new File(newFolder, newName + ".pde");
|
File newMainFile = new File(newFolder, newName + ".ino");
|
||||||
String newMainFilePath = newMainFile.getAbsolutePath();
|
String newMainFilePath = newMainFile.getAbsolutePath();
|
||||||
|
|
||||||
// having saved everything and renamed the folder and the main .pde,
|
// having saved everything and renamed the folder and the main .pde,
|
||||||
|
@ -860,7 +860,7 @@ public class Sketch {
|
||||||
}
|
}
|
||||||
|
|
||||||
// save the main tab with its new name
|
// save the main tab with its new name
|
||||||
File newFile = new File(newFolder, newName + ".pde");
|
File newFile = new File(newFolder, newName + ".ino");
|
||||||
code[0].saveAs(newFile);
|
code[0].saveAs(newFile);
|
||||||
|
|
||||||
editor.handleOpenUnchecked(newFile.getPath(),
|
editor.handleOpenUnchecked(newFile.getPath(),
|
||||||
|
@ -1261,7 +1261,7 @@ public class Sketch {
|
||||||
StringBuffer bigCode = new StringBuffer();
|
StringBuffer bigCode = new StringBuffer();
|
||||||
int bigCount = 0;
|
int bigCount = 0;
|
||||||
for (SketchCode sc : code) {
|
for (SketchCode sc : code) {
|
||||||
if (sc.isExtension("pde")) {
|
if (sc.isExtension("ino")) {
|
||||||
sc.setPreprocOffset(bigCount);
|
sc.setPreprocOffset(bigCount);
|
||||||
bigCode.append(sc.getProgram());
|
bigCode.append(sc.getProgram());
|
||||||
bigCode.append('\n');
|
bigCode.append('\n');
|
||||||
|
@ -1357,7 +1357,7 @@ public class Sketch {
|
||||||
}
|
}
|
||||||
// sc.setPreprocName(filename);
|
// sc.setPreprocName(filename);
|
||||||
|
|
||||||
} else if (sc.isExtension("pde")) {
|
} else if (sc.isExtension("ino")) {
|
||||||
// The compiler and runner will need this to have a proper offset
|
// The compiler and runner will need this to have a proper offset
|
||||||
sc.addPreprocOffset(headerOffset);
|
sc.addPreprocOffset(headerOffset);
|
||||||
}
|
}
|
||||||
|
@ -1386,7 +1386,7 @@ public class Sketch {
|
||||||
// SketchCode errorCode = null;
|
// SketchCode errorCode = null;
|
||||||
// if (filename.equals(appletJavaFile)) {
|
// if (filename.equals(appletJavaFile)) {
|
||||||
// for (SketchCode code : getCode()) {
|
// for (SketchCode code : getCode()) {
|
||||||
// if (code.isExtension("pde")) {
|
// if (code.isExtension("ino")) {
|
||||||
// if (line >= code.getPreprocOffset()) {
|
// if (line >= code.getPreprocOffset()) {
|
||||||
// errorCode = code;
|
// errorCode = code;
|
||||||
// }
|
// }
|
||||||
|
@ -1520,15 +1520,15 @@ public class Sketch {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
protected boolean exportApplet(boolean verbose) throws Exception {
|
protected boolean exportApplet(boolean usingProgrammer) throws Exception {
|
||||||
return exportApplet(tempBuildFolder.getAbsolutePath(), verbose);
|
return exportApplet(tempBuildFolder.getAbsolutePath(), usingProgrammer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handle export to applet.
|
* Handle export to applet.
|
||||||
*/
|
*/
|
||||||
public boolean exportApplet(String appletPath, boolean verbose)
|
public boolean exportApplet(String appletPath, boolean usingProgrammer)
|
||||||
throws RunnerException, IOException, SerialException {
|
throws RunnerException, IOException, SerialException {
|
||||||
|
|
||||||
// Make sure the user didn't hide the sketch folder
|
// Make sure the user didn't hide the sketch folder
|
||||||
|
@ -1565,7 +1565,7 @@ public class Sketch {
|
||||||
// return false;
|
// return false;
|
||||||
// }
|
// }
|
||||||
|
|
||||||
upload(appletFolder.getPath(), foundName, verbose);
|
upload(appletFolder.getPath(), foundName, usingProgrammer);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -1592,7 +1592,7 @@ public class Sketch {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
protected String upload(String buildPath, String suggestedClassName, boolean verbose)
|
protected String upload(String buildPath, String suggestedClassName, boolean usingProgrammer)
|
||||||
throws RunnerException, SerialException {
|
throws RunnerException, SerialException {
|
||||||
|
|
||||||
Uploader uploader;
|
Uploader uploader;
|
||||||
|
@ -1602,7 +1602,7 @@ public class Sketch {
|
||||||
uploader = new AvrdudeUploader();
|
uploader = new AvrdudeUploader();
|
||||||
boolean success = uploader.uploadUsingPreferences(buildPath,
|
boolean success = uploader.uploadUsingPreferences(buildPath,
|
||||||
suggestedClassName,
|
suggestedClassName,
|
||||||
verbose);
|
usingProgrammer);
|
||||||
|
|
||||||
return success ? suggestedClassName : null;
|
return success ? suggestedClassName : null;
|
||||||
}
|
}
|
||||||
|
@ -1791,7 +1791,7 @@ public class Sketch {
|
||||||
* Returns the default extension for this editor setup.
|
* Returns the default extension for this editor setup.
|
||||||
*/
|
*/
|
||||||
public String getDefaultExtension() {
|
public String getDefaultExtension() {
|
||||||
return "pde";
|
return "ino";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1799,7 +1799,7 @@ public class Sketch {
|
||||||
* Returns a String[] array of proper extensions.
|
* Returns a String[] array of proper extensions.
|
||||||
*/
|
*/
|
||||||
public String[] getExtensions() {
|
public String[] getExtensions() {
|
||||||
return new String[] { "pde", "c", "cpp", "h" };
|
return new String[] { "ino", "c", "cpp", "h" };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -42,33 +42,28 @@ public class AvrdudeUploader extends Uploader {
|
||||||
public AvrdudeUploader() {
|
public AvrdudeUploader() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// XXX: add support for uploading sketches using a programmer
|
public boolean uploadUsingPreferences(String buildPath, String className, boolean usingProgrammer)
|
||||||
public boolean uploadUsingPreferences(String buildPath, String className, boolean verbose)
|
|
||||||
throws RunnerException, SerialException {
|
throws RunnerException, SerialException {
|
||||||
this.verbose = verbose;
|
this.verbose = verbose;
|
||||||
Map<String, String> boardPreferences = Base.getBoardPreferences();
|
Map<String, String> boardPreferences = Base.getBoardPreferences();
|
||||||
String uploadUsing = boardPreferences.get("upload.using");
|
|
||||||
if (uploadUsing == null) {
|
|
||||||
// fall back on global preference
|
|
||||||
uploadUsing = Preferences.get("upload.using");
|
|
||||||
}
|
|
||||||
if (uploadUsing.equals("bootloader")) {
|
|
||||||
return uploadViaBootloader(buildPath, className);
|
|
||||||
} else {
|
|
||||||
Target t;
|
|
||||||
|
|
||||||
if (uploadUsing.indexOf(':') == -1) {
|
// if no protocol is specified for this board, assume it lacks a
|
||||||
t = Base.getTarget(); // the current target (associated with the board)
|
// bootloader and upload using the selected programmer.
|
||||||
} else {
|
if (usingProgrammer || boardPreferences.get("upload.protocol") == null) {
|
||||||
String targetName = uploadUsing.substring(0, uploadUsing.indexOf(':'));
|
String programmer = Preferences.get("programmer");
|
||||||
t = Base.targetsTable.get(targetName);
|
Target target = Base.getTarget();
|
||||||
uploadUsing = uploadUsing.substring(uploadUsing.indexOf(':') + 1);
|
|
||||||
|
if (programmer.indexOf(":") != -1) {
|
||||||
|
target = Base.targetsTable.get(programmer.substring(0, programmer.indexOf(":")));
|
||||||
|
programmer = programmer.substring(programmer.indexOf(":") + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
Collection params = getProgrammerCommands(t, uploadUsing);
|
Collection params = getProgrammerCommands(target, programmer);
|
||||||
params.add("-Uflash:w:" + buildPath + File.separator + className + ".hex:i");
|
params.add("-Uflash:w:" + buildPath + File.separator + className + ".hex:i");
|
||||||
return avrdude(params);
|
return avrdude(params);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return uploadViaBootloader(buildPath, className);
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean uploadViaBootloader(String buildPath, String className)
|
private boolean uploadViaBootloader(String buildPath, String className)
|
||||||
|
@ -96,8 +91,14 @@ public class AvrdudeUploader extends Uploader {
|
||||||
return avrdude(commandDownloader);
|
return avrdude(commandDownloader);
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean burnBootloader(String targetName, String programmer) throws RunnerException {
|
public boolean burnBootloader() throws RunnerException {
|
||||||
return burnBootloader(getProgrammerCommands(Base.targetsTable.get(targetName), programmer));
|
String programmer = Preferences.get("programmer");
|
||||||
|
Target target = Base.getTarget();
|
||||||
|
if (programmer.indexOf(":") != -1) {
|
||||||
|
target = Base.targetsTable.get(programmer.substring(0, programmer.indexOf(":")));
|
||||||
|
programmer = programmer.substring(programmer.indexOf(":") + 1);
|
||||||
|
}
|
||||||
|
return burnBootloader(getProgrammerCommands(target, programmer));
|
||||||
}
|
}
|
||||||
|
|
||||||
private Collection getProgrammerCommands(Target target, String programmer) {
|
private Collection getProgrammerCommands(Target target, String programmer) {
|
||||||
|
|
|
@ -64,10 +64,10 @@ public abstract class Uploader implements MessageConsumer {
|
||||||
public Uploader() {
|
public Uploader() {
|
||||||
}
|
}
|
||||||
|
|
||||||
public abstract boolean uploadUsingPreferences(String buildPath, String className, boolean verbose)
|
public abstract boolean uploadUsingPreferences(String buildPath, String className, boolean usingProgrammer)
|
||||||
throws RunnerException, SerialException;
|
throws RunnerException, SerialException;
|
||||||
|
|
||||||
public abstract boolean burnBootloader(String target, String programmer) throws RunnerException;
|
public abstract boolean burnBootloader() throws RunnerException;
|
||||||
|
|
||||||
protected void flushSerialBuffer() throws RunnerException, SerialException {
|
protected void flushSerialBuffer() throws RunnerException, SerialException {
|
||||||
// Cleanup the serial buffer
|
// Cleanup the serial buffer
|
||||||
|
|
|
@ -44,8 +44,8 @@ public class Platform extends processing.app.Platform {
|
||||||
|
|
||||||
static final String openCommand =
|
static final String openCommand =
|
||||||
System.getProperty("user.dir").replace('/', '\\') +
|
System.getProperty("user.dir").replace('/', '\\') +
|
||||||
"\\processing.exe \"%1\"";
|
"\\arduino.exe \"%1\"";
|
||||||
static final String DOC = "Processing.Document";
|
static final String DOC = "Arduino.Document";
|
||||||
|
|
||||||
public void init(Base base) {
|
public void init(Base base) {
|
||||||
super.init(base);
|
super.init(base);
|
||||||
|
@ -86,13 +86,13 @@ public class Platform extends processing.app.Platform {
|
||||||
*/
|
*/
|
||||||
protected void setAssociations() throws UnsupportedEncodingException {
|
protected void setAssociations() throws UnsupportedEncodingException {
|
||||||
if (Registry.createKey(REGISTRY_ROOT_KEY.CLASSES_ROOT,
|
if (Registry.createKey(REGISTRY_ROOT_KEY.CLASSES_ROOT,
|
||||||
"", ".pde") &&
|
"", ".ino") &&
|
||||||
Registry.setStringValue(REGISTRY_ROOT_KEY.CLASSES_ROOT,
|
Registry.setStringValue(REGISTRY_ROOT_KEY.CLASSES_ROOT,
|
||||||
".pde", "", DOC) &&
|
".ino", "", DOC) &&
|
||||||
|
|
||||||
Registry.createKey(REGISTRY_ROOT_KEY.CLASSES_ROOT, "", DOC) &&
|
Registry.createKey(REGISTRY_ROOT_KEY.CLASSES_ROOT, "", DOC) &&
|
||||||
Registry.setStringValue(REGISTRY_ROOT_KEY.CLASSES_ROOT, DOC, "",
|
Registry.setStringValue(REGISTRY_ROOT_KEY.CLASSES_ROOT, DOC, "",
|
||||||
"Processing Source Code") &&
|
"Arduino Source Code") &&
|
||||||
|
|
||||||
Registry.createKey(REGISTRY_ROOT_KEY.CLASSES_ROOT,
|
Registry.createKey(REGISTRY_ROOT_KEY.CLASSES_ROOT,
|
||||||
DOC, "shell") &&
|
DOC, "shell") &&
|
||||||
|
|
|
@ -35,13 +35,15 @@
|
||||||
<dict>
|
<dict>
|
||||||
<key>CFBundleTypeExtensions</key>
|
<key>CFBundleTypeExtensions</key>
|
||||||
<array>
|
<array>
|
||||||
<string>pde</string>
|
<string>ino</string>
|
||||||
<string>java</string>
|
<string>c</string>
|
||||||
|
<string>cpp</string>
|
||||||
|
<string>h</string>
|
||||||
</array>
|
</array>
|
||||||
<key>CFBundleTypeIconFile</key>
|
<key>CFBundleTypeIconFile</key>
|
||||||
<string>pde.icns</string>
|
<string>pde.icns</string>
|
||||||
<key>CFBundleTypeName</key>
|
<key>CFBundleTypeName</key>
|
||||||
<string>Processing Source File</string>
|
<string>Arduino Source File</string>
|
||||||
<key>CFBundleTypeMIMETypes</key>
|
<key>CFBundleTypeMIMETypes</key>
|
||||||
<array>
|
<array>
|
||||||
<string>text/plain</string>
|
<string>text/plain</string>
|
||||||
|
|
Before Width: | Height: | Size: 113 KiB After Width: | Height: | Size: 104 KiB |
|
@ -240,6 +240,8 @@ run.present.exclusive.macosx = true
|
||||||
board = uno
|
board = uno
|
||||||
target = arduino
|
target = arduino
|
||||||
|
|
||||||
|
programmer = arduino:avrispmkii
|
||||||
|
|
||||||
upload.using = bootloader
|
upload.using = bootloader
|
||||||
|
|
||||||
serial.port=COM1
|
serial.port=COM1
|
||||||
|
|
Before Width: | Height: | Size: 2.7 KiB After Width: | Height: | Size: 3.3 KiB |
Before Width: | Height: | Size: 869 B After Width: | Height: | Size: 73 B |
Before Width: | Height: | Size: 832 B After Width: | Height: | Size: 73 B |
Before Width: | Height: | Size: 891 B After Width: | Height: | Size: 114 B |
Before Width: | Height: | Size: 830 B After Width: | Height: | Size: 54 B |
Before Width: | Height: | Size: 834 B After Width: | Height: | Size: 87 B |
Before Width: | Height: | Size: 844 B After Width: | Height: | Size: 73 B |
Before Width: | Height: | Size: 896 B After Width: | Height: | Size: 114 B |
Before Width: | Height: | Size: 828 B After Width: | Height: | Size: 54 B |
Before Width: | Height: | Size: 842 B After Width: | Height: | Size: 73 B |
|
@ -1,35 +1,35 @@
|
||||||
# GUI - STATUS
|
# GUI - STATUS
|
||||||
status.notice.fgcolor = #000000
|
status.notice.fgcolor = #002325
|
||||||
status.notice.bgcolor = #54919e
|
status.notice.bgcolor = #17A1A5
|
||||||
status.error.fgcolor = #ffffff
|
status.error.fgcolor = #FFFFFF
|
||||||
status.error.bgcolor = #662000
|
status.error.bgcolor = #E34C00
|
||||||
status.edit.fgcolor = #000000
|
status.edit.fgcolor = #000000
|
||||||
status.edit.bgcolor = #cc9900
|
status.edit.bgcolor = #F1B500
|
||||||
status.font = SansSerif,plain,12
|
status.font = SansSerif,plain,12
|
||||||
|
|
||||||
# GUI - TABS
|
# GUI - TABS
|
||||||
# settings for the tabs at the top
|
# settings for the tabs at the top
|
||||||
# (tab images are stored in the lib/theme folder)
|
# (tab images are stored in the lib/theme folder)
|
||||||
header.bgcolor = #216886
|
header.bgcolor = #17A1A5
|
||||||
header.text.selected.color = #1a1a00
|
header.text.selected.color = #005B5B
|
||||||
header.text.unselected.color = #ffffff
|
header.text.unselected.color = #007e82
|
||||||
header.text.font = SansSerif,plain,12
|
header.text.font = SansSerif,plain,12
|
||||||
|
|
||||||
# GUI - CONSOLE
|
# GUI - CONSOLE
|
||||||
console.font = Monospaced,plain,11
|
console.font = Monospaced,plain,11
|
||||||
console.font.macosx = Monaco,plain,10
|
console.font.macosx = Monaco,plain,10
|
||||||
console.color = #000000
|
console.color = #000000
|
||||||
console.output.color = #cccccc
|
console.output.color = #eeeeee
|
||||||
console.error.color = #ff3000
|
console.error.color = #E34C00
|
||||||
|
|
||||||
# GUI - BUTTONS
|
# GUI - BUTTONS
|
||||||
buttons.bgcolor = #044f6f
|
buttons.bgcolor = #006468
|
||||||
buttons.status.font = SansSerif,plain,12
|
buttons.status.font = SansSerif,plain,12
|
||||||
buttons.status.color = #ffffff
|
buttons.status.color = #ffffff
|
||||||
|
|
||||||
# GUI - LINESTATUS
|
# GUI - LINESTATUS
|
||||||
linestatus.color = #ffffff
|
linestatus.color = #17A1A5
|
||||||
linestatus.bgcolor = #044f6f
|
linestatus.bgcolor = #006468
|
||||||
|
|
||||||
# EDITOR - DETAILS
|
# EDITOR - DETAILS
|
||||||
|
|
||||||
|
|
Before Width: | Height: | Size: 374 KiB After Width: | Height: | Size: 457 KiB |
|
@ -1,227 +1,534 @@
|
||||||
/*
|
/*
|
||||||
SoftwareSerial.cpp - Software serial library
|
SoftwareSerial.cpp (formerly NewSoftSerial.cpp) -
|
||||||
Copyright (c) 2006 David A. Mellis. All right reserved.
|
Multi-instance software serial library for Arduino/Wiring
|
||||||
|
-- Interrupt-driven receive and other improvements by ladyada
|
||||||
|
(http://ladyada.net)
|
||||||
|
-- Tuning, circular buffer, derivation from class Print/Stream,
|
||||||
|
multi-instance support, porting to 8MHz processors,
|
||||||
|
various optimizations, PROGMEM delay tables, inverse logic and
|
||||||
|
direct port writing by Mikal Hart (http://www.arduiniana.org)
|
||||||
|
-- Pin change interrupt macros by Paul Stoffregen (http://www.pjrc.com)
|
||||||
|
-- 20MHz processor support by Garrett Mace (http://www.macetech.com)
|
||||||
|
-- ATmega1280/2560 support by Brett Hagman (http://www.roguerobotics.com/)
|
||||||
|
|
||||||
This library is free software; you can redistribute it and/or
|
This library is free software; you can redistribute it and/or
|
||||||
modify it under the terms of the GNU Lesser General Public
|
modify it under the terms of the GNU Lesser General Public
|
||||||
License as published by the Free Software Foundation; either
|
License as published by the Free Software Foundation; either
|
||||||
version 2.1 of the License, or (at your option) any later version.
|
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,
|
This library is distributed in the hope that it will be useful,
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
Lesser General Public License for more details.
|
Lesser General Public License for more details.
|
||||||
|
|
||||||
You should have received a copy of the GNU Lesser General Public
|
You should have received a copy of the GNU Lesser General Public
|
||||||
License along with this library; if not, write to the Free Software
|
License along with this library; if not, write to the Free Software
|
||||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
|
||||||
|
The latest version of this library can always be found at
|
||||||
|
http://arduiniana.org.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/******************************************************************************
|
// When set, _DEBUG co-opts pins 11 and 13 for debugging with an
|
||||||
* Includes
|
// oscilloscope or logic analyzer. Beware: it also slightly modifies
|
||||||
******************************************************************************/
|
// the bit times, so don't rely on it too much at high baud rates
|
||||||
|
#define _DEBUG 0
|
||||||
|
#define _DEBUG_PIN1 11
|
||||||
|
#define _DEBUG_PIN2 13
|
||||||
|
//
|
||||||
|
// Includes
|
||||||
|
//
|
||||||
|
#include <avr/interrupt.h>
|
||||||
|
#include <avr/pgmspace.h>
|
||||||
#include "WConstants.h"
|
#include "WConstants.h"
|
||||||
|
#include "pins_arduino.h"
|
||||||
#include "SoftwareSerial.h"
|
#include "SoftwareSerial.h"
|
||||||
|
#include "icrmacros.h"
|
||||||
/******************************************************************************
|
//
|
||||||
* Definitions
|
// Lookup table
|
||||||
******************************************************************************/
|
//
|
||||||
|
typedef struct _DELAY_TABLE
|
||||||
/******************************************************************************
|
|
||||||
* Constructors
|
|
||||||
******************************************************************************/
|
|
||||||
|
|
||||||
SoftwareSerial::SoftwareSerial(uint8_t receivePin, uint8_t transmitPin)
|
|
||||||
{
|
{
|
||||||
_receivePin = receivePin;
|
long baud;
|
||||||
_transmitPin = transmitPin;
|
unsigned short rx_delay_centering;
|
||||||
_baudRate = 0;
|
unsigned short rx_delay_intrabit;
|
||||||
|
unsigned short rx_delay_stopbit;
|
||||||
|
unsigned short tx_delay;
|
||||||
|
} DELAY_TABLE;
|
||||||
|
|
||||||
|
#if F_CPU == 16000000
|
||||||
|
|
||||||
|
static const DELAY_TABLE PROGMEM table[] =
|
||||||
|
{
|
||||||
|
// baud rxcenter rxintra rxstop tx
|
||||||
|
{ 115200, 1, 17, 17, 12, },
|
||||||
|
{ 57600, 10, 37, 37, 33, },
|
||||||
|
{ 38400, 25, 57, 57, 54, },
|
||||||
|
{ 31250, 31, 70, 70, 68, },
|
||||||
|
{ 28800, 34, 77, 77, 74, },
|
||||||
|
{ 19200, 54, 117, 117, 114, },
|
||||||
|
{ 14400, 74, 156, 156, 153, },
|
||||||
|
{ 9600, 114, 236, 236, 233, },
|
||||||
|
{ 4800, 233, 474, 474, 471, },
|
||||||
|
{ 2400, 471, 950, 950, 947, },
|
||||||
|
{ 1200, 947, 1902, 1902, 1899, },
|
||||||
|
{ 300, 3804, 7617, 7617, 7614, },
|
||||||
|
};
|
||||||
|
|
||||||
|
const int XMIT_START_ADJUSTMENT = 5;
|
||||||
|
|
||||||
|
#elif F_CPU == 8000000
|
||||||
|
|
||||||
|
static const DELAY_TABLE table[] PROGMEM =
|
||||||
|
{
|
||||||
|
// baud rxcenter rxintra rxstop tx
|
||||||
|
{ 115200, 1, 5, 5, 3, },
|
||||||
|
{ 57600, 1, 15, 15, 13, },
|
||||||
|
{ 38400, 2, 25, 26, 23, },
|
||||||
|
{ 31250, 7, 32, 33, 29, },
|
||||||
|
{ 28800, 11, 35, 35, 32, },
|
||||||
|
{ 19200, 20, 55, 55, 52, },
|
||||||
|
{ 14400, 30, 75, 75, 72, },
|
||||||
|
{ 9600, 50, 114, 114, 112, },
|
||||||
|
{ 4800, 110, 233, 233, 230, },
|
||||||
|
{ 2400, 229, 472, 472, 469, },
|
||||||
|
{ 1200, 467, 948, 948, 945, },
|
||||||
|
{ 300, 1895, 3805, 3805, 3802, },
|
||||||
|
};
|
||||||
|
|
||||||
|
const int XMIT_START_ADJUSTMENT = 4;
|
||||||
|
|
||||||
|
#elif F_CPU == 20000000
|
||||||
|
|
||||||
|
// 20MHz support courtesy of the good people at macegr.com.
|
||||||
|
// Thanks, Garrett!
|
||||||
|
|
||||||
|
static const DELAY_TABLE PROGMEM table[] =
|
||||||
|
{
|
||||||
|
// baud rxcenter rxintra rxstop tx
|
||||||
|
{ 115200, 3, 21, 21, 18, },
|
||||||
|
{ 57600, 20, 43, 43, 41, },
|
||||||
|
{ 38400, 37, 73, 73, 70, },
|
||||||
|
{ 31250, 45, 89, 89, 88, },
|
||||||
|
{ 28800, 46, 98, 98, 95, },
|
||||||
|
{ 19200, 71, 148, 148, 145, },
|
||||||
|
{ 14400, 96, 197, 197, 194, },
|
||||||
|
{ 9600, 146, 297, 297, 294, },
|
||||||
|
{ 4800, 296, 595, 595, 592, },
|
||||||
|
{ 2400, 592, 1189, 1189, 1186, },
|
||||||
|
{ 1200, 1187, 2379, 2379, 2376, },
|
||||||
|
{ 300, 4759, 9523, 9523, 9520, },
|
||||||
|
};
|
||||||
|
|
||||||
|
const int XMIT_START_ADJUSTMENT = 6;
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
#error This version of SoftwareSerial supports only 20, 16 and 8MHz processors
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//
|
||||||
|
// Statics
|
||||||
|
//
|
||||||
|
SoftwareSerial *SoftwareSerial::active_object = 0;
|
||||||
|
char SoftwareSerial::_receive_buffer[_SS_MAX_RX_BUFF];
|
||||||
|
volatile uint8_t SoftwareSerial::_receive_buffer_tail = 0;
|
||||||
|
volatile uint8_t SoftwareSerial::_receive_buffer_head = 0;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Debugging
|
||||||
|
//
|
||||||
|
// This function generates a brief pulse
|
||||||
|
// for debugging or measuring on an oscilloscope.
|
||||||
|
inline void DebugPulse(uint8_t pin, uint8_t count)
|
||||||
|
{
|
||||||
|
#if _DEBUG
|
||||||
|
volatile uint8_t *pport = portOutputRegister(digitalPinToPort(pin));
|
||||||
|
|
||||||
|
uint8_t val = *pport;
|
||||||
|
while (count--)
|
||||||
|
{
|
||||||
|
*pport = val | digitalPinToBitMask(pin);
|
||||||
|
*pport = val;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
/******************************************************************************
|
//
|
||||||
* User API
|
// Private methods
|
||||||
******************************************************************************/
|
//
|
||||||
|
|
||||||
|
/* static */
|
||||||
|
inline void SoftwareSerial::tunedDelay(uint16_t delay) {
|
||||||
|
uint8_t tmp=0;
|
||||||
|
|
||||||
|
asm volatile("sbiw %0, 0x01 \n\t"
|
||||||
|
"ldi %1, 0xFF \n\t"
|
||||||
|
"cpi %A0, 0xFF \n\t"
|
||||||
|
"cpc %B0, %1 \n\t"
|
||||||
|
"brne .-10 \n\t"
|
||||||
|
: "+r" (delay), "+a" (tmp)
|
||||||
|
: "0" (delay)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// This function sets the current object as the "listening"
|
||||||
|
// one and returns true if it replaces another
|
||||||
|
bool SoftwareSerial::listen()
|
||||||
|
{
|
||||||
|
if (active_object != this)
|
||||||
|
{
|
||||||
|
_buffer_overflow = false;
|
||||||
|
uint8_t oldSREG = SREG;
|
||||||
|
cli();
|
||||||
|
_receive_buffer_head = _receive_buffer_tail = 0;
|
||||||
|
active_object = this;
|
||||||
|
SREG = oldSREG;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// The receive routine called by the interrupt handler
|
||||||
|
//
|
||||||
|
void SoftwareSerial::recv()
|
||||||
|
{
|
||||||
|
|
||||||
|
#if GCC_VERSION < 40302
|
||||||
|
// Work-around for avr-gcc 4.3.0 OSX version bug
|
||||||
|
// Preserve the registers that the compiler misses
|
||||||
|
// (courtesy of Arduino forum user *etracer*)
|
||||||
|
asm volatile(
|
||||||
|
"push r18 \n\t"
|
||||||
|
"push r19 \n\t"
|
||||||
|
"push r20 \n\t"
|
||||||
|
"push r21 \n\t"
|
||||||
|
"push r22 \n\t"
|
||||||
|
"push r23 \n\t"
|
||||||
|
"push r26 \n\t"
|
||||||
|
"push r27 \n\t"
|
||||||
|
::);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
uint8_t d = 0;
|
||||||
|
|
||||||
|
// If RX line is high, then we don't see any start bit
|
||||||
|
// so interrupt is probably not for us
|
||||||
|
if (_inverse_logic ? rx_pin_read() : !rx_pin_read())
|
||||||
|
{
|
||||||
|
// Wait approximately 1/2 of a bit width to "center" the sample
|
||||||
|
tunedDelay(_rx_delay_centering);
|
||||||
|
DebugPulse(_DEBUG_PIN2, 1);
|
||||||
|
|
||||||
|
// Read each of the 8 bits
|
||||||
|
for (uint8_t i=0x1; i; i <<= 1)
|
||||||
|
{
|
||||||
|
tunedDelay(_rx_delay_intrabit);
|
||||||
|
DebugPulse(_DEBUG_PIN2, 1);
|
||||||
|
uint8_t noti = ~i;
|
||||||
|
if (rx_pin_read())
|
||||||
|
d |= i;
|
||||||
|
else // else clause added to ensure function timing is ~balanced
|
||||||
|
d &= noti;
|
||||||
|
}
|
||||||
|
|
||||||
|
// skip the stop bit
|
||||||
|
tunedDelay(_rx_delay_stopbit);
|
||||||
|
DebugPulse(_DEBUG_PIN2, 1);
|
||||||
|
|
||||||
|
if (_inverse_logic)
|
||||||
|
d = ~d;
|
||||||
|
|
||||||
|
// if buffer full, set the overflow flag and return
|
||||||
|
if ((_receive_buffer_tail + 1) % _SS_MAX_RX_BUFF != _receive_buffer_head)
|
||||||
|
{
|
||||||
|
// save new data in buffer: tail points to where byte goes
|
||||||
|
_receive_buffer[_receive_buffer_tail] = d; // save new byte
|
||||||
|
_receive_buffer_tail = (_receive_buffer_tail + 1) % _SS_MAX_RX_BUFF;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
#if _DEBUG // for scope: pulse pin as overflow indictator
|
||||||
|
DebugPulse(_DEBUG_PIN1, 1);
|
||||||
|
#endif
|
||||||
|
_buffer_overflow = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#if GCC_VERSION < 40302
|
||||||
|
// Work-around for avr-gcc 4.3.0 OSX version bug
|
||||||
|
// Restore the registers that the compiler misses
|
||||||
|
asm volatile(
|
||||||
|
"pop r27 \n\t"
|
||||||
|
"pop r26 \n\t"
|
||||||
|
"pop r23 \n\t"
|
||||||
|
"pop r22 \n\t"
|
||||||
|
"pop r21 \n\t"
|
||||||
|
"pop r20 \n\t"
|
||||||
|
"pop r19 \n\t"
|
||||||
|
"pop r18 \n\t"
|
||||||
|
::);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void SoftwareSerial::tx_pin_write(uint8_t pin_state)
|
||||||
|
{
|
||||||
|
if (pin_state == LOW)
|
||||||
|
*_transmitPortRegister &= ~_transmitBitMask;
|
||||||
|
else
|
||||||
|
*_transmitPortRegister |= _transmitBitMask;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t SoftwareSerial::rx_pin_read()
|
||||||
|
{
|
||||||
|
return *_receivePortRegister & _receiveBitMask;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Interrupt handling
|
||||||
|
//
|
||||||
|
|
||||||
|
/* static */
|
||||||
|
inline void SoftwareSerial::handle_interrupt()
|
||||||
|
{
|
||||||
|
if (active_object)
|
||||||
|
{
|
||||||
|
active_object->recv();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#if defined(PCINT0_vect)
|
||||||
|
ISR(PCINT0_vect)
|
||||||
|
{
|
||||||
|
SoftwareSerial::handle_interrupt();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(PCINT1_vect)
|
||||||
|
ISR(PCINT1_vect)
|
||||||
|
{
|
||||||
|
SoftwareSerial::handle_interrupt();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(PCINT2_vect)
|
||||||
|
ISR(PCINT2_vect)
|
||||||
|
{
|
||||||
|
SoftwareSerial::handle_interrupt();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(PCINT3_vect)
|
||||||
|
ISR(PCINT3_vect)
|
||||||
|
{
|
||||||
|
SoftwareSerial::handle_interrupt();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//
|
||||||
|
// Constructor
|
||||||
|
//
|
||||||
|
SoftwareSerial::SoftwareSerial(uint8_t receivePin, uint8_t transmitPin, bool inverse_logic /* = false */) :
|
||||||
|
_rx_delay_centering(0),
|
||||||
|
_rx_delay_intrabit(0),
|
||||||
|
_rx_delay_stopbit(0),
|
||||||
|
_tx_delay(0),
|
||||||
|
_buffer_overflow(false),
|
||||||
|
_inverse_logic(inverse_logic)
|
||||||
|
{
|
||||||
|
setTX(transmitPin);
|
||||||
|
setRX(receivePin);
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Destructor
|
||||||
|
//
|
||||||
|
SoftwareSerial::~SoftwareSerial()
|
||||||
|
{
|
||||||
|
end();
|
||||||
|
}
|
||||||
|
|
||||||
|
void SoftwareSerial::setTX(uint8_t tx)
|
||||||
|
{
|
||||||
|
pinMode(tx, OUTPUT);
|
||||||
|
digitalWrite(tx, HIGH);
|
||||||
|
_transmitBitMask = digitalPinToBitMask(tx);
|
||||||
|
uint8_t port = digitalPinToPort(tx);
|
||||||
|
_transmitPortRegister = portOutputRegister(port);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SoftwareSerial::setRX(uint8_t rx)
|
||||||
|
{
|
||||||
|
pinMode(rx, INPUT);
|
||||||
|
if (!_inverse_logic)
|
||||||
|
digitalWrite(rx, HIGH); // pullup for normal logic!
|
||||||
|
_receivePin = rx;
|
||||||
|
_receiveBitMask = digitalPinToBitMask(rx);
|
||||||
|
uint8_t port = digitalPinToPort(rx);
|
||||||
|
_receivePortRegister = portInputRegister(port);
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Public methods
|
||||||
|
//
|
||||||
|
|
||||||
void SoftwareSerial::begin(long speed)
|
void SoftwareSerial::begin(long speed)
|
||||||
{
|
{
|
||||||
_baudRate = speed;
|
_rx_delay_centering = _rx_delay_intrabit = _rx_delay_stopbit = _tx_delay = 0;
|
||||||
_bitPeriod = 1000000 / _baudRate;
|
|
||||||
|
|
||||||
digitalWrite(_transmitPin, HIGH);
|
for (unsigned i=0; i<sizeof(table)/sizeof(table[0]); ++i)
|
||||||
delayMicroseconds( _bitPeriod); // if we were low this establishes the end
|
{
|
||||||
|
long baud = pgm_read_dword(&table[i].baud);
|
||||||
|
if (baud == speed)
|
||||||
|
{
|
||||||
|
_rx_delay_centering = pgm_read_word(&table[i].rx_delay_centering);
|
||||||
|
_rx_delay_intrabit = pgm_read_word(&table[i].rx_delay_intrabit);
|
||||||
|
_rx_delay_stopbit = pgm_read_word(&table[i].rx_delay_stopbit);
|
||||||
|
_tx_delay = pgm_read_word(&table[i].tx_delay);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set up RX interrupts, but only if we have a valid RX baud rate
|
||||||
|
if (_rx_delay_stopbit)
|
||||||
|
{
|
||||||
|
if (digitalPinToPCICR(_receivePin))
|
||||||
|
{
|
||||||
|
*digitalPinToPCICR(_receivePin) |= _BV(digitalPinToPCICRbit(_receivePin));
|
||||||
|
*digitalPinToPCMSK(_receivePin) |= _BV(digitalPinToPCMSKbit(_receivePin));
|
||||||
|
}
|
||||||
|
tunedDelay(_tx_delay); // if we were low this establishes the end
|
||||||
|
}
|
||||||
|
|
||||||
|
#if _DEBUG
|
||||||
|
pinMode(_DEBUG_PIN1, OUTPUT);
|
||||||
|
pinMode(_DEBUG_PIN2, OUTPUT);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
listen();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SoftwareSerial::end()
|
||||||
|
{
|
||||||
|
if (digitalPinToPCMSK(_receivePin))
|
||||||
|
*digitalPinToPCMSK(_receivePin) &= ~_BV(digitalPinToPCMSKbit(_receivePin));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Read data from buffer
|
||||||
int SoftwareSerial::read()
|
int SoftwareSerial::read()
|
||||||
{
|
{
|
||||||
int val = 0;
|
if (!is_listening())
|
||||||
int bitDelay = _bitPeriod - clockCyclesToMicroseconds(50);
|
|
||||||
|
|
||||||
// one byte of serial data (LSB first)
|
|
||||||
// ...--\ /--\/--\/--\/--\/--\/--\/--\/--\/--...
|
|
||||||
// \--/\--/\--/\--/\--/\--/\--/\--/\--/
|
|
||||||
// start 0 1 2 3 4 5 6 7 stop
|
|
||||||
|
|
||||||
while (digitalRead(_receivePin));
|
|
||||||
|
|
||||||
// confirm that this is a real start bit, not line noise
|
|
||||||
if (digitalRead(_receivePin) == LOW) {
|
|
||||||
// frame start indicated by a falling edge and low start bit
|
|
||||||
// jump to the middle of the low start bit
|
|
||||||
delayMicroseconds(bitDelay / 2 - clockCyclesToMicroseconds(50));
|
|
||||||
|
|
||||||
// offset of the bit in the byte: from 0 (LSB) to 7 (MSB)
|
|
||||||
for (int offset = 0; offset < 8; offset++) {
|
|
||||||
// jump to middle of next bit
|
|
||||||
delayMicroseconds(bitDelay);
|
|
||||||
|
|
||||||
// read bit
|
|
||||||
val |= digitalRead(_receivePin) << offset;
|
|
||||||
}
|
|
||||||
|
|
||||||
delayMicroseconds(_bitPeriod);
|
|
||||||
|
|
||||||
return val;
|
|
||||||
}
|
|
||||||
|
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
|
// Empty buffer?
|
||||||
|
if (_receive_buffer_head == _receive_buffer_tail)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
// Read from "head"
|
||||||
|
uint8_t d = _receive_buffer[_receive_buffer_head]; // grab next byte
|
||||||
|
_receive_buffer_head = (_receive_buffer_head + 1) % _SS_MAX_RX_BUFF;
|
||||||
|
return d;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SoftwareSerial::print(uint8_t b)
|
int SoftwareSerial::available()
|
||||||
{
|
{
|
||||||
if (_baudRate == 0)
|
if (!is_listening())
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
return (_receive_buffer_tail + _SS_MAX_RX_BUFF - _receive_buffer_head) % _SS_MAX_RX_BUFF;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SoftwareSerial::write(uint8_t b)
|
||||||
|
{
|
||||||
|
if (_tx_delay == 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
int bitDelay = _bitPeriod - clockCyclesToMicroseconds(50); // a digitalWrite is about 50 cycles
|
uint8_t oldSREG = SREG;
|
||||||
byte mask;
|
cli(); // turn off interrupts for a clean txmit
|
||||||
|
|
||||||
digitalWrite(_transmitPin, LOW);
|
// Write the start bit
|
||||||
delayMicroseconds(bitDelay);
|
tx_pin_write(_inverse_logic ? HIGH : LOW);
|
||||||
|
tunedDelay(_tx_delay + XMIT_START_ADJUSTMENT);
|
||||||
|
|
||||||
for (mask = 0x01; mask; mask <<= 1) {
|
// Write each of the 8 bits
|
||||||
if (b & mask){ // choose bit
|
if (_inverse_logic)
|
||||||
digitalWrite(_transmitPin,HIGH); // send 1
|
{
|
||||||
}
|
for (byte mask = 0x01; mask; mask <<= 1)
|
||||||
else{
|
{
|
||||||
digitalWrite(_transmitPin,LOW); // send 1
|
if (b & mask) // choose bit
|
||||||
}
|
tx_pin_write(LOW); // send 1
|
||||||
delayMicroseconds(bitDelay);
|
|
||||||
}
|
|
||||||
|
|
||||||
digitalWrite(_transmitPin, HIGH);
|
|
||||||
delayMicroseconds(bitDelay);
|
|
||||||
}
|
|
||||||
|
|
||||||
void SoftwareSerial::print(const char *s)
|
|
||||||
{
|
|
||||||
while (*s)
|
|
||||||
print(*s++);
|
|
||||||
}
|
|
||||||
|
|
||||||
void SoftwareSerial::print(char c)
|
|
||||||
{
|
|
||||||
print((uint8_t) c);
|
|
||||||
}
|
|
||||||
|
|
||||||
void SoftwareSerial::print(int n)
|
|
||||||
{
|
|
||||||
print((long) n);
|
|
||||||
}
|
|
||||||
|
|
||||||
void SoftwareSerial::print(unsigned int n)
|
|
||||||
{
|
|
||||||
print((unsigned long) n);
|
|
||||||
}
|
|
||||||
|
|
||||||
void SoftwareSerial::print(long n)
|
|
||||||
{
|
|
||||||
if (n < 0) {
|
|
||||||
print('-');
|
|
||||||
n = -n;
|
|
||||||
}
|
|
||||||
printNumber(n, 10);
|
|
||||||
}
|
|
||||||
|
|
||||||
void SoftwareSerial::print(unsigned long n)
|
|
||||||
{
|
|
||||||
printNumber(n, 10);
|
|
||||||
}
|
|
||||||
|
|
||||||
void SoftwareSerial::print(long n, int base)
|
|
||||||
{
|
|
||||||
if (base == 0)
|
|
||||||
print((char) n);
|
|
||||||
else if (base == 10)
|
|
||||||
print(n);
|
|
||||||
else
|
else
|
||||||
printNumber(n, base);
|
tx_pin_write(HIGH); // send 0
|
||||||
|
|
||||||
|
tunedDelay(_tx_delay);
|
||||||
|
}
|
||||||
|
|
||||||
|
tx_pin_write(LOW); // restore pin to natural state
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for (byte mask = 0x01; mask; mask <<= 1)
|
||||||
|
{
|
||||||
|
if (b & mask) // choose bit
|
||||||
|
tx_pin_write(HIGH); // send 1
|
||||||
|
else
|
||||||
|
tx_pin_write(LOW); // send 0
|
||||||
|
|
||||||
|
tunedDelay(_tx_delay);
|
||||||
|
}
|
||||||
|
|
||||||
|
tx_pin_write(HIGH); // restore pin to natural state
|
||||||
|
}
|
||||||
|
|
||||||
|
SREG = oldSREG; // turn interrupts back on
|
||||||
|
tunedDelay(_tx_delay);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SoftwareSerial::println(void)
|
#if !defined(cbi)
|
||||||
|
#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit))
|
||||||
|
#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void SoftwareSerial::enable_timer0(bool enable)
|
||||||
{
|
{
|
||||||
print('\r');
|
if (enable)
|
||||||
print('\n');
|
#if defined(__AVR_ATmega8__)
|
||||||
|
sbi(TIMSK, TOIE0);
|
||||||
|
#else
|
||||||
|
sbi(TIMSK0, TOIE0);
|
||||||
|
#endif
|
||||||
|
else
|
||||||
|
#if defined(__AVR_ATmega8__)
|
||||||
|
cbi(TIMSK, TOIE0);
|
||||||
|
#else
|
||||||
|
cbi(TIMSK0, TOIE0);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void SoftwareSerial::println(char c)
|
void SoftwareSerial::flush()
|
||||||
{
|
{
|
||||||
print(c);
|
if (!is_listening())
|
||||||
println();
|
|
||||||
}
|
|
||||||
|
|
||||||
void SoftwareSerial::println(const char c[])
|
|
||||||
{
|
|
||||||
print(c);
|
|
||||||
println();
|
|
||||||
}
|
|
||||||
|
|
||||||
void SoftwareSerial::println(uint8_t b)
|
|
||||||
{
|
|
||||||
print(b);
|
|
||||||
println();
|
|
||||||
}
|
|
||||||
|
|
||||||
void SoftwareSerial::println(int n)
|
|
||||||
{
|
|
||||||
print(n);
|
|
||||||
println();
|
|
||||||
}
|
|
||||||
|
|
||||||
void SoftwareSerial::println(long n)
|
|
||||||
{
|
|
||||||
print(n);
|
|
||||||
println();
|
|
||||||
}
|
|
||||||
|
|
||||||
void SoftwareSerial::println(unsigned long n)
|
|
||||||
{
|
|
||||||
print(n);
|
|
||||||
println();
|
|
||||||
}
|
|
||||||
|
|
||||||
void SoftwareSerial::println(long n, int base)
|
|
||||||
{
|
|
||||||
print(n, base);
|
|
||||||
println();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Private Methods /////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
void SoftwareSerial::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;
|
return;
|
||||||
}
|
|
||||||
|
|
||||||
while (n > 0) {
|
uint8_t oldSREG = SREG;
|
||||||
buf[i++] = n % base;
|
cli();
|
||||||
n /= base;
|
_receive_buffer_head = _receive_buffer_tail = 0;
|
||||||
}
|
SREG = oldSREG;
|
||||||
|
}
|
||||||
for (; i > 0; i--)
|
|
||||||
print((char) (buf[i - 1] < 10 ? '0' + buf[i - 1] : 'A' + buf[i - 1] - 10));
|
int SoftwareSerial::peek()
|
||||||
|
{
|
||||||
|
if (!is_listening())
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
// Empty buffer?
|
||||||
|
if (_receive_buffer_head == _receive_buffer_tail)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
// Read from "head"
|
||||||
|
return _receive_buffer[_receive_buffer_head];
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,56 +1,113 @@
|
||||||
/*
|
/*
|
||||||
SoftwareSerial.h - Software serial library
|
SoftwareSerial.h (formerly NewSoftSerial.h) -
|
||||||
Copyright (c) 2006 David A. Mellis. All right reserved.
|
Multi-instance software serial library for Arduino/Wiring
|
||||||
|
-- Interrupt-driven receive and other improvements by ladyada
|
||||||
|
(http://ladyada.net)
|
||||||
|
-- Tuning, circular buffer, derivation from class Print/Stream,
|
||||||
|
multi-instance support, porting to 8MHz processors,
|
||||||
|
various optimizations, PROGMEM delay tables, inverse logic and
|
||||||
|
direct port writing by Mikal Hart (http://www.arduiniana.org)
|
||||||
|
-- Pin change interrupt macros by Paul Stoffregen (http://www.pjrc.com)
|
||||||
|
-- 20MHz processor support by Garrett Mace (http://www.macetech.com)
|
||||||
|
-- ATmega1280/2560 support by Brett Hagman (http://www.roguerobotics.com/)
|
||||||
|
|
||||||
This library is free software; you can redistribute it and/or
|
This library is free software; you can redistribute it and/or
|
||||||
modify it under the terms of the GNU Lesser General Public
|
modify it under the terms of the GNU Lesser General Public
|
||||||
License as published by the Free Software Foundation; either
|
License as published by the Free Software Foundation; either
|
||||||
version 2.1 of the License, or (at your option) any later version.
|
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,
|
This library is distributed in the hope that it will be useful,
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
Lesser General Public License for more details.
|
Lesser General Public License for more details.
|
||||||
|
|
||||||
You should have received a copy of the GNU Lesser General Public
|
You should have received a copy of the GNU Lesser General Public
|
||||||
License along with this library; if not, write to the Free Software
|
License along with this library; if not, write to the Free Software
|
||||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
|
||||||
|
The latest version of this library can always be found at
|
||||||
|
http://arduiniana.org.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef SoftwareSerial_h
|
#ifndef SoftwareSerial_h
|
||||||
#define SoftwareSerial_h
|
#define SoftwareSerial_h
|
||||||
|
|
||||||
#include <inttypes.h>
|
#include <inttypes.h>
|
||||||
|
#include <Stream.h>
|
||||||
|
|
||||||
class SoftwareSerial
|
/******************************************************************************
|
||||||
{
|
* Definitions
|
||||||
private:
|
******************************************************************************/
|
||||||
uint8_t _receivePin;
|
|
||||||
uint8_t _transmitPin;
|
|
||||||
long _baudRate;
|
|
||||||
int _bitPeriod;
|
|
||||||
void printNumber(unsigned long, uint8_t);
|
|
||||||
public:
|
|
||||||
SoftwareSerial(uint8_t, uint8_t);
|
|
||||||
void begin(long);
|
|
||||||
int read();
|
|
||||||
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 println(void);
|
|
||||||
void println(char);
|
|
||||||
void println(const char[]);
|
|
||||||
void println(uint8_t);
|
|
||||||
void println(int);
|
|
||||||
void println(long);
|
|
||||||
void println(unsigned long);
|
|
||||||
void println(long, int);
|
|
||||||
};
|
|
||||||
|
|
||||||
|
#define _SS_MAX_RX_BUFF 64 // RX buffer size
|
||||||
|
#define _SS_VERSION 11 // software version of this library
|
||||||
|
#ifndef GCC_VERSION
|
||||||
|
#define GCC_VERSION (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
class SoftwareSerial : public Stream
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
// per object data
|
||||||
|
uint8_t _receivePin;
|
||||||
|
uint8_t _receiveBitMask;
|
||||||
|
volatile uint8_t *_receivePortRegister;
|
||||||
|
uint8_t _transmitBitMask;
|
||||||
|
volatile uint8_t *_transmitPortRegister;
|
||||||
|
|
||||||
|
uint16_t _rx_delay_centering;
|
||||||
|
uint16_t _rx_delay_intrabit;
|
||||||
|
uint16_t _rx_delay_stopbit;
|
||||||
|
uint16_t _tx_delay;
|
||||||
|
|
||||||
|
uint16_t _buffer_overflow:1;
|
||||||
|
uint16_t _inverse_logic:1;
|
||||||
|
|
||||||
|
// static data
|
||||||
|
static char _receive_buffer[_SS_MAX_RX_BUFF];
|
||||||
|
static volatile uint8_t _receive_buffer_tail;
|
||||||
|
static volatile uint8_t _receive_buffer_head;
|
||||||
|
static SoftwareSerial *active_object;
|
||||||
|
|
||||||
|
// private methods
|
||||||
|
void recv();
|
||||||
|
uint8_t rx_pin_read();
|
||||||
|
void tx_pin_write(uint8_t pin_state);
|
||||||
|
void setTX(uint8_t transmitPin);
|
||||||
|
void setRX(uint8_t receivePin);
|
||||||
|
|
||||||
|
// private static method for timing
|
||||||
|
static inline void tunedDelay(uint16_t delay);
|
||||||
|
|
||||||
|
public:
|
||||||
|
// public methods
|
||||||
|
SoftwareSerial(uint8_t receivePin, uint8_t transmitPin, bool inverse_logic = false);
|
||||||
|
~SoftwareSerial();
|
||||||
|
void begin(long speed);
|
||||||
|
bool listen();
|
||||||
|
void end();
|
||||||
|
bool is_listening() { return this == active_object; }
|
||||||
|
bool overflow() { bool ret = _buffer_overflow; _buffer_overflow = false; return ret; }
|
||||||
|
static int library_version() { return _SS_VERSION; }
|
||||||
|
static void enable_timer0(bool enable);
|
||||||
|
int peek();
|
||||||
|
|
||||||
|
virtual void write(uint8_t byte);
|
||||||
|
virtual int read();
|
||||||
|
virtual int available();
|
||||||
|
virtual void flush();
|
||||||
|
|
||||||
|
// public only for easy access by interrupt handlers
|
||||||
|
static inline void handle_interrupt();
|
||||||
|
};
|
||||||
|
|
||||||
|
// Arduino 0012 workaround
|
||||||
|
#undef int
|
||||||
|
#undef char
|
||||||
|
#undef long
|
||||||
|
#undef byte
|
||||||
|
#undef float
|
||||||
|
#undef abs
|
||||||
|
#undef round
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
|
@ -0,0 +1,21 @@
|
||||||
|
#include <SoftwareSerial.h>
|
||||||
|
|
||||||
|
SoftwareSerial mySerial(2, 3);
|
||||||
|
|
||||||
|
void setup()
|
||||||
|
{
|
||||||
|
Serial.begin(57600);
|
||||||
|
Serial.println("Goodnight moon!");
|
||||||
|
|
||||||
|
// set the data rate for the SoftwareSerial port
|
||||||
|
mySerial.begin(4800);
|
||||||
|
mySerial.println("Hello, world?");
|
||||||
|
}
|
||||||
|
|
||||||
|
void loop() // run over and over
|
||||||
|
{
|
||||||
|
if (mySerial.available())
|
||||||
|
Serial.print((char)mySerial.read());
|
||||||
|
if (Serial.available())
|
||||||
|
mySerial.print((char)Serial.read());
|
||||||
|
}
|
|
@ -0,0 +1,50 @@
|
||||||
|
#include <SoftwareSerial.h>
|
||||||
|
|
||||||
|
SoftwareSerial ss(2, 3);
|
||||||
|
SoftwareSerial ss2(4, 5);
|
||||||
|
|
||||||
|
/* This sample shows how to correctly process received data
|
||||||
|
on two different "soft" serial ports. Here we listen on
|
||||||
|
the first port (ss) until we receive a '?' character. Then
|
||||||
|
we begin listening on the other soft port.
|
||||||
|
*/
|
||||||
|
|
||||||
|
void setup()
|
||||||
|
{
|
||||||
|
// Start the HW serial port
|
||||||
|
Serial.begin(57600);
|
||||||
|
|
||||||
|
// Start each soft serial port
|
||||||
|
ss.begin(4800);
|
||||||
|
ss2.begin(4800);
|
||||||
|
|
||||||
|
// By default, the most recently "begun" port is listening.
|
||||||
|
// We want to listen on ss, so let's explicitly select it.
|
||||||
|
ss.listen();
|
||||||
|
|
||||||
|
// Simply wait for a ? character to come down the pipe
|
||||||
|
Serial.println("Data from the first port: ");
|
||||||
|
char c = 0;
|
||||||
|
do
|
||||||
|
if (ss.available())
|
||||||
|
{
|
||||||
|
c = (char)ss.read();
|
||||||
|
Serial.print(c);
|
||||||
|
}
|
||||||
|
while (c != '?');
|
||||||
|
|
||||||
|
// Now listen on the second port
|
||||||
|
ss2.listen();
|
||||||
|
|
||||||
|
Serial.println("Data from the second port: ");
|
||||||
|
}
|
||||||
|
|
||||||
|
void loop()
|
||||||
|
{
|
||||||
|
if (ss2.available())
|
||||||
|
{
|
||||||
|
char c = (char)ss2.read();
|
||||||
|
Serial.print(c);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,69 @@
|
||||||
|
/*
|
||||||
|
icrmacros.h
|
||||||
|
|
||||||
|
A place to put useful ICR (interrupt change register) macros
|
||||||
|
|
||||||
|
If you want to support non-Arduino processors you can extend or replace
|
||||||
|
this file.
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
The latest version of this library can always be found at
|
||||||
|
http://arduiniana.org.
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Abstractions for maximum portability between processors
|
||||||
|
// These are macros to associate pins to pin change interrupts
|
||||||
|
#if !defined(digitalPinToPCICR) // Courtesy Paul Stoffregen
|
||||||
|
|
||||||
|
#if defined(__AVR_ATmega168__) || defined(__AVR_ATmega328P__)
|
||||||
|
|
||||||
|
#define digitalPinToPCICR(p) (((p) >= 0 && (p) <= 21) ? (&PCICR) : ((uint8_t *)0))
|
||||||
|
#define digitalPinToPCICRbit(p) (((p) <= 7) ? 2 : (((p) <= 13) ? 0 : 1))
|
||||||
|
#define digitalPinToPCMSK(p) (((p) <= 7) ? (&PCMSK2) : (((p) <= 13) ? (&PCMSK0) : (((p) <= 21) ? (&PCMSK1) : ((uint8_t *)0))))
|
||||||
|
#define digitalPinToPCMSKbit(p) (((p) <= 7) ? (p) : (((p) <= 13) ? ((p) - 8) : ((p) - 14)))
|
||||||
|
|
||||||
|
#elif defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
|
||||||
|
// Specifically for the Arduino Mega 2560 (or 1280 on the original Arduino Mega)
|
||||||
|
// A majority of the pins are NOT PCINTs, SO BE WARNED (i.e. you cannot use them as receive pins)
|
||||||
|
// Only pins available for RECEIVE (TRANSMIT can be on any pin):
|
||||||
|
// (I've deliberately left out pin mapping to the Hardware USARTs - seems senseless to me)
|
||||||
|
// Pins: 10, 11, 12, 13, 50, 51, 52, 53, 62, 63, 64, 65, 66, 67, 68, 69
|
||||||
|
|
||||||
|
#define digitalPinToPCICR(p) ( (((p) >= 10) && ((p) <= 13)) || \
|
||||||
|
(((p) >= 50) && ((p) <= 53)) || \
|
||||||
|
(((p) >= 62) && ((p) <= 69)) ? (&PCICR) : ((uint8_t *)0) )
|
||||||
|
|
||||||
|
#define digitalPinToPCICRbit(p) ( (((p) >= 10) && ((p) <= 13)) || (((p) >= 50) && ((p) <= 53)) ? 0 : \
|
||||||
|
( (((p) >= 62) && ((p) <= 69)) ? 2 : \
|
||||||
|
0 ) )
|
||||||
|
|
||||||
|
#define digitalPinToPCMSK(p) ( (((p) >= 10) && ((p) <= 13)) || (((p) >= 50) && ((p) <= 53)) ? (&PCMSK0) : \
|
||||||
|
( (((p) >= 62) && ((p) <= 69)) ? (&PCMSK2) : \
|
||||||
|
((uint8_t *)0) ) )
|
||||||
|
|
||||||
|
#define digitalPinToPCMSKbit(p) ( (((p) >= 10) && ((p) <= 13)) ? ((p) - 6) : \
|
||||||
|
( ((p) == 50) ? 3 : \
|
||||||
|
( ((p) == 51) ? 2 : \
|
||||||
|
( ((p) == 52) ? 1 : \
|
||||||
|
( ((p) ==53) ? 0 : \
|
||||||
|
( (((p) >= 62) && ((p) <= 69)) ? ((p) - 62) : \
|
||||||
|
0 ) ) ) ) ) )
|
||||||
|
|
||||||
|
#else
|
||||||
|
#error This processor is not supported by SoftwareSerial
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
|
@ -1,17 +1,28 @@
|
||||||
#######################################
|
#######################################
|
||||||
# Syntax Coloring Map For Ultrasound
|
# Syntax Coloring Map for NewSoftSerial
|
||||||
#######################################
|
#######################################
|
||||||
|
|
||||||
#######################################
|
#######################################
|
||||||
# Datatypes (KEYWORD1)
|
# Datatypes (KEYWORD1)
|
||||||
#######################################
|
#######################################
|
||||||
|
|
||||||
SoftwareSerial KEYWORD1
|
NewSoftSerial KEYWORD1
|
||||||
|
|
||||||
#######################################
|
#######################################
|
||||||
# Methods and Functions (KEYWORD2)
|
# Methods and Functions (KEYWORD2)
|
||||||
#######################################
|
#######################################
|
||||||
|
|
||||||
|
begin KEYWORD2
|
||||||
|
end KEYWORD2
|
||||||
|
read KEYWORD2
|
||||||
|
available KEYWORD2
|
||||||
|
is_listening KEYWORD2
|
||||||
|
overflow KEYWORD2
|
||||||
|
library_version KEYWORD2
|
||||||
|
enable_timer0 KEYWORD2
|
||||||
|
flush KEYWORD2
|
||||||
|
listen KEYWORD2
|
||||||
|
|
||||||
#######################################
|
#######################################
|
||||||
# Constants (LITERAL1)
|
# Constants (LITERAL1)
|
||||||
#######################################
|
#######################################
|
||||||
|
|