1
0
mirror of https://github.com/esp8266/Arduino.git synced 2025-06-16 11:21:18 +03:00

Pre-merge upstream Arduino

This commit is contained in:
Cristian Maglie
2012-05-21 01:56:06 +02:00
103 changed files with 60311 additions and 2041 deletions

8
.gitignore vendored Normal file
View File

@ -0,0 +1,8 @@
app/bin/
app/pde.jar
build/macosx/work/
core/bin/
core/core.jar
build/macosx/arduino.xcworkspace/contents.xcworkspacedata
build/macosx/arduino.xcworkspace/xcuserdata/mellis.xcuserdatad/UserInterfaceState.xcuserstate

View File

@ -46,9 +46,9 @@ import static processing.app.I18n._;
* files and images, etc) that comes from that. * files and images, etc) that comes from that.
*/ */
public class Base { public class Base {
public static final int REVISION = 100; public static final int REVISION = 101;
/** This might be replaced by main() if there's a lib/version.txt file. */ /** This might be replaced by main() if there's a lib/version.txt file. */
static String VERSION_NAME = "0100"; static String VERSION_NAME = "0101";
/** Set true if this a proper release rather than a numbered revision. */ /** Set true if this a proper release rather than a numbered revision. */
static public boolean RELEASE = false; static public boolean RELEASE = false;
@ -171,6 +171,9 @@ public class Base {
// run static initialization that grabs all the prefs // run static initialization that grabs all the prefs
Preferences.init(null); Preferences.init(null);
// load the I18n module for internationalization
I18n.init(Preferences.get("editor.languages.current"));
// setup the theme coloring fun // setup the theme coloring fun
Theme.init(); Theme.init();
@ -1535,12 +1538,12 @@ public class Base {
static public String getAvrBasePath() { static public String getAvrBasePath() {
if(Base.isLinux()) { String path = getHardwarePath() + File.separator + "tools" +
return ""; // avr tools are installed system-wide and in the path File.separator + "avr" + File.separator + "bin" + File.separator;
} else { if (Base.isLinux() && !(new File(path)).exists()) {
return getHardwarePath() + File.separator + "tools" + return ""; // use distribution provided avr tools if bundled tools missing
File.separator + "avr" + File.separator + "bin" + File.separator;
} }
return path;
} }

View File

@ -264,7 +264,9 @@ public class Editor extends JFrame implements RunnerListener {
splitPane.setDividerSize(dividerSize); splitPane.setDividerSize(dividerSize);
} }
splitPane.setMinimumSize(new Dimension(600, 400)); // the following changed from 600, 400 for netbooks
// http://code.google.com/p/arduino/issues/detail?id=52
splitPane.setMinimumSize(new Dimension(600, 100));
box.add(splitPane); box.add(splitPane);
// hopefully these are no longer needed w/ swing // hopefully these are no longer needed w/ swing
@ -288,19 +290,9 @@ public class Editor extends JFrame implements RunnerListener {
setPlacement(location); setPlacement(location);
// If the window is resized too small this will resize it again to the // Set the minimum size for the editor window
// minimums. Adapted by Chris Lonnen from comments here: setMinimumSize(new Dimension(Preferences.getInteger("editor.window.width.min"),
// http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4320050 Preferences.getInteger("editor.window.height.min")));
// as a fix for http://dev.processing.org/bugs/show_bug.cgi?id=25
final int minW = Preferences.getInteger("editor.window.width.min");
final int minH = Preferences.getInteger("editor.window.height.min");
addComponentListener(new java.awt.event.ComponentAdapter() {
public void componentResized(ComponentEvent event) {
setSize((getWidth() < minW) ? minW : getWidth(),
(getHeight() < minH) ? minH : getHeight());
}
});
// System.out.println("t3"); // System.out.println("t3");
// Bring back the general options for the editor // Bring back the general options for the editor
@ -1135,7 +1127,11 @@ public class Editor extends JFrame implements RunnerListener {
undoItem.addActionListener(undoAction = new UndoAction()); undoItem.addActionListener(undoAction = new UndoAction());
menu.add(undoItem); menu.add(undoItem);
redoItem = newJMenuItem(_("Redo"), 'Y'); if (!Base.isMacOS()) {
redoItem = newJMenuItem(_("Redo"), 'Y');
} else {
redoItem = newJMenuItemShift(_("Redo"), 'Z');
}
redoItem.addActionListener(redoAction = new RedoAction()); redoItem.addActionListener(redoAction = new RedoAction());
menu.add(redoItem); menu.add(redoItem);
@ -1247,14 +1243,33 @@ public class Editor extends JFrame implements RunnerListener {
item.addActionListener(new ActionListener() { item.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) { public void actionPerformed(ActionEvent e) {
if (find != null) { if (find != null) {
//find.find(true); find.findNext();
//FindReplace find = new FindReplace(Editor.this); //.show();
find.find(true);
} }
} }
}); });
menu.add(item); menu.add(item);
item = newJMenuItemShift(_("Find Previous"), 'G');
item.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
if (find != null) {
find.findPrevious();
}
}
});
menu.add(item);
item = newJMenuItem(_("Use Selection For Find"), 'E');
item.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
if (find == null) {
find = new FindReplace(Editor.this);
}
find.setFindText( getSelectedText() );
}
});
menu.add(item);
return menu; return menu;
} }

View File

@ -122,6 +122,14 @@ public class EditorListener {
} }
} }
if ((event.getModifiers() & KeyEvent.CTRL_MASK) != 0) {
// Consume ctrl-m(carriage return) keypresses
if (code == KeyEvent.VK_M) {
event.consume(); // does nothing
return false;
}
}
if ((event.getModifiers() & KeyEvent.META_MASK) != 0) { if ((event.getModifiers() & KeyEvent.META_MASK) != 0) {
//event.consume(); // does nothing //event.consume(); // does nothing
return false; return false;

View File

@ -46,8 +46,9 @@ import javax.swing.*;
*/ */
public class FindReplace extends JFrame implements ActionListener { public class FindReplace extends JFrame implements ActionListener {
static final int BIG = 13; static final int EDGE = Base.isMacOS() ? 20 : 13;
static final int SMALL = 6; static final int SMALL = 6;
static final int BUTTONGAP = 12; // 12 is correct for Mac, other numbers may be required for other platofrms
Editor editor; Editor editor;
@ -59,14 +60,14 @@ public class FindReplace extends JFrame implements ActionListener {
JButton replaceButton; JButton replaceButton;
JButton replaceAllButton; JButton replaceAllButton;
JButton replaceFindButton; JButton replaceFindButton;
JButton previousButton;
JButton findButton; JButton findButton;
JCheckBox ignoreCaseBox; JCheckBox ignoreCaseBox;
static boolean ignoreCase = true; static boolean ignoreCase = true;
/// true when there's something selected in the editor JCheckBox wrapAroundBox;
boolean found; static boolean wrapAround = true;
public FindReplace(Editor editor) { public FindReplace(Editor editor) {
super("Find"); super("Find");
@ -77,23 +78,66 @@ public class FindReplace extends JFrame implements ActionListener {
pain.setLayout(null); pain.setLayout(null);
JLabel findLabel = new JLabel(_("Find:")); JLabel findLabel = new JLabel(_("Find:"));
Dimension d0 = findLabel.getPreferredSize();
JLabel replaceLabel = new JLabel(_("Replace with:")); JLabel replaceLabel = new JLabel(_("Replace with:"));
Dimension d1 = replaceLabel.getPreferredSize(); Dimension labelDimension = replaceLabel.getPreferredSize();
pain.add(findLabel); pain.add(findLabel);
pain.add(replaceLabel); pain.add(replaceLabel);
pain.add(findField = new JTextField(20)); pain.add(findField = new JTextField(20));
pain.add(replaceField = new JTextField(20)); pain.add(replaceField = new JTextField(20));
Dimension d2 = findField.getPreferredSize(); int fieldHeight = findField.getPreferredSize().height;
if (findString != null) findField.setText(findString); if (findString != null) findField.setText(findString);
if (replaceString != null) replaceField.setText(replaceString); if (replaceString != null) replaceField.setText(replaceString);
//System.out.println("setting find str to " + findString); //System.out.println("setting find str to " + findString);
//findField.requestFocusInWindow(); //findField.requestFocusInWindow();
//pain.setDefault ignoreCaseBox = new JCheckBox(_("Ignore Case"));
ignoreCaseBox.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
ignoreCase = ignoreCaseBox.isSelected();
}
});
ignoreCaseBox.setSelected(ignoreCase);
pain.add(ignoreCaseBox);
wrapAroundBox = new JCheckBox(_("Wrap Around"));
wrapAroundBox.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
wrapAround = wrapAroundBox.isSelected();
}
});
wrapAroundBox.setSelected(wrapAround);
pain.add(wrapAroundBox);
JPanel buttons = new JPanel();
buttons.setLayout(new FlowLayout(FlowLayout.CENTER,BUTTONGAP,0));
// ordering is different on mac versus pc
if (Base.isMacOS()) {
buttons.add(replaceAllButton = new JButton(_("Replace All")));
buttons.add(replaceButton = new JButton(_("Replace")));
buttons.add(replaceFindButton = new JButton(_("Replace & Find")));
buttons.add(previousButton = new JButton(_("Previous")));
buttons.add(findButton = new JButton(_("Find")));
} else {
buttons.add(findButton = new JButton(_("Find")));
buttons.add(previousButton = new JButton(_("Previous"))); // is this the right position for non-Mac?
buttons.add(replaceFindButton = new JButton(_("Replace & Find")));
buttons.add(replaceButton = new JButton(_("Replace")));
buttons.add(replaceAllButton = new JButton(_("Replace All")));
}
pain.add(buttons);
// to fix ugliness.. normally macosx java 1.3 puts an
// ugly white border around this object, so turn it off.
if (Base.isMacOS()) {
buttons.setBorder(null);
}
/* /*
findField.addFocusListener(new FocusListener() { findField.addFocusListener(new FocusListener() {
public void focusGained(FocusEvent e) { public void focusGained(FocusEvent e) {
@ -109,92 +153,74 @@ public class FindReplace extends JFrame implements ActionListener {
}); });
*/ */
// +1 since it's better to tend downwards Dimension buttonsDimension = buttons.getPreferredSize();
int yoff = (1 + d2.height - d1.height) / 2; int visibleButtonWidth = buttonsDimension.width - 2 * BUTTONGAP;
int fieldWidth = visibleButtonWidth - (labelDimension.width + SMALL);
findLabel.setBounds(BIG + (d1.width-d0.width) + yoff, BIG, // +1 since it's better to tend downwards
d1.width, d1.height); int yoff = (1 + fieldHeight - labelDimension.height) / 2;
replaceLabel.setBounds(BIG, BIG + d2.height + SMALL + yoff,
d1.width, d1.height);
//ignoreCase = true; int ypos = EDGE;
ignoreCaseBox = new JCheckBox(_("Ignore Case"));
ignoreCaseBox.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
ignoreCase = ignoreCaseBox.isSelected();
}
});
ignoreCaseBox.setSelected(ignoreCase);
pain.add(ignoreCaseBox);
// int labelWidth = findLabel.getPreferredSize().width;
findLabel.setBounds(EDGE + (labelDimension.width-labelWidth), ypos + yoff, // + yoff was added to the wrong field
labelWidth, labelDimension.height);
findField.setBounds(EDGE + labelDimension.width + SMALL, ypos,
fieldWidth, fieldHeight);
JPanel buttons = new JPanel(); ypos += fieldHeight + SMALL;
buttons.setLayout(new FlowLayout());
// ordering is different on mac versus pc labelWidth = replaceLabel.getPreferredSize().width;
if (Base.isMacOS()) { replaceLabel.setBounds(EDGE + (labelDimension.width-labelWidth), ypos + yoff,
buttons.add(replaceAllButton = new JButton(_("Replace All"))); labelWidth, labelDimension.height);
buttons.add(replaceButton = new JButton(_("Replace"))); replaceField.setBounds(EDGE + labelDimension.width + SMALL, ypos,
buttons.add(replaceFindButton = new JButton(_("Replace & Find"))); fieldWidth, fieldHeight);
buttons.add(findButton = new JButton(_("Find")));
} else { ypos += fieldHeight + SMALL;
buttons.add(findButton = new JButton(_("Find")));
buttons.add(replaceFindButton = new JButton(_("Replace & Find")));
buttons.add(replaceButton = new JButton(_("Replace")));
buttons.add(replaceAllButton = new JButton(_("Replace All")));
}
pain.add(buttons);
// to fix ugliness.. normally macosx java 1.3 puts an ignoreCaseBox.setBounds(EDGE + labelDimension.width + SMALL,
// ugly white border around this object, so turn it off. ypos,
if (Base.isMacOS()) { (fieldWidth-SMALL)/2, fieldHeight);
buttons.setBorder(null);
}
Dimension d3 = buttons.getPreferredSize(); wrapAroundBox.setBounds(EDGE + labelDimension.width + SMALL + (fieldWidth-SMALL)/2 + SMALL,
//buttons.setBounds(BIG, BIG + d2.height*2 + SMALL + BIG, ypos,
buttons.setBounds(BIG, BIG + d2.height*3 + SMALL*2 + BIG, (fieldWidth-SMALL)/2, fieldHeight);
d3.width, d3.height);
// ypos += fieldHeight + SMALL;
findField.setBounds(BIG + d1.width + SMALL, BIG, buttons.setBounds(EDGE-BUTTONGAP, ypos,
d3.width - (d1.width + SMALL), d2.height); buttonsDimension.width, buttonsDimension.height);
replaceField.setBounds(BIG + d1.width + SMALL, BIG + d2.height + SMALL,
d3.width - (d1.width + SMALL), d2.height);
ignoreCaseBox.setBounds(BIG + d1.width + SMALL, ypos += buttonsDimension.height + EDGE;
BIG + d2.height*2 + SMALL*2,
d3.width, d2.height);
// // Dimension screen = Toolkit.getDefaultToolkit().getScreenSize();
int wide = visibleButtonWidth + EDGE*2;
int high = ypos; // butt.y + butt.height + EDGE*2 + SMALL;
pack();
Insets insets = getInsets();
//System.out.println("Insets = " + insets);
setSize(wide + insets.left + insets.right,high + insets.top + insets.bottom);
setLocationRelativeTo( null ); // center
// setBounds((screen.width - wide) / 2, (screen.height - high) / 2, wide, high);
replaceButton.addActionListener(this); replaceButton.addActionListener(this);
replaceAllButton.addActionListener(this); replaceAllButton.addActionListener(this);
replaceFindButton.addActionListener(this); replaceFindButton.addActionListener(this);
findButton.addActionListener(this); findButton.addActionListener(this);
previousButton.addActionListener(this);
// you mustn't replace what you haven't found, my son // you mustn't replace what you haven't found, my son
replaceButton.setEnabled(false); // semantics of replace are "replace the current selection with the replace field"
replaceFindButton.setEnabled(false); // so whether we have found before or not is irrelevent
// replaceButton.setEnabled(false);
// so that typing will go straight to this field // replaceFindButton.setEnabled(false);
//findField.requestFocus();
// make the find button the blinky default // make the find button the blinky default
getRootPane().setDefaultButton(findButton); getRootPane().setDefaultButton(findButton);
Dimension screen = Toolkit.getDefaultToolkit().getScreenSize();
int wide = d3.width + BIG*2;
Rectangle butt = buttons.getBounds(); // how big is your butt?
int high = butt.y + butt.height + BIG*2 + SMALL;
setBounds((screen.width - wide) / 2,
(screen.height - high) / 2, wide, high);
setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE); setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE);
addWindowListener(new WindowAdapter() { addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) { public void windowClosing(WindowEvent e) {
@ -245,11 +271,13 @@ public class FindReplace extends JFrame implements ActionListener {
Object source = e.getSource(); Object source = e.getSource();
if (source == findButton) { if (source == findButton) {
find(true); findNext();
} else if (source == previousButton) {
findPrevious();
} else if (source == replaceFindButton) { } else if (source == replaceFindButton) {
replace(); replaceAndFindNext();
find(true);
} else if (source == replaceButton) { } else if (source == replaceButton) {
replace(); replace();
@ -260,50 +288,54 @@ public class FindReplace extends JFrame implements ActionListener {
} }
// look for the next instance of the find string // look for the next instance of the find string to be found
// to be found later than the current caret selection
// once found, select it (and go to that line) // once found, select it (and go to that line)
public void find(boolean wrap) { private boolean find(boolean wrap,boolean backwards ) {
// in case search len is zero,
// otherwise replace all will go into an infinite loop
found = false;
String search = findField.getText(); String search = findField.getText();
//System.out.println("finding for " + search + " " + findString); //System.out.println("finding for " + search + " " + findString);
// this will catch "find next" being called when no search yet // this will catch "find next" being called when no search yet
if (search.length() == 0) return; if (search.length() == 0) return false;
String text = editor.getText(); String text = editor.getText();
if (ignoreCase) { if (ignoreCase) {
search = search.toLowerCase(); search = search.toLowerCase();
text = text.toLowerCase(); text = text.toLowerCase();
} }
//int selectionStart = editor.textarea.getSelectionStart(); int nextIndex;
int selectionEnd = editor.getSelectionStop(); if (!backwards) {
//int selectionStart = editor.textarea.getSelectionStart();
int selectionEnd = editor.getSelectionStop();
int nextIndex = text.indexOf(search, selectionEnd); nextIndex = text.indexOf(search, selectionEnd);
if (nextIndex == -1) { if (wrap && nextIndex == -1) {
if (wrap) {
// if wrapping, a second chance is ok, start from beginning // if wrapping, a second chance is ok, start from beginning
nextIndex = text.indexOf(search, 0); nextIndex = text.indexOf(search, 0);
} }
} else {
//int selectionStart = editor.textarea.getSelectionStart();
int selectionStart = editor.getSelectionStart()-1;
if (nextIndex == -1) { if ( selectionStart >= 0 ) {
found = false; nextIndex = text.lastIndexOf(search, selectionStart);
replaceButton.setEnabled(false); } else {
replaceFindButton.setEnabled(false); nextIndex = -1;
//Toolkit.getDefaultToolkit().beep(); }
return; if (wrap && nextIndex == -1) {
// if wrapping, a second chance is ok, start from the end
nextIndex = text.lastIndexOf(search);
} }
} }
found = true;
replaceButton.setEnabled(true); if (nextIndex != -1) {
replaceFindButton.setEnabled(true); editor.setSelection(nextIndex, nextIndex + search.length());
editor.setSelection(nextIndex, nextIndex + search.length()); } else {
//Toolkit.getDefaultToolkit().beep();
}
return nextIndex != -1;
} }
@ -312,28 +344,18 @@ public class FindReplace extends JFrame implements ActionListener {
* replacement text field. * replacement text field.
*/ */
public void replace() { public void replace() {
if (!found) return; // don't replace if nothing found
// check to see if the document has wrapped around
// otherwise this will cause an infinite loop
String sel = editor.getSelectedText();
if (sel.equals(replaceField.getText())) {
found = false;
replaceButton.setEnabled(false);
replaceFindButton.setEnabled(false);
return;
}
editor.setSelectedText(replaceField.getText()); editor.setSelectedText(replaceField.getText());
//editor.setSketchModified(true);
//editor.sketch.setCurrentModified(true);
editor.getSketch().setModified(true); // TODO is this necessary? editor.getSketch().setModified(true); // TODO is this necessary?
// don't allow a double replace
replaceButton.setEnabled(false);
replaceFindButton.setEnabled(false);
} }
/**
* Replace the current selection with whatever's in the
* replacement text field, and then find the next match
*/
public void replaceAndFindNext() {
replace();
findNext();
}
/** /**
* Replace everything that matches by doing find and replace * Replace everything that matches by doing find and replace
@ -343,9 +365,35 @@ public class FindReplace extends JFrame implements ActionListener {
// move to the beginning // move to the beginning
editor.setSelection(0, 0); editor.setSelection(0, 0);
do { boolean foundAtLeastOne = false;
find(false); while ( true ) {
replace(); if ( find(false,false) ) {
} while (found); foundAtLeastOne = true;
replace();
} else {
break;
}
}
if ( !foundAtLeastOne ) {
Toolkit.getDefaultToolkit().beep();
}
} }
public void setFindText( String t ) {
findField.setText( t );
findString = t;
}
public void findNext() {
if ( !find( wrapAround, false ) ) {
Toolkit.getDefaultToolkit().beep();
}
}
public void findPrevious() {
if ( !find( wrapAround, true ) ) {
Toolkit.getDefaultToolkit().beep();
}
}
} }

View File

@ -12,11 +12,25 @@
*/ */
package processing.app; package processing.app;
import java.util.*; import java.util.*;
import java.util.Locale.*;
import java.text.MessageFormat; import java.text.MessageFormat;
public class I18n { public class I18n {
// start using current locale but still allow using the dropdown list later
private static ResourceBundle i18n = ResourceBundle.getBundle("processing.app.Resources"); private static ResourceBundle i18n = ResourceBundle.getBundle("processing.app.Resources");
public static Locale locale;
static protected void init (String language) {
// there might be a null pointer exception ... most likely will never happen but the jvm gets mad
try {
if (language == null || language.trim().length() == 0) locale = Locale.getDefault();
else locale = new Locale(language);
i18n = ResourceBundle.getBundle("processing.app.Resources", locale);
} catch (java.lang.NullPointerException e) {
}
}
public static String _(String s) { public static String _(String s) {
try { try {

View File

@ -80,6 +80,51 @@ public class Preferences {
static final String PROMPT_OK = _("OK"); static final String PROMPT_OK = _("OK");
static final String PROMPT_BROWSE = _("Browse"); static final String PROMPT_BROWSE = _("Browse");
String[] languages = {
_("System Default"),
"Català" + " (" + _("Catalan") + ")",
"简体中文" + " (" + _("Chinese Simplified") + ")",
"繁體中文" + " (" + _("Chinese Traditional") + ")",
"Dansk" + " (" + _("Danish") + ")",
"Nederlands" + " (" + _("Dutch") + ")",
"English" + " (" + _("English") + ")",
"Français" + " (" + _("French") + ")",
"Pilipino" + " (" + _("Filipino") + ")",
"Galego" + " (" + _("Galician") + ")",
"Deutsch" + " (" + _("German") + ")",
"ελληνικά" + " (" + _("Greek") + ")",
"Magyar" + " (" + _("Hungarian") + ")",
"Italiano" + " (" + _("Italian") + ")",
"日本語" + " (" + _("Japanese") + ")",
"Latviešu" + " (" + _("Latvian") + ")",
"فارسی" + " (" + _("Persian") + ")",
"Português" + " (" + _("Portuguese") + ")",
"Română" + " (" + _("Romanian") + ")",
"Русский" + " (" + _("Russian") + ")",
"Español" + " (" + _("Spanish") + ")"};
String[] languagesISO = {
"",
"ca",
"zh_cn",
"zh_tw",
"da",
"nl",
"en",
"fr",
"tl",
"gl",
"de",
"el",
"hu",
"it",
"ja",
"lv",
"fa",
"pt_br",
"ro",
"ru",
"es"};
/** /**
* Standardized width for buttons. Mac OS X 10.3 wants 70 as its default, * Standardized width for buttons. Mac OS X 10.3 wants 70 as its default,
* Windows XP needs 66, and my Ubuntu machine needs 80+, so 80 seems proper. * Windows XP needs 66, and my Ubuntu machine needs 80+, so 80 seems proper.
@ -117,6 +162,7 @@ public class Preferences {
JCheckBox exportSeparateBox; JCheckBox exportSeparateBox;
JCheckBox verboseCompilationBox; JCheckBox verboseCompilationBox;
JCheckBox verboseUploadBox; JCheckBox verboseUploadBox;
JCheckBox verifyUploadBox;
JCheckBox externalEditorBox; JCheckBox externalEditorBox;
JCheckBox memoryOverrideBox; JCheckBox memoryOverrideBox;
JTextField memoryField; JTextField memoryField;
@ -124,6 +170,7 @@ public class Preferences {
JTextField fontSizeField; JTextField fontSizeField;
JCheckBox updateExtensionBox; JCheckBox updateExtensionBox;
JCheckBox autoAssociateBox; JCheckBox autoAssociateBox;
JComboBox comboLanguage;
// the calling editor, so updates can be applied // the calling editor, so updates can be applied
@ -278,9 +325,25 @@ public class Preferences {
top += vmax + GUI_BETWEEN; top += vmax + GUI_BETWEEN;
// Preferred language: [ ] (requires restart of Arduino)
Container box = Box.createHorizontalBox();
label = new JLabel(_("Editor language: "));
box.add(label);
comboLanguage = new JComboBox(languages);
comboLanguage.setSelectedIndex((Arrays.asList(languagesISO)).indexOf(Preferences.get("editor.languages.current")));
box.add(comboLanguage);
label = new JLabel(_(" (requires restart of Arduino)"));
box.add(label);
pain.add(box);
d = box.getPreferredSize();
box.setForeground(Color.gray);
box.setBounds(left, top, d.width, d.height);
right = Math.max(right, left + d.width);
top += d.height + GUI_BETWEEN;
// Editor font size [ ] // Editor font size [ ]
Container box = Box.createHorizontalBox(); box = Box.createHorizontalBox();
label = new JLabel(_("Editor font size: ")); label = new JLabel(_("Editor font size: "));
box.add(label); box.add(label);
fontSizeField = new JTextField(4); fontSizeField = new JTextField(4);
@ -309,6 +372,14 @@ public class Preferences {
box.setBounds(left, top, d.width, d.height); box.setBounds(left, top, d.width, d.height);
top += d.height + GUI_BETWEEN; top += d.height + GUI_BETWEEN;
// [ ] Verify code after upload
verifyUploadBox = new JCheckBox(_("Verify code after upload"));
pain.add(verifyUploadBox);
d = verifyUploadBox.getPreferredSize();
verifyUploadBox.setBounds(left, top, d.width + 10, d.height);
right = Math.max(right, left + d.width);
top += d.height + GUI_BETWEEN;
// [ ] Use external editor // [ ] Use external editor
@ -350,7 +421,6 @@ public class Preferences {
top += d.height + GUI_BETWEEN; top += d.height + GUI_BETWEEN;
} }
// More preferences are in the ... // More preferences are in the ...
label = new JLabel(_("More preferences can be edited directly in the file")); label = new JLabel(_("More preferences can be edited directly in the file"));
@ -491,6 +561,7 @@ public class Preferences {
// put each of the settings into the table // put each of the settings into the table
setBoolean("build.verbose", verboseCompilationBox.isSelected()); setBoolean("build.verbose", verboseCompilationBox.isSelected());
setBoolean("upload.verbose", verboseUploadBox.isSelected()); setBoolean("upload.verbose", verboseUploadBox.isSelected());
setBoolean("upload.verify", verifyUploadBox.isSelected());
// setBoolean("sketchbook.closing_last_window_quits", // setBoolean("sketchbook.closing_last_window_quits",
// closingLastQuitsBox.isSelected()); // closingLastQuitsBox.isSelected());
@ -538,6 +609,11 @@ public class Preferences {
setBoolean("editor.update_extension", updateExtensionBox.isSelected()); setBoolean("editor.update_extension", updateExtensionBox.isSelected());
// adds the selected language to the preferences file
Object newItem = comboLanguage.getSelectedItem();
int pos = (Arrays.asList(languages)).indexOf(newItem.toString()); // position in the languages array
set("editor.languages.current",(Arrays.asList(languagesISO)).get(pos));
editor.applyPreferences(); editor.applyPreferences();
} }
@ -548,6 +624,7 @@ public class Preferences {
// set all settings entry boxes to their actual status // set all settings entry boxes to their actual status
verboseCompilationBox.setSelected(getBoolean("build.verbose")); verboseCompilationBox.setSelected(getBoolean("build.verbose"));
verboseUploadBox.setSelected(getBoolean("upload.verbose")); verboseUploadBox.setSelected(getBoolean("upload.verbose"));
verifyUploadBox.setSelected(getBoolean("upload.verify"));
//closingLastQuitsBox. //closingLastQuitsBox.
// setSelected(getBoolean("sketchbook.closing_last_window_quits")); // setSelected(getBoolean("sketchbook.closing_last_window_quits"));

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -834,6 +834,17 @@ public class JEditTextArea extends JComponent
return lineElement.getEndOffset(); return lineElement.getEndOffset();
} }
/**
* Returns the end offset of the specified line, but not past the end of the text
* @param line The line
* @return The end offset of the specified line, safe to use for a selection, or -1 if the line is
* invalid.
*/
public int getSafeLineStopOffset(int line)
{
return Math.min(getLineStopOffset(line),getDocumentLength());
}
/** /**
* Returns the length of the specified line. * Returns the length of the specified line.
* @param line The line * @param line The line
@ -1144,7 +1155,7 @@ public class JEditTextArea extends JComponent
{ {
throw new IllegalArgumentException("Bounds out of" throw new IllegalArgumentException("Bounds out of"
+ " range: " + newStart + "," + + " range: " + newStart + "," +
newEnd); newEnd + " [" + getDocumentLength() + "]");
} }
// If the new position is the same as the old, we don't // If the new position is the same as the old, we don't
@ -1202,6 +1213,86 @@ public class JEditTextArea extends JComponent
} }
} }
private boolean isWordCharacter( char ch, String noWordSep )
{
return Character.isLetterOrDigit(ch) || ch=='_' || noWordSep.indexOf(ch) != -1;
}
protected void setNewSelectionWord( int line, int offset )
{
if (getLineLength(line) == 0) {
newSelectionStart = getLineStartOffset(line);
newSelectionEnd = newSelectionStart;
return;
}
String noWordSep = (String)document.getProperty("noWordSep");
if(noWordSep == null)
noWordSep = "";
String lineText = getLineText(line);
int wordStart = 0;
int wordEnd = lineText.length();
char ch = lineText.charAt(Math.max(0,offset - 1));
// special case for whitespace (fry 0122, bug #348)
// this is really nasty.. turns out that double-clicking any non-letter
// or digit char gets lumped together.. sooo, this quickly gets messy,
// because really it needs to check whether the chars are of the same
// type.. so a double space or double - might be grouped together,
// but what about a +=1? do + and - get grouped but not the 1? blech,
// coming back to this later. it's not a difficult fix, just a
// time-consuming one to track down all the proper cases.
/*
if (ch == ' ') {
//System.out.println("yeehaa");
for(int i = offset - 1; i >= 0; i--) {
if (lineText.charAt(i) == ' ') {
wordStart = i;
} else {
break;
}
}
for(int i = offset; i < lineText.length(); i++) {
if (lineText.charAt(i) == ' ') {
wordEnd = i + 1;
} else {
break;
}
}
} else {
*/
// If the user clicked on a non-letter char,
// we select the surrounding non-letters
boolean selectNoLetter = !isWordCharacter(ch,noWordSep);
for(int i = offset - 1; i >= 0; i--) {
ch = lineText.charAt(i);
if (selectNoLetter ^ !isWordCharacter(ch,noWordSep)) {
wordStart = i + 1;
break;
}
}
for(int i = offset; i < lineText.length(); i++) {
ch = lineText.charAt(i);
if(selectNoLetter ^ !isWordCharacter(ch,noWordSep)) {
wordEnd = i;
break;
}
}
//}
int lineStart = getLineStartOffset(line);
newSelectionStart = lineStart + wordStart;
newSelectionEnd = lineStart + wordEnd;
}
/** /**
* Returns the selected text, or null if no selection is active. * Returns the selected text, or null if no selection is active.
@ -1685,6 +1776,14 @@ public class JEditTextArea extends JComponent
protected int selectionEndLine; protected int selectionEndLine;
protected boolean biasLeft; protected boolean biasLeft;
protected int newSelectionStart; // hack to get around lack of multiple returns in Java
protected int newSelectionEnd;
protected boolean selectWord;
protected boolean selectLine;
protected int selectionAncorStart;
protected int selectionAncorEnd;
protected int bracketPosition; protected int bracketPosition;
protected int bracketLine; protected int bracketLine;
@ -2021,9 +2120,26 @@ public class JEditTextArea extends JComponent
{ {
if (popup != null && popup.isVisible()) return; if (popup != null && popup.isVisible()) return;
setSelectionRectangular((evt.getModifiers() if ( !selectWord && !selectLine ) {
& InputEvent.CTRL_MASK) != 0); setSelectionRectangular((evt.getModifiers()
select(getMarkPosition(),xyToOffset(evt.getX(),evt.getY())); & InputEvent.CTRL_MASK) != 0);
select(getMarkPosition(),xyToOffset(evt.getX(),evt.getY()));
} else {
int line = yToLine(evt.getY());
if ( selectWord ) {
setNewSelectionWord( line, xToOffset(line,evt.getX()) );
} else {
newSelectionStart = getLineStartOffset(line);
newSelectionEnd = getSafeLineStopOffset(line);
}
if ( newSelectionStart < selectionAncorStart ) {
select(newSelectionStart,selectionAncorEnd);
} else if ( newSelectionEnd > selectionAncorEnd ) {
select(selectionAncorStart,newSelectionEnd);
} else {
select(newSelectionStart,newSelectionEnd);
}
}
} }
final Cursor normalCursor = new Cursor(Cursor.DEFAULT_CURSOR); final Cursor normalCursor = new Cursor(Cursor.DEFAULT_CURSOR);
@ -2094,6 +2210,9 @@ public class JEditTextArea extends JComponent
int offset = xToOffset(line,evt.getX()); int offset = xToOffset(line,evt.getX());
int dot = getLineStartOffset(line) + offset; int dot = getLineStartOffset(line) + offset;
selectLine = false;
selectWord = false;
switch(evt.getClickCount()) { switch(evt.getClickCount()) {
case 1: case 1:
@ -2159,74 +2278,11 @@ public class JEditTextArea extends JComponent
bl.printStackTrace(); bl.printStackTrace();
} }
String noWordSep = (String)document.getProperty("noWordSep"); setNewSelectionWord( line, offset );
if(noWordSep == null) select(newSelectionStart,newSelectionEnd);
noWordSep = ""; selectWord = true;
selectionAncorStart = selectionStart;
// Ok, it's not a bracket... select the word selectionAncorEnd = selectionEnd;
String lineText = getLineText(line);
int wordStart = 0;
int wordEnd = lineText.length();
char ch = lineText.charAt(Math.max(0,offset - 1));
// special case for whitespace (fry 0122, bug #348)
// this is really nasty.. turns out that double-clicking any non-letter
// or digit char gets lumped together.. sooo, this quickly gets messy,
// because really it needs to check whether the chars are of the same
// type.. so a double space or double - might be grouped together,
// but what about a +=1? do + and - get grouped but not the 1? blech,
// coming back to this later. it's not a difficult fix, just a
// time-consuming one to track down all the proper cases.
/*
if (ch == ' ') {
//System.out.println("yeehaa");
for(int i = offset - 1; i >= 0; i--) {
if (lineText.charAt(i) == ' ') {
wordStart = i;
} else {
break;
}
}
for(int i = offset; i < lineText.length(); i++) {
if (lineText.charAt(i) == ' ') {
wordEnd = i + 1;
} else {
break;
}
}
} else {
*/
// If the user clicked on a non-letter char,
// we select the surrounding non-letters
boolean selectNoLetter = (!Character.isLetterOrDigit(ch)
&& noWordSep.indexOf(ch) == -1);
for(int i = offset - 1; i >= 0; i--) {
ch = lineText.charAt(i);
if (selectNoLetter ^ (!Character.isLetterOrDigit(ch) &&
noWordSep.indexOf(ch) == -1)) {
wordStart = i + 1;
break;
}
}
for(int i = offset; i < lineText.length(); i++) {
ch = lineText.charAt(i);
if(selectNoLetter ^ (!Character.isLetterOrDigit(ch) &&
noWordSep.indexOf(ch) == -1)) {
wordEnd = i;
break;
}
}
//}
int lineStart = getLineStartOffset(line);
select(lineStart + wordStart,lineStart + wordEnd);
/* /*
String lineText = getLineText(line); String lineText = getLineText(line);
@ -2242,7 +2298,10 @@ public class JEditTextArea extends JComponent
private void doTripleClick(MouseEvent evt, int line, private void doTripleClick(MouseEvent evt, int line,
int offset, int dot) int offset, int dot)
{ {
select(getLineStartOffset(line),getLineStopOffset(line)-1); selectLine = true;
select(getLineStartOffset(line),getSafeLineStopOffset(line));
selectionAncorStart = selectionStart;
selectionAncorEnd = selectionEnd;
} }
} }

View File

@ -515,7 +515,10 @@ implements TabExpander, Printable
*/ */
public Dimension getMinimumSize() public Dimension getMinimumSize()
{ {
return getPreferredSize(); Dimension dim = new Dimension();
dim.width = fm.charWidth('w') * 10;
dim.height = fm.getHeight() * 4;
return dim;
} }
// package-private members // package-private members

View File

@ -8,6 +8,7 @@
<condition property="macosx"><os family="mac" /></condition> <condition property="macosx"><os family="mac" /></condition>
<condition property="windows"><os family="windows" /></condition> <condition property="windows"><os family="windows" /></condition>
<condition property="linux"><os family="unix" /></condition> <condition property="linux"><os family="unix" /></condition>
<condition property="linux32"><os family="unix" arch="i386" /></condition>
<condition property="linux64"><os family="unix" arch="amd64" /></condition> <condition property="linux64"><os family="unix" arch="amd64" /></condition>
<condition property="platform" <condition property="platform"
@ -15,7 +16,7 @@
<condition property="platform" <condition property="platform"
value="windows"><os family="windows" /></condition> value="windows"><os family="windows" /></condition>
<condition property="platform" <condition property="platform"
value="linux"><os family="unix" arch="i386" /></condition> value="linux32"><os family="unix" arch="i386" /></condition>
<condition property="platform" <condition property="platform"
value="linux64"><os family="unix" arch="amd64" /></condition> value="linux64"><os family="unix" arch="amd64" /></condition>
@ -388,6 +389,9 @@
<param name="target.path" value="linux/work" /> <param name="target.path" value="linux/work" />
</antcall> </antcall>
<copy todir="linux/work" file="linux/dist/arduino" />
<chmod perm="755" file="linux/work/arduino" />
<copy todir="linux/work/hardware"> <copy todir="linux/work/hardware">
<fileset dir="linux/dist" includes="tools/**" /> <fileset dir="linux/dist" includes="tools/**" />
</copy> </copy>
@ -402,12 +406,28 @@
<antcall target="linux-unzip-arm-toolchain" /> <antcall target="linux-unzip-arm-toolchain" />
</target> </target>
<target name="linux32-build" depends="linux-build" description="Build linux (32-bit) version">
<!-- Unzip AVR tools -->
<exec executable="tar" dir="linux/work/hardware">
<arg value="-xjf"/>
<arg value="../../avr_tools_linux32.tar.bz2"/>
</exec>
</target>
<target name="linux64-build" depends="linux-build" description="Build linux (64-bit) version"> <target name="linux64-build" depends="linux-build" description="Build linux (64-bit) version">
<copy tofile="linux/work/hardware/tools/avrdude" file="linux/dist/tools/avrdude64" overwrite="true" /> <copy tofile="linux/work/hardware/tools/avrdude" file="linux/dist/tools/avrdude64" overwrite="true" />
<copy tofile="linux/work/lib/librxtxSerial.so" file="linux/dist/lib/librxtxSerial64.so" overwrite="true" /> <copy tofile="linux/work/lib/librxtxSerial.so" file="linux/dist/lib/librxtxSerial64.so" overwrite="true" />
<chmod perm="755" file="linux/work/hardware/tools/avrdude" />
<!-- Unzip AVR tools -->
<exec executable="tar" dir="linux/work/hardware">
<arg value="-xjf"/>
<arg value="../../avr_tools_linux64.tar.bz2"/>
</exec>
</target> </target>
<target name="linux-run" depends="linux-build" <target name="linux32-run" depends="linux32-build"
description="Run Linux (32-bit) version"> description="Run Linux (32-bit) version">
<exec executable="./linux/work/arduino" spawn="false"/> <exec executable="./linux/work/arduino" spawn="false"/>
</target> </target>
@ -475,7 +495,7 @@
<!-- <!--
<tar compression="gzip" basedir="linux/work" <tar compression="gzip" basedir="linux/work"
destfile="linux/arduino-${version}.tgz" /> destfile="linux/arduino-${version}.tgz" />
-->
<tar compression="gzip" destfile="linux/arduino-${version}-linux.tgz"> <tar compression="gzip" destfile="linux/arduino-${version}-linux.tgz">
<tarfileset dir="linux/work" <tarfileset dir="linux/work"
prefix="arduino-${version}" prefix="arduino-${version}"
@ -487,6 +507,18 @@
<tarfileset file="linux/work/hardware/tools/avrdude" filemode="755" <tarfileset file="linux/work/hardware/tools/avrdude" filemode="755"
prefix="arduino-${version}/hardware/tools" /> prefix="arduino-${version}/hardware/tools" />
</tar> </tar>
-->
<move file="linux/work" tofile="linux/arduino-${version}" />
<exec executable="tar" dir="linux">
<arg value="-z"/>
<arg value="-c"/>
<arg value="-f"/>
<arg value="arduino-${version}-linux.tgz"/>
<arg value="arduino-${version}"/>
</exec>
<move file="linux/arduino-${version}" tofile="linux/work" />
<echo> <echo>
======================================================= =======================================================
@ -497,6 +529,8 @@
</echo> </echo>
</target> </target>
<target name="linux32-dist" depends="linux-dist"
description="Build .tar.gz of linux version" />
<target name="linux64-dist" depends="linux-dist" <target name="linux64-dist" depends="linux-dist"
description="Build .tar.gz of linux version" /> description="Build .tar.gz of linux version" />
@ -683,6 +717,7 @@
<tarfileset dir="../" <tarfileset dir="../"
prefix="arduino-${version}" prefix="arduino-${version}"
excludes="**/*.tgz, excludes="**/*.tgz,
**/*.bz2,
**/macosx/, **/macosx/,
**/windows/, **/windows/,
**/work/, **/work/,

Binary file not shown.

Binary file not shown.

View File

@ -1,15 +1,21 @@
/* /*
AnalogReadSerial AnalogReadSerial
Reads an analog input on pin 0, prints the result to the serial monitor Reads an analog input on pin 0, prints the result to the serial monitor.
Attach the center pin of a potentiometer to pin A0, and the outside pins to +5V and ground.
This example code is in the public domain. This example code is in the public domain.
*/ */
// the setup routine runs once when you press reset:
void setup() { void setup() {
// initialize serial communication at 9600 bits per second:
Serial.begin(9600); Serial.begin(9600);
} }
// the loop routine runs over and over again forever:
void loop() { void loop() {
// read the input on analog pin 0:
int sensorValue = analogRead(A0); int sensorValue = analogRead(A0);
// print out the value you read:
Serial.println(sensorValue); Serial.println(sensorValue);
} }

View File

@ -5,15 +5,20 @@
This example code is in the public domain. This example code is in the public domain.
*/ */
// Pin 13 has an LED connected on most Arduino boards.
// give it a name:
int led = 13;
// the setup routine runs once when you press reset:
void setup() { void setup() {
// initialize the digital pin as an output. // initialize the digital pin as an output.
// Pin 13 has an LED connected on most Arduino boards: pinMode(led, OUTPUT);
pinMode(13, OUTPUT);
} }
// the loop routine runs over and over again forever:
void loop() { void loop() {
digitalWrite(13, HIGH); // set the LED on digitalWrite(led, HIGH); // turn the LED on (HIGH is the voltage level)
delay(1000); // wait for a second delay(1000); // wait for a second
digitalWrite(13, LOW); // set the LED off digitalWrite(led, LOW); // turn the LED off by making the voltage LOW
delay(1000); // wait for a second delay(1000); // wait for a second
} }

View File

@ -5,14 +5,23 @@
This example code is in the public domain. This example code is in the public domain.
*/ */
// digital pin 2 has a pushbutton attached to it. Give it a name:
int pushButton = 2;
// the setup routine runs once when you press reset:
void setup() { void setup() {
// initialize serial communication at 9600 bits per second:
Serial.begin(9600); Serial.begin(9600);
pinMode(2, INPUT); // make the pushbutton's pin an input:
pinMode(pushButton, INPUT);
} }
// the loop routine runs over and over again forever:
void loop() { void loop() {
int sensorValue = digitalRead(2); // read the input pin:
Serial.println(sensorValue); int buttonState = digitalRead(pushButton);
// print out the state of the button:
Serial.println(buttonState);
} }

View File

@ -5,19 +5,22 @@
using the analogWrite() function. using the analogWrite() function.
This example code is in the public domain. This example code is in the public domain.
*/ */
int led = 9; // the pin that the LED is attached to
int brightness = 0; // how bright the LED is int brightness = 0; // how bright the LED is
int fadeAmount = 5; // how many points to fade the LED by int fadeAmount = 5; // how many points to fade the LED by
// the setup routine runs once when you press reset:
void setup() { void setup() {
// declare pin 9 to be an output: // declare pin 9 to be an output:
pinMode(9, OUTPUT); pinMode(led, OUTPUT);
} }
// the loop routine runs over and over again forever:
void loop() { void loop() {
// set the brightness of pin 9: // set the brightness of pin 9:
analogWrite(9, brightness); analogWrite(led, brightness);
// change the brightness for next time through the loop: // change the brightness for next time through the loop:
brightness = brightness + fadeAmount; brightness = brightness + fadeAmount;
@ -29,3 +32,4 @@ void loop() {
// wait for 30 milliseconds to see the dimming effect // wait for 30 milliseconds to see the dimming effect
delay(30); delay(30);
} }

View File

@ -0,0 +1,23 @@
/*
ReadAnalogVoltage
Reads an analog input on pin 0, converts it to voltage, and prints the result to the serial monitor.
Attach the center pin of a potentiometer to pin A0, and the outside pins to +5V and ground.
This example code is in the public domain.
*/
// the setup routine runs once when you press reset:
void setup() {
// initialize serial communication at 9600 bits per second:
Serial.begin(9600);
}
// the loop routine runs over and over again forever:
void loop() {
// read the input on analog pin 0:
int sensorValue = analogRead(A0);
// Convert the analog reading (which goes from 0 - 1023) to a voltage (0 - 5V):
float voltage = sensorValue * (5.0 / 1023.0);
// print out the value you read:
Serial.println(voltage);
}

View File

@ -0,0 +1,52 @@
/*
Input Pullup Serial
This example demonstrates the use of pinMode(INPUT_PULLUP). It reads a
digital input on pin 2 and prints the results to the serial monitor.
The circuit:
* Momentary switch attached from pin 2 to ground
* Built-in LED on pin 13
Unlike pinMode(INPUT), there is no pull-down resistor necessary. An internal
20K-ohm resistor is pulled to 5V. This configuration causes the input to
read HIGH when the switch is open, and LOW when it is closed.
created 14 March 2012
by Scott Fitzgerald
http://www.arduino.cc/en/Tutorial/InputPullupSerial
This example code is in the public domain
*/
void setup(){
//start serial connection
Serial.begin(9600);
//configure pin2 as an input and enable the internal pull-up resistor
pinMode(2, INPUT_PULLUP);
pinMode(13, OUTPUT);
}
void loop(){
//read the pushbutton value into a variable
int sensorVal = digitalRead(2);
//print out the value of the pushbutton
Serial.println(sensorVal);
// Keep in mind the pullup means the pushbutton's
// logic is inverted. It goes HIGH when it's open,
// and LOW when it's pressed. Turn on pin 13 when the
// button's pressed, and off when it's not:
if (sensorVal == HIGH) {
digitalWrite(13, LOW);
}
else {
digitalWrite(13, HIGH);
}
}

View File

@ -15,7 +15,7 @@
Created 26 Sept. 2005 Created 26 Sept. 2005
by Tom Igoe by Tom Igoe
modified 30 Aug 2011 modified 24 April 2012
by Tom Igoe and Scott Fitzgerald by Tom Igoe and Scott Fitzgerald
This example code is in the public domain. This example code is in the public domain.
@ -147,65 +147,95 @@ void serialEvent(Serial myPort) {
Max/MSP version 5 patch to run with this example: Max/MSP version 5 patch to run with this example:
----------begin_max5_patcher---------- ----------begin_max5_patcher----------
2569.3oc2as0jiZqD9YO+Jzw09PRc75BIAX671TaUop8gy4gLoNmG1YqsjAY 3908.3oc6ckziiaiE9b0+J3XjCIXpp.WzZNMURv.jCInQ5fYNjNngrDssRKK
rxhAGPLW1T4+dZIAd.aCFeiEuYqXFABQqu9qa0Rp0ec2fgyiegmND8KnOgFL 4nkp6JA4+973hrkrsjncKu0SRiXasQ83G+dKj7QV+4qtaxzrOxKlf9Zzuft6
3utav.8sT2XPd4ACWwdwKjkpq1vU7zTV.e3Hyyj7Wj5665Tbq3LYHWJecM2z t+7U2cm7ThSbm936lrL3igIAExaaRJ+CYS+sI2qtTI+ikxSuBMKNojm+N3D4
tCGh9b9iVyjdKEQAeIg6IMOkRmM1ZDx10UcgRF6LBgmN1Zy6H70se77+38yJ Aua5KkPwpuoUAkgKhSm+tbdXo5cQXVOhuGwrohuHD4WT7iXzupen3HY4BuqG
9DKhijQrU5Ovv6SDrvhmDksRDAedsvRJU8Tw2zUGSfuyl5ZjUckwpa922cm5 rH0kzrrzxzfkb4kdJONHo9JoUKiSS3kRgjt4jYUk0mkznPJh+CYgHewpSqty
mQsDLh3OCx0NXQJODgqENlyhBFNpkvBchFVzfCwZ+vh60DVHm.r3EuZEORtC xWVwUh3jIqkEYEfmqQEMr.ETbB+YddQbVZix+tIAqV03z203QDX4ukIKHm6W
t7.WISnOvBCe+uwSWGGkxQnGidL5AdjeJhgl+pjifuNRtjiRMUecbhbDhE4i ep3T0ovqOUN+435m2Rcx+5U0E+FTzVBh9xOsHXIh5YuADg1x4IYgumG0r3mj
R3LnVTcsRQhnwHzCfXhVDmvChyfZ3EGFmLB8x53Tyq7J7Wn3EPS6IR7B4nrT shmFmtJmWvSKCJ0um0WNhOKnJo7c6GmZe8YAg7Ne381Rc2j44wQYoBgn0SJN
.n0M+SrvLnYR3xrjHtOZQR7ps+tiMh2+MVx+EzuuTjhz5JDzSy.KAn5Lir5y c8qCHH1RhQqJi7NRCVsmGt.pGUESCxE31zDdCV.PRyxRZeo0MU.WOHMdYPIu
eR3AhdjtTL7SBB5SpO8VMIBZjfXsPDC2GpCCojIP1L89EFIC45f9o6e3Ce7i LVIrT75BMd4p73zxVuHdZ.TFKJByyRRZUTpq77dtRDzZFx+PbT4BYY0DJgaO
n6+YUCmJYIxr0iA4.ZvuxUxwyLgo+ajDUCLR8AizsLfnQn7l.8LbW9SfXIjv dUcSvj0XTT7bdQY6yUFLun8YZo71jl0TIt042RYNLa4RfCTWfsznKWDWfJpl
qAZdzJ.1P9LIartS5AvqDvArM590I.ayZ1iQyeE8fWrTh9Ug7aA7DVnuFW+c tJHrbgV6t.AZInfzWP.4INpJHA8za91u+6QN1nk7hh.PpQwonxEbTAWzpilV
.q9XP7F+.ghHtGnBzJZLtdhsskshK6PLV85BXmZL3cNRlM9XX1VWPlsLQD.n MimilkmsDtPbo3TPiUdY0pGa9ZShS4gYUJz1pwE1iwCpxbAgJI9DGGwWNzFT
C5m.Mwmje9mUpDOE4RDrT99P9BIPMidBdUAP5AV08ggFdSB6YEWPgoqShg2Q ksLf3z7M0MybG6Hj1WngsD7VEXS8j5q7Wu5U0+39ir8QJJS5GMHdtRimL4m1
yOeV.OeIa8ZPSNmq32n+C6Efq9m.kETcfimb96Xz+WotkJtYgTrPjvA9Onn2 0e1EVX0YsE2YssINriYRoFRyWVMoRRUGQvnkmms3pnXDYHbBKMPpIOL5i1s8
gE.bNV5WQ2m3mIhh0LmRs0d0lz5UlDiWJGKGs1jXtTixz8lQalvEQBIHVvGM 3rMPwFcRCsGRyPH780.8HBnpWz.vlEQBWJ+0CSunehJSmJxiIZRtNGhhDYrU
UqlBXJONOqQZi2BvfjosuWrWPiTOngmXo8oatfoZPiZWCnYeq.ZdK4desvWD jt3ZQyA2fHJhZDifXIQHUHH8oGYgOREI5nqHIzhFWUndPyBdB3VzHJGwUhkV
GXYdBQtmLvk1iCu+wgJ12bdfHBLF.QNyioLGTVCKjJGSFPW8vUYQBySUtKWw rgvRl2UCVNMHcd234lf1DN16HFEIdHt99A5hrp7v5WWMSBQZgMP.Tkwoqig8
70t0f+bdXr2WQoKy.i.+3miNZJqsqA8czvNgRajxR6aneMQbrF.XkqDMzaFo W1.Sn1f3h3nn1wLpBypPDzlJ7XinEGkLiMPloWOhrgR7dpZWJQV1faDy35Qj
6wgmV.YDrNjCWaC.4psvwypAfH6Ef9e7DeVDauPDcePjUcAkUVN4I4.SNx.s MThMFkWFGsJChQPqrQp8iorV6Q28HBVF4nMVDJj7f1xyYACFScisg.ruLHOW
gHTMjVJvSJU6ACeq23nGfYlsoKYYT1khiBv6.Ekhq6SVE2zmu3XZiXvO8a0W uMUS4Am4pI4PTnHi.6bi02HNzSYnDBe4cgAgKzRk1jc8PJLoH3Ydz6.Q.7K8
WiJ+Tslhn0f+YvFRSv296xxBkeY+fS0muf4wq8kqQULXXPhvONRIFUdW0sK9 tfxx73oUkJq1MGuCy5TpAi.POWZ3AenidLOOIaZPhdjZVW3sdk6LXEGzHb7p
f.Gvn6cJK45ZDwVumWVFGGNmk7jHULOjWQS.rYVjXE39TJLRDDWQwCEqVmHL Mfr7SEy3SXHyBSxJ3J2ncNNYVJsXG6Me10nj4cfCRFdTFjLo7q3SiCpjjEDM
VratGOhAswxTuj3vvJMk4IOsmmXB95YgubotsdCupL8lRLmJ1YUteiS2opQ2 .nvra.GN39.E2CDTHWXPo8.xzfqrHCHKnf5QUYUVdoZPUjCSC7LU8.XtTUXl
hjf4.H4T7+kqT81b0Fw+DGSrPZRyro5Bk7Kssom8jxeuZ8OUa3+6ZDhG6LyA X8vr51GjwFGLC2AlMdLkU4RiaRrnmJuiudnDk0ZW+9p6TuKBe433JUCzp6fU
OcR0Wb6oHMnvok4OFcs.VK0+NOHkjCoF5ryrCBot2zPZkwF1cFoJVZy.ZwLS iOF0SUk2UQYUPNTEkiZubvKa1tsmgL5SCTXGHnnG0CceLpkpR9Rs28IUESWl
2YFp0xYsLwvXtXlBOA2..6TK.ukep5FYsgQW2C5R6FzcMChIw5RvXMF+4DV7 EwWNKfHlg.zj6Ee7S+nE8A+m9F7Cu40u9gMm+aRp3kYYkKd3GDOz5y+c7b96
TqCBnzSFPsOE.sinq+afR0HPpG03PV+UHm1GFKImLVR9QGKycj1ZnDe6BkMM K9gfvuIK68uNO6g2vUUL80WxihCVFD9vlB30e2SOrmxUb527RZ3nZNrljGrR
vDDVMKYDZMCvrXXtMn2gQuifdGE8N6KhgewExAGpx5ldnJs7b1rRmIpUKNmN 70vs1J9suWuZ3zaHVdG3RIJLgGj2Gfn6TcGcstEfvtH.hpFLlnBndjOLGQAI
taHqauXRSqETZfYU5IEy7U0fC6cfAlT137vnwrenQCp0QgFtV8Tzv74FdfQ5 z98BXc6yQxghmOn6gZqj0ShPOXhynLOjzCESt+XwE8TxrCvrdXo16rqnLgvb
HSGSg+y1dj9uaWWF2pXs1ZIKNht7aScTs1L0LKLcuQ878iEowYIdE58h.dPU HaFmbh29QD+K0DyNdjDwvzQL.NXpoMvoOBxkger0HwMRQbpbCh91fjjG9Idw
6S97ToHZybo+zaNH2phKE99Um4pFtE9qiAJUt.h9bqzdGsb6zV41s+I231H2 prTH9SzaSea5a.GQEPnnh43WNefMlsOgx18n.vgUNO.tKl7tDyI3iHzafJHZ
S5WxMts3shPQ5OxM4XjaZuQtUCt1d415FTtw8K4d1wf23aP4lzqvaWq1J2N8 VVNedVEbGgYIY42i93prB0i7B7KT1LnnCiyAiinpBnsPV7OG.tYKfBsrJOkG
K+fsUtc6W768LL3sgbO46gbmeSnCX1tjT1Sb+u.eFHDwuvjxDw7LoIDrxaex UG5aq26iJw6GyJ4eM5mEgEKaNQPMEBUp.t8.krplOVTlZdJAW27bjvGK7p2p
4uaBM9vCsYFAgwyYg4asylVoRauiTscac2aHwkYmzrpcWyJOsi8NkCb995N8 HQPgLOSJDYv4E9gQBYBjMUselRxDy+4WplIzm9JQAWOEmfb.E364B43CAwp5
sLYptT1wYxMRpL8udeCYxzAQjolDBf51BDw4FAQToB.LfJ9DS2MCjju8ylcV uRRDEv8hWXprjADMUOYpOg9.bVQpEfhKgGCnAnk.rghBJCdTVICA3sDvAhE5
rVHwtuAIx3ffP9YyGLoKhY8JpsySabC1u1pWqSS8hM6RrcqTuV2PoyXCo2Y6 oU4hf67ea5zWPuILqrD8uiK+i477fjHIt9y.V88yy3uMsZUj7wnxGKNAdPx5
xmwbduYKMroMAL1S6aIzXnmesc+PQpT08KtpLBF0xbrXV9pz3t4x9vC5rivT fAZMErDZOcJU4M01WFQokix.pKa+JE1WacmnKFeYd7b.0PeIzB8Kk+5WIZpB
v9xo2kpTPLrQq8Qsydvwjze1js23fJcSmiNWRveuxj0mXga7OsuEl1jTWtlt Ejt34KJeHgOCh4HK8Y3QiAkAfs8TRhhOkG7AAGQf0qxyfmQxa+PLb8Ex.2PS
sIGdqqaiut85SJIixVMmmbHEu1tuIkus6jRnfiaiJ+aJcOoAcusILPWyfbGP 4BdO5GB9Hvg+cfJCMofAIMu9Qz+UPCjckqVJlEmyA8Bf.rC6.3hAEuG8TdTU
2Os+o7anaianaSlRZc2lX8CKmmZWFFZlySH8OR+EBFJFfKGFbZDF5g190LhX bZljQ0nr1ayIqmTwQYfyRGafZhur5vfuyMSqYNWmtAPwWHalDSuUgT0Bosh.
Vzao5wgvnRWZAR4XxF37zsrVnZ10EpnWNn5agnfj3r0HZ8QR2xnGrMAMNA23 JpAR89Y6Ez5QEfPTQO4J0DHLInIliz8BZV2JfV3Bd36qsQwAVVXbr1BGXp6s
.HG+3njuSrHHdZnKBbnCeFgZWr0XSbU4YgEooXqoVWyLZldIym7PAXpsjmvU Sd5sSDruo74wofx.HxUgxQwTnMLqTXvRmiGh2PUZr5pBynKChjl6feNUjSRn
oMtWXbJe6iRSCCGQMo4MYlgzX03Anh3dyjj8U.EUh3dLXxz7T51oMXxj9FlT hEUfRPT1GfG9Ik4TQBm.hEZZ.bc38HjAMKGzDRijEm1ifx1dbgzQyKh6FZc3
2IOTSMNwUiI2xwvRn6jfnU.Dbea550AH5SYF6TONl1k3H13lPDbu67XVmYyG wOCkRJH+KUh0daWs6wzltWx1puXxlWW6NZWY2JiTBzzILRIANku02NourySM
pX1DvA3Aolut5joTx1Isov5yWzJCIgXMoQim9lsyYtvcDhwzHOPNRwu6kUf+ VI1VJTvQZff32AJr+dS9e34QAoA6EGXlGFH9yk7yyQAlVd3SR94g+TxOu1sU
9rvc+4JtLI9sjcrlAUaQ2rXfTmlTwXxMi6.8Yr3z7FjuBlFRuYY7q0a.8lY4 Flgd6ICI96LzazyPu1cgqsZ8r74SgF.65+efbMf4pGHT7lgHh30Sha3N5Ia.
L0F7LzLWKqyZ0sx4KTrloLswU6EeUOHeWx02323L+Buhhn0YRz7rEKTmm4m3 oqjMf7nsuMwycf7iYDybiAAVr3eC.oTMjpzEr8GDRc9bFRGHYXDrzg.Tlx+q
IuBFXnUhPv6I2KNxO8nO8iTy4IKeo.sZ5vOhuYNwnlAXTGna0gztokIwrj.X NW8TY1IkzCfZ2IftkQstbB08HUezoDS+oFyI.cWIhWBaDiUo7qIrDO7f.L6n
WCLfabXDbmECl9qWMO8Lvw16+cNnry9dWIsNpYKuUl.kpzNa2892p6czPsUj AXqCmyNT9act.z+Iv.GR0uES0ZXfjdz.IczAxQOUR+zvRsUTigRxmyPYeNlj
bnsPlbONQhByHUkxwTr5B0d5lRmov51BYcVmBeTbKDIpS2JSUxFwZjIxrtWl yXv8Peef2ZFzuLzWPPeAE8ELzWXYlhe8WzAcUg+b1UkIoCLzIH60zwASGXau
tzTehEUwrbLqlH1rP5UKkmgyDplCpKctFLSZQOYKqpCawfmYRR+7oXYuoz4h a1Dq2nUY.sox4vng+m0nACePngC9lEMLZMBPodOxf+yx5d4uMCTHm3kJvIIG
6VsQZmzstbZCWvw9z74XN+h1NlSrdkRTmxnqtTW37zoas9IsxgNoakIRakIb jcLMedEQldkjpoBkQyjY1Hk.hmSY95Iwos8NDb9VSlIWOIntqgxryUjL6bCJ
24QpshDoyDI21.Szt0w8V1g0jNmS6TYBa2VGHGAcpXHByvG1jYaJ0INIrNM2 y1lli5tWWxrQ7YmqGYlc6shK1iY2dr0wtNjYxgHyzaq0OznY235awCr8zSz6
cj7kmjtozYJsaoJuLCuctHXaFDaqHw5GbPqN0klNltCF3WG65uMy4gP6dYhb EGd1QNUKf.74dADTBbTbeotjpW95IolY0WpKYONY8M83Rx2MChx3fL+iG5Mm
H9T2RmZ07HNRmD4tzv4KbOAuozkHpxCQzvc7LLZiSBR25jffuBy5IWORw5KE tXpdmvXj8uTvaAL1WjbbarQD4Z6kXBpnm6a69oKV2PY9WY174IbC3CaRQ9iK
CagO+YWiuFKOA0VOzDY5zRRqtz4Jszqgz5ZjVWqxRqpTWXei6VWyXx0d4nfB Q4sYGQpwdtZ5wFrc7n569.M83OOR5ydSB1ZcAWCxdbKuavz9LILxfD.wWO.W
+8c+C81VE7B Nq+Zu4Es+AP6s5p9jDWH8ET+c85+XbW0.N1nDCTD7U4DGc6ohnU019fS7kQ0
o43luuOGjv5agHp0DT.CysOfgLR3xXlXTUKm16RivRsn3z0O6cl3YScAvtrb
hwekGB7BZuqESUzBJWmCvK7t9HF8Ts6cUAPoFWso3aP8ApWyJ3wqOPo2pJDC
BQ0NI0Pj8QCQ2r1L5vKaU5lDRYX7yRur1UYYZmJQ9iDHwN9dndB5n5ejflmm
UsBwLHnDkKXWRuAkb3NeuzqRstiQGP.fCQFdHNzaE.8u58Nz9svFE9SGIE1X
kv9Iwfl1BdNWjA7xcThsWCS847loyFD8pZq2E2F04lYULzBTDYhrFSDDJdjo
fisN2NUN26e4xRu51zD5ZseJ4HC63WyIX6jRqsp0jangBnK.Qlo58PCpWevt
ahzqK7fbKsdX6R64aao8LmWhBPh9jKVAPMzb5a2cV6opdWHneMmqMEmAGsPh
ieigIjV+4gF1GgbMNXg+NH44YaRYyd..S1ThHzKhFwwGRaWVITqyj9FvPqMT
d0pDuSqDrOGF.Uogf.juCFi9WAUkYR+rFPanDcPG8SbrtjyG03ZQ8m3AqC5H
NcUUoXSwVrqXKVcZu.5ZnkwIfIVdXVZTwAuTTUiYuxwjZDK6ZgnRtYV8tJmP
hEcuXgz2Goxyaiw35UkaWbpqtfzD02oUkkYqi.YQbZqIIWrIljFolsdmMKFR
wCJ2+DTn.9QlkOld+d9Qy9IJdpLfy05Ik2b8GsG9h8rdm1ZFx1FrmmlA2snw
qI9Mcdi2nr6q3Gc87nLawurbw1dda+tMyGJ9HaQmlkGwy6davisMgrkM65oz
eulfYCzG46am8tSDK144xV4cEvVMTRXq9CIX8+ALNWb6sttKNkiZetnbz+lx
cQnb1Nds2C0tvLNe14hwQtxYbxhqc17qHfamUcZZ3NYSWqjJuiDoizZ+ud2j
naRK4k3346IIVdR1kKiQjM39adMamvc6n+Xp36Yf3SIGh3uKbquqs1JksTII
kuJ7RrZSFb2Cn9j5a6DT8cMo0iczU+lsYaU8YNVh5k5uzJLU26ZcfuJE6XLY
0mcRp9NTCp+L+Ap+in7Xf3b9jFQBLtIY06PbrGhcrU6N00Qlaf9N0+QPo9nS
P6qsI7aYNLSNOHpsAxis0ggnZLjYqyyFkdSqinVsPaqSDZaYBZ6c93uLCjGm
iCroJVLzU45iNE.pIUfs3TWb.0FejHp9uANr0GcJPTroFDNOHpkIweLnI1QT
dHl3P7LhOF3Ahd9rnvLwAMy5JSdNezGlsIsW9mW44r26js+alhxjlkdhN0YE
YqiH5MTeWo6D4Qm.ieLS7OynmuVGSbmbFUlnWWhiQlhOeN+Yl35bq.tGo9JR
cj8AVqdz7nSgVB9zNj.FTOU68o5d9KO5TUOGxVMw+jTO8T6wqD0hEiHsOJO5
TTOMoS.zlqN0SpZjz6GcH05ylVM0jwuidlkmAif374ih5M5QPfccr8Hqifff
otN8pt3hUcaWu8nosBhwmD0Epw5KmoF.poxy4YHbnjqfPJqcM3Y2vun7nS.i
f3eETiqcRX2LR.4QmhZrkoCSGwzZrqKHrVR8caari+55d2caPqmq5n.ywe8Q
WrZL9fpwVXeaogMByE6y1SMdjk+gbavbN7fYvVtt1C2XwHJSzpk+tidUO25H
UB9onw9mlFQ10fhpZBaDatcMTTEGcJpwzqg92qqiVtM6Cu0IRQ0ndEdfCAqV
l0qYAUmPrctbxO4XCuPMa1asYzKDks1D52ZCne6Mednz9qW8+.vfqkDA
-----------end_max5_patcher----------- -----------end_max5_patcher-----------
*/ */

View File

@ -19,7 +19,7 @@
Created 26 Sept. 2005 Created 26 Sept. 2005
by Tom Igoe by Tom Igoe
modified 26 Oct 2011 modified 24 Apr 2012
by Tom Igoe and Scott Fitzgerald by Tom Igoe and Scott Fitzgerald
This example code is in the public domain. This example code is in the public domain.
@ -142,83 +142,88 @@ void serialEvent(Serial myPort) {
/* /*
Max/MSP version 5 patch to run with this example: Max/MSP version 5 patch to run with this example:
----------begin_max5_patcher---------- ----------begin_max5_patcher----------
3365.3oc4bk0iiaiD9Y2+J3JLOrAq6Fhj5LOscRP.lGxtCxDr6CYBFHaQaqL 3640.3oc6cs0jZajE94Y9UzKkeHoVloTeSHkm1II0VkeHIthSs6C1obIjZ.E
xRNRzcOcBx+8s3grkZac31Vr8jMASKScPU7qNXUTUw+3lIVyx+LqzB80neFM KjHRhY7jT4+9d5KBj.jTCAXfoV6x.sj5VmyWet127ed6MCFm8EQw.z2f9.5l
YxebyjIxSINwDc6IVqi977znR4sYMOe8ZVF2Zp5Zb1m4pyuJOujghPkrhjnT a9yau4F0kjW3FS4aFLO3KgIAEpGaPX174hzxAC02qT7kR80mkkUHPAnBQdbP
zl7BNZQQ9ZDeURIBdlsUOyh7LdYxuyDOGlbms9zYaWmjkx3x2Cd+Iy2xqNa0 BZQVdIZRd1bT4r3BDTmkU0YQPY3r3zoeJWDVpe2ttr6cFhvXt7KhyH8W26f9
stIhOeUR1xOVvlyUTuuqOzSHRfs7fspEz.8K5GJIVRn4y90ao90okrn0RZw5 USkhiTulrw+1czQUszjrzxzf4B0sdP9dqtS5x4woIhREQiWewrkkUW0oViTD
dAkaItvedyMh+LcffRF6QnaO.SzPQnmsM5eFskmmugkgrOebfzNNPbbDibJU +GpFASt2Qd0+51akeLzRPIU7DPXagIFnH.4653f9WAKKyxVHRQNcfDXlih2w
hCXG2tvArSEsn5b9SaXptwJQviQVV6drKCRslUVFsjcn3SJH8bJ.C4n.Ctcf puvbdWHAlcTPBRKHg4x5mr74EBMINHV1+iFL.8qG.VMWTTDLUrs.TBH+zAvP
gRjhDTaO4gPI7DbbbgfaEWtz.RKhNR7XVT1xSASrOYLITJrfUG75VVwqULQR nTEhvvxun9pBd6FWH38DWH6DWv6ItbX.RKBOJ7XbP5ztvDesvhBLb6VTwcOg
mlAWRyihOUXAepvhiGsNrX2ErPbtFfkMELvzRrzp6nBM9Dk5CUJq3G1IzDXL DmiBjnXfiIrjjED0CpP490PEmtPExwQA5EGUVjK.CKQJqtcYl0nCMRAJi76D
snsuz4WR3r054+rduzb86jPHxZp3OyxyWK92seS5VFX+lu5128c2e6s3c2w9 Z7dQflCCVV1i+ENiTy3AwYaghEA4.KVJx+jHMXbhntJPceO3iBpPOPKtZqtU
K7C4wr0G47hG38OkMe2k99jB12m9zsgem+2b66e261CFMYCz1YCdJ7WaLiX2 jUoXtw28fkEimmEIlOI.3Q4iMT9wO+iLxc9O7sN28928t6Ve8uMYo.7EUN6t
oHJE2qU9FV5EWWiIlU5MZi3vnJ+pANhxagvfNwMxq8r.bz7TVTw3pQqkgHRa ePVoUW+6E4hOW7CAgeaV1meWd1cuWnYLy8mKhhClGDd25F3ce+C2si1Ud42+
dNzNQDZqHhhPMCr.JsEFQJQgIjt8kz40VJo.dwrKjoeRufBNTZrwizInztyB bZ3IQJOXg7q96t80e50YvDjqHw7VvkRTXhHHuKEerRwmqfBFsS.g9h.HZN3X
igWks.LhvOJeBLfmd4jVlmmlWnFJXABXeWPnMNzS7Ka8uv0.ki4htxQK2.0b hJf5Qd+xHZHgzc.mrqeYjbn4E84evfIDUjDtjNwD2iRHV6anmGdbmsfKxTTJ
nNcAj9u1BWI77nSA8nlB8TBfNdcgdAcNwmY.veOEsDzP2b9A2P5GTTg031oQ dd93rjtBJ2U42foCwZDqKfYzKkrh4VgYIY4FxVRmN2646f8ck+xw7KrjzOlZ
bmqAUyRVJP7HrMBSOekyN7ThXqfDao7le2g3X2su7S2ezTwE64NtAE6Js93D ZYAVfdZgKlaWn29FzA8nfdR2quj.3ejflBJnKr.Dwpf13cZBm85P0rPj.rOB
HQGJ4N21CJN701TDHyfvipZTEb3JssP6z1hWuxJWZXoskdSE2B5aiRSu8GYk 6fvztPFGkVI0SAPi5NKHmih7E8Ph2e35uOtYN6x6JEQtJVWpV7gRtm2dZy9W
axyJYn6e+2912h9P1GxdO3ScIJBM6IvKAfXQ7Ur5qR2TTD36cAKBtKp94XYP +YMCxLHrEvAknQktDVdY7v82SFosgmSGHO56BRRt6mEEKxRKDnGd+2812h9X
vLwSQhWoXI81DUDwYwHTR1TDuXa1bYyYOA8aZRFaAiEeG5sx9NCtedIZQdAa 5GSeODOcAJ.M9YHHAfjPkyD0GIugn.Ht6bQ.7TTS8DoPtCQCQxWobX+jYPUJ
Y9VnqkF8mh97l7R065I3Wn7EvyNOo.bbDssD3CR55gHHtoRfZ3aKxf2fdEDa hPn3zgnx7kogphieFZ2j3TwDgH5dzaUscJ77kEnIY4hoYKglVYzcH5KKxJzu
Pv2gjiq+UNm80neRr5hRVIBvIHNvR31iTCxX1CIygwblrEDKFq.Ihy.d0OqK qmgegxl.0MLNGBNDsr.5IUz0iAPZFE.0TtLOEdClQYrAAeORwW+XVo3aP+hb
QPmrLWRD4v4EwhfDzDPaJXaghxPdtn+tBht+qDcbIOpfucyc.c.c3mXB53wn DHUBCH.mfbEKfGOPyjQhGiCAdNUUBRcQjij4X.u5MZRDzHSyTDQFbcYdHHIM
D03WQIhNXZEvHYEYZT9dzivYYO.jUBGdLPhFsFfMTbDO5N4fbNvWDHM1Ac+l AzlF1lnoLjKG8UZH5guV1vEkA4kKWbOPGPC9YgjNdJHVy+ZJQ1.Cq.FUWQpA
BQjdgeHCf82OOmyQeeB+2WxJhRik35OAX0aWly9P11MwxGihQ+6477YLwih2 ke.8DbUwi.YEWBUCDhPyAXCEETFbuhICg9EIRiYnGVjKyt0+io.r+9vrxRz+
o7HXYyAdiT9ASGy0k0QY3UpP45nVTx.uiqR4ZYD8EdQxR.0P+cfC8y7e4qDr Nt7OlJxCRhT35u.X0amlI9X5xEQppQwneJrLarPVU7JkGYWVHz2njevz1UoX
p4Bgtjkq32lxV.gckm8.7nIfpDHsceZpRdpH5QgLh.q2TjCOiTt8wD35qjAu XkoEWOkxDWO9kXYocoTwuzF611zXJyimB3F5qf9nOT9qesryJTJ1EOcV4cIh
hlwDx8neH5yfL7uAhx.KELmokquC8eEhAxUDuhJVjTv.8BP.3.oCPVLp7Sn6 IPVWYoOBUMFTl.4sGRRzRT4AOIkRjn8h7LnNJI2mhg6OSk5JZrPJ4i9gfu.R
Kh2ljkKknp0WGkYNp7Rhx7nGQNKpi9PKSW3YHtYAKIKgCcJLZKkrokfneoT0 w+NHLCcpfAMij88n+qTPPMt4UTwj3bAnY.h.aIe.RiAEeF8Pdzx3zLkLUs1Z
Bosh.JpQR89EGEzHiIngUt4SUGv5EtwoEPywLf17Ur4epxFECjxlmjnsvAl5 mcmczah0FH4ZmpLcp.rVbX3d0zalKhSiKAxBZ9BU2zTP3uPobgL1Q.U0.kl+
.gLA9Hj+lwVljImFXaVBXzGzHDJDK3BaVJbu4UEVRWGEKs3A+bVZ97OgJWsE jcBZj1AMOpzsJYjdz0n53QXsfYrqELKblH7yUFoDfPVXbrwDGXqCjwjviT7a
zChyeL6UPp0wWEo.VYHpximVX.Ti7kg1f9fkvZhD8USB9Aqi5Zi8KILqio6R rXZbpxOvxzXvpOnPH0GlTJMZog8l2UZJcdPjxjG7ywIYgeFULaInFDk8jpxZ
knfudQ98Te+ivVPgSdku9Orh3nrcQJJI.VgFXzHC7HIohY6JA4jZj6DKv1Ys apvMA4cv9X.7.vaRRGFAcPYHMR0dF2BZC7wEJ2TOKeZnCRD+HzJo.OLWSW6r
SOo1iHfyeUExn6zcmBrFVTuCl.VAdHo54CUmDXR2TcwJTPw70qquZ1HmfZN3 qk2wfI6pGf.pdjC4rpfL2YeK8JYloVf93.ocJEvocv9wAcEiMQgBtl.lb0y9
ArykBIVVbMgpIVwrEmReH9Le6ueaUft09Sy6LIaCLC.nkJ0ed96MZaJ+iGWh heKnvtGRs+iHOJHM3uaZbN1jDrhED4FfwfLPCEmH8jV.BB0Z+aF.Vkqc4apU
n40WDMm05C2BeZh0xhj37LAYz3YEmt5EJr6qzbpS4x6HKZyQdXddd5rnBACY EIb9a5zAcGt5Rf3WdsNJ3R4PXDU0mouHzIca0MWO.KpQjT8oq1SIyqV3mP24
VJqAiFTVhxRVCFn4IJJB7no5hIq2TjnLHr6brrHnOVUNuHOMsQWotxCG4JJ2 ToxfHpdyOPNqgwoK.W.fxfRNtwsiDSBVlT9ociSMu+jfPQqUtk9paFLMONJK
9dLIluR1W6wqFes65RY0Uiab9NCS64q1zxY.H4V8u52TCFH9N2PWbfesqerv URFMpq7xUuvOXF1HBuN6ndhzfE6nxPXQkKKFGjKQNyHtSptYYVVRyaspyBD3
VZW+t0vWTg2hcs2u310il6fUBvuNM1tpdW1CmTYSTqxMV.qs3+MOjRzPpREv CRiA0YQYrlbgHdptY77E4wZk5UWSOf9yJByyRRZzT5673NtiNrvmhiJmoZq5
MrWH06pARaL0ygQRKjRaGP2M4aqS.29xvzp3o5yTgUG7TQWi6.Kc6DKacIYZ fI73wKp5DFrBihhmBNxadsxfoEMuRiIbutfVcM4FWuyr.2bvrlNF5.3U+q9C
e1Iyftah.Wdr6QhsC.14kJrpz60xpXclvzE.SeoBqlEP+GH7KBHe4Z8MjTc5 sKaa5jkMt70iSd8bC2ZbEFUuAa0DWqYF0tJ91p43649br2nZ2usLGuoxrnQq
GHIcBj0Wr4+uCK0FPGLThutfxtlXR9MOmh1DATUND8D5MXzaHn2PQuww7SUo 6TArNx+1CjRLPpVWf62Kj59ZFRa38Y6D0kRo8AnT8b0g0e4p8+f6.P4sBnaX
09qNP5cpJ6qlopjidq1PD6WLh3KVOasL2g9v97UeJ3zj7phsV77eA.FXRcMv TqMmPsOdOcjG+dMtOmdzcgLdIGqjX0J+FAVrmSu.L8fAX19Ky1C.e1.z+IB2
9Qiv+RiFT6SBM7ruNPC0a15zcMytmI7HA2Qg+ywYp72CCTZXptug79PGEK8S qpeCIUV+.I4fARxQGH0i.9ECVZrhZMTheMCkc4XRMsoCgbef2ZFjaF5MXzaH
KQgIIMw0ONVTlusXdEnWEACpIAFyJ4IY6hk9m2SqO6FWkDG2LxU0ZKDuIG3m n2PQugYmhe0WjdcU47Z1Ukhb6CwFISy2HNtcvtaNRWdshHNVgHcNMUlopRm4
6R.pAw8NY516KT519KS51anzsHliqH5VXEdXzM4KT5FBAAgudn6fgR2WWx2C tJByyLXfI0UN6GM7eUiFTm8BMbctZQC8atOegDu6oveXrgpeaGnfaETvsBJN
mtoWW1SHmBcSudna7oP2jqG518.0sVna+qK4D2gh2dWWzMcnzs8Ejt0mr5Cf 6AKuNsT4n+zRVXJtQd+ciEEYKyCq.8ptRTSdBRQrLNcUd5eXcjoa7fyhihZl
XUF8.K9ivqA726iQbdQxrsbkKXM95LG6qHLde5gNuXee4iko4yhR0eloc8h0 UrNQxBYZo5g.vpdt8klkJi1QyPvdH7UFMStbvYu8Amu1nY7ECMKGXBqnY2KH
M6QhKyGpydjqII0WCNjtO8qZKeib8uBRlw+1sWhLvpqRuQGWlKd.Hh6U.hHR Z18Jjl4aYNnEYiQWVzrUxytWNzL0VZ14xglI6isN5kAMi2GZlbYPyNma6FqC
1.vhpQPEpusJMZ5JuzbMW9nyyWtLcWNKdl0bklwS1UJKcLDo8v3u3r2w0LfN aJRs9qEogO+ovfvYFxxjGV07cLnH3QQzm.R.BG7SAkk4wiWVpC2p9jwX23ka
GUcFD609pHMLsG07vrRdOb.0jhSfwSDyz4wmfPuSuIkQ.VuVKd6Nbzhpn8Lv 0zSz4M6e1QZY.8mljMNHwLURqZ9FuzslMk8ZJXtcMPeblVut1XYDhdMCpmjZ
MMoTVHWUG2W8tWxhQxyEkNtEurRQvinxQGxy+XAMPC2WXsKW+iDbgRmpGhRo 8BAqsU9DezKxJAa8Hmbbfi+wccuVv7c0qELrEHB+UAhHWzCfCbKPEyBki24Z
iZ0s6pRoees+B9cALXqK7nFnxYWhBtpKE9.RswmqWmL9936cT2siCumLp7dc clythVwfkYSmlHrPdX8tC5v1iPb5ArPuOWc8NVrRZspq24UxhE0wBcAsMyt2
dVNLdefk4F13QcXSB8G7vlX+EnLO00evx7DxqiPuAfgpDSTCCtcBCuR59sLi 2LLuqvkKZRXjEq5CM6S3tq9Zm6HD+8Prm0F+jDWn1paUe+2ZuF259kxkiR5W
31r5o5wkXi8vsWbxSU9k5D3rUfJrOfp0ClB7zU.lMBOp0+kda+fnbwpmpV80 Qf6vzKBtMm+gFrMeuWsKW.6B61VyWOFjz0Zsmwza+.ikxQcAL3iDtbLWMTKm
q9uZMQsSS.IrUrBY1XK2UPddsqLpVg0oT3tMZfNKIJhm0q.nH2TcLIlniNY2 OtyMEFcjWM9iu0rMa81D8kUl3v2ewcHWP5B2HX6kK7t7DL5fs6JVIrO0Z1l3
VMT2XxEdqFpsBETlEti5ZU4DVaTqlOtsREDatZErMYjusgLxRFWVoZkbQ8MT bEpOP3zih9.gbspPzKDYbRVAQ7CFhtZsYzhW1ko0WEJcG3oAC0aRIyxKsUEI
SPobbkTv57KXHaJUDqq1EmQuoRgUKPAgT82ix6wFawY9s0LdQ9EYwH5evWMC +iDPwOLfp0uNA68MmtSUSmRuNb8d1ttWya7sVWf5Iwf.1LQtZUnqNvT1bS6z
R2UPLwn6FPsYLPkG8ip0.s+GpEqRUorsZMf9paM3GYQwUp8IYa1xQy1tXgnb E5o2vfqNSH5bufQbuZV09M.E04Mj8XBUiBqNGl5FSt3NGlZaGRpV6wc4kiWi
PefU7jnLzWmjBlGXyyyhKMeQhoS4FsABkUi1pQLrgJrNkETQ8vJpw0wMVOer q0twaaORhul1jjsIi7cMjQlJJUaQuhR495nlfRQWRJXkrgmMGXWjKM4jdGJH
x9RP+6pT3K7Dphw6rsbd9toOWkTkFS0dQUeiK7wvA5NbXVdQrptm1clkGtoW yovkl4HUetutzWuY5tjFHneGn77rtG3iJ92whCVJxKhBwgGtRaFIzabfNrRn
3GDPnthe43a6FD7rM8hZkCzgEmNVAOOuVhNNGXGybmcoYPDKh8ihr39cmV7z WThd9q24vsZjf9JvHwOKBhprFDmtXYIZ7xISjaO1GE4OK2V9yiS.qFhvrznh
4fBRsAf8cjo09Se6UG9pMRMW+9WTeha26KES6+q5T0oKyxAZPH9VeLpXMMFK 8cKyMZs7EVepT01FlCe0rIC0lUk6NX4N9syCyAE660+ovE9hyGqjaGurrLak
MJLq5iEI.oJBLu8Ufm.OZ77fOQ1Rn34+P1W+kPXrawJ7qhXkOUMireP+hUgz G0YwoMlFO4YMSZjd9DcWucsjUr1Yqgy8TluCY3N9Q8.+k0JCD3ZTS0CW8Qyb
+BKVI63l4SoRJ644ofVV6f7SPrNA6SOkVxMARijz4v7R334jvAR9mDM4zCMQ s19nOxrgjw7VFU+3ooYviK66pCfimt8AAxHOOBkK+EajC2yayWtciMzgdvpM
MJIQaj1LsASglGlr6ilLKN4ZO.ZBaaTZxe.jD08zHIhuiHwD7v5HCB105LI1 NKORj29YyGcS4wFVlql0wcZTg1yw5wvMNiTpuUzpu.Y0miRlgO0w7wpZI2Em
fAPr9FE9bF.EEXTJBODgLmSjgpXgtjPYBmnXuxVWBhkbgIVM4o+9n0ZctDKd SUBGayVM5eqU4C+rV4ZSPkvXqLJbAHlR3mKwT5ISL8+Kv0k.GWEKwpP3ewk3
Hpulc1.5P31Dr4oo9lN.a1oCFDuidhldItTUBXo2ze8105bmnfN.p08DoVGa 7omKIN7EtDmp4ZtHk0BfatXgLhgasHgZrVYaY8AIO7fq8Pas1fFzjd4ibwpd
o1qiCtlUYYqyjZ8HCAaMK+dH.njtIlyiDxPoIr4noAiSFzKoAI76ZVZxcHzj XO4GXOeOG+lcyasNh1R+wVx2yBxeTOT+wiZFYA0P48PNyiiVjAhJlNT4Qvpb
yKSgTsEm53Enxxs5snpsA.8cJaYhILbMqSTtCwIT2SzWcJUNwuCtNBJactl6 uj3aN2qYqJcBfSWhMbf+YCPcsfbNeTC2l9WNc+5eIlkST0RJgupzIn+kysgC
F.wFd8ow38BmsvSI4Q205b8XNXDX1mK.ND23cLqe7CI9Uri4iy+RSSUgG5p+ X6GGXnYpdYfP0GP6MKQXM3N1Ih6XVvcLuym7B0B5w8v.ahqBI49qJcJ.TaX.
HIpz3nQKZUBfJEBksNW2AcFp8b7I6NnNwkbbb10xHTqsY8b.OBxBZWnopDbs N+xBP4NGHhhqYfkRNM9q1f3ZweqyYCQYdGCSZGQ5wBx47o.Ssw+CkcgQOmud
BOIm+BGfGCsIpqTxkZqhBPSshVmK0RGCp0OPE7taMpU15boVxUnkJ7PVQRyZ KZic4QKzCw+7ROm8nY2LfMsEDtdfeMKSn5Ev95IQhorcqJcBrzPsQUhRNe8M
PmNnvjLbn5zqPZZHV6nFdYVFhSeT5UHMYV8Nr2HrbTNZCrNXoAV8xrHZctyg 1X6lhOezC4Bidv1nKcFs8YimJ9n8RWZXiO7aSCxDRLdjd91qU5TnmXCeRvmR
MDIM7IxUE6mpR5SM8u1pqn0kvKf9roQ8N0YETQVpJnPOhptBazRteTK1KOcT 9jnm7b15RmJ9rO4Kr+IgO04BfczyOpqx9npzofOsIlaR8Mo0IUMR48i0mYly
a+8meDTjfQXFCepaMuunggpQRiV5jcsxuB+C9dg27m27+.7QBpFG lVMwlw6gbloGRezy4yKEw6BHBBWik.eRi3DNM5KDahS.SOE1EjmXl7Uyqo9T
AtQAO8fG3oLX3cZFxKh0FLNSRfDaoG74gdvW.ZDU9FMGSdFMBt+IQh.6eIvw
FujTkJREGKKcJ3X2WtXf7Ub1HywEqxh2tJnE.FcZhMByrcXQw1x+bOWJYjpy
lv8oq55aEHLcwD8hJjxbVU5EigcNtL7Ql76KVVp69Huhcb87vpoCkRYT+96v
Hd5Ay1rofMqm+FkLYvv0+GL3FkL6bLp21kL6QFNV8BNM48foWBV4zt1wXm5V
4jkNEbL45dtNw13Iltmi9sAyY0S0l8BR+3yWjVXax7eOmKrp4m0QKIal6VYo
SAf5XQxSrCa5l0qk45k5kAzqEgMNgzkz9FmL5abpnu4IhNzZ+0s+OKCSg0.
-----------end_max5_patcher----------- -----------end_max5_patcher-----------
*/ */

View File

@ -66,7 +66,7 @@
void pulse(int pin, int times); void pulse(int pin, int times);
void setup() { void setup() {
Serial.begin(9600); Serial.begin(19200);
pinMode(LED_PMODE, OUTPUT); pinMode(LED_PMODE, OUTPUT);
pulse(LED_PMODE, 2); pulse(LED_PMODE, 2);
pinMode(LED_ERR, OUTPUT); pinMode(LED_ERR, OUTPUT);
@ -109,7 +109,7 @@ void heartbeat() {
if (hbval < 32) hbdelta = -hbdelta; if (hbval < 32) hbdelta = -hbdelta;
hbval += hbdelta; hbval += hbdelta;
analogWrite(LED_HB, hbval); analogWrite(LED_HB, hbval);
delay(40); delay(20);
} }

View File

@ -3,6 +3,7 @@
HIGH LITERAL1 Constants HIGH LITERAL1 Constants
LOW LITERAL1 Constants LOW LITERAL1 Constants
INPUT LITERAL1 Constants INPUT LITERAL1 Constants
INPUT_PULLUP LITERAL1 Constants
OUTPUT LITERAL1 Constants OUTPUT LITERAL1 Constants
DEC LITERAL1 Serial_Print DEC LITERAL1 Serial_Print
BIN LITERAL1 Serial_Print BIN LITERAL1 Serial_Print
@ -30,6 +31,7 @@ byte KEYWORD1 Byte
case KEYWORD1 SwitchCase case KEYWORD1 SwitchCase
char KEYWORD1 Char char KEYWORD1 Char
class KEYWORD1 class KEYWORD1
const KEYWORD1 Const
continue KEYWORD1 Continue continue KEYWORD1 Continue
default KEYWORD1 SwitchCase default KEYWORD1 SwitchCase
do KEYWORD1 DoWhile do KEYWORD1 DoWhile

View File

@ -76,11 +76,16 @@ editor.window.width.default = 500
editor.window.height.default = 600 editor.window.height.default = 600
editor.window.width.min = 400 editor.window.width.min = 400
editor.window.height.min = 500 editor.window.height.min = 290
# the following commented out to better support netbooks
# http://code.google.com/p/arduino/issues/detail?id=52
#editor.window.height.min = 500
# tested as approx 440 on OS X # tested as approx 440 on OS X
editor.window.height.min.macosx = 450 #editor.window.height.min.macosx = 450
# tested to be 515 on Windows XP, this leaves some room # tested to be 515 on Windows XP, this leaves some room
editor.window.height.min.windows = 530 #editor.window.height.min.windows = 530
# font size for editor # font size for editor
editor.font=Monospaced,plain,12 editor.font=Monospaced,plain,12
@ -245,9 +250,15 @@ software=ARDUINO
programmer = arduino:avrispmkii programmer = arduino:avrispmkii
upload.using = bootloader upload.using = bootloader
upload.verify = true
serial.port=COM1 serial.port=COM1
serial.databits=8 serial.databits=8
serial.stopbits=1 serial.stopbits=1
serial.parity=N serial.parity=N
serial.debug_rate=9600 serial.debug_rate=9600
# I18 Preferences
# default chosen language (none for none)
editor.languages.current =

Binary file not shown.

View File

@ -0,0 +1,106 @@
;************************************************************
; Windows USB CDC ACM Setup File
; Copyright (c) 2000 Microsoft Corporation
[Version]
Signature="$Windows NT$"
Class=Ports
ClassGuid={4D36E978-E325-11CE-BFC1-08002BE10318}
Provider=%MFGNAME%
LayoutFile=layout.inf
CatalogFile=%MFGFILENAME%.cat
DriverVer=11/15/2007,5.1.2600.0
[Manufacturer]
%MFGNAME%=DeviceList, NTamd64
[DestinationDirs]
DefaultDestDir=12
;------------------------------------------------------------------------------
; Windows 2000/XP/Vista-32bit Sections
;------------------------------------------------------------------------------
[DriverInstall.nt]
include=mdmcpq.inf
CopyFiles=DriverCopyFiles.nt
AddReg=DriverInstall.nt.AddReg
[DriverCopyFiles.nt]
usbser.sys,,,0x20
[DriverInstall.nt.AddReg]
HKR,,DevLoader,,*ntkern
HKR,,NTMPDriver,,%DRIVERFILENAME%.sys
HKR,,EnumPropPages32,,"MsPorts.dll,SerialPortPropPageProvider"
[DriverInstall.nt.Services]
AddService=usbser, 0x00000002, DriverService.nt
[DriverService.nt]
DisplayName=%SERVICE%
ServiceType=1
StartType=3
ErrorControl=1
ServiceBinary=%12%\%DRIVERFILENAME%.sys
;------------------------------------------------------------------------------
; Vista-64bit Sections
;------------------------------------------------------------------------------
[DriverInstall.NTamd64]
include=mdmcpq.inf
CopyFiles=DriverCopyFiles.NTamd64
AddReg=DriverInstall.NTamd64.AddReg
[DriverCopyFiles.NTamd64]
%DRIVERFILENAME%.sys,,,0x20
[DriverInstall.NTamd64.AddReg]
HKR,,DevLoader,,*ntkern
HKR,,NTMPDriver,,%DRIVERFILENAME%.sys
HKR,,EnumPropPages32,,"MsPorts.dll,SerialPortPropPageProvider"
[DriverInstall.NTamd64.Services]
AddService=usbser, 0x00000002, DriverService.NTamd64
[DriverService.NTamd64]
DisplayName=%SERVICE%
ServiceType=1
StartType=3
ErrorControl=1
ServiceBinary=%12%\%DRIVERFILENAME%.sys
;------------------------------------------------------------------------------
; Vendor and Product ID Definitions
;------------------------------------------------------------------------------
; When developing your USB device, the VID and PID used in the PC side
; application program and the firmware on the microcontroller must match.
; Modify the below line to use your VID and PID. Use the format as shown below.
; Note: One INF file can be used for multiple devices with different VID and PIDs.
; For each supported device, append ",USB\VID_xxxx&PID_yyyy" to the end of the line.
;------------------------------------------------------------------------------
[SourceDisksFiles]
[SourceDisksNames]
[DeviceList]
%DESCRIPTION%=DriverInstall, USB\VID_2341&PID_003B
[DeviceList.NTamd64]
%DESCRIPTION%=DriverInstall, USB\VID_2341&PID_003B
;------------------------------------------------------------------------------
; String Definitions
;------------------------------------------------------------------------------
;Modify these strings to customize your device
;------------------------------------------------------------------------------
[Strings]
MFGFILENAME="CDC_vista"
DRIVERFILENAME ="usbser"
MFGNAME="Arduino LLC (www.arduino.cc)"
INSTDISK="Arduino USBSerial Driver Installer"
DESCRIPTION="Arduino UNO"
SERVICE="USB RS-232 Emulation Driver"

View File

@ -20,6 +20,7 @@ extern "C"{
#define INPUT 0x0 #define INPUT 0x0
#define OUTPUT 0x1 #define OUTPUT 0x1
#define INPUT_PULLUP 0x2
#define true 0x1 #define true 0x1
#define false 0x0 #define false 0x0

View File

@ -46,8 +46,8 @@
struct ring_buffer struct ring_buffer
{ {
unsigned char buffer[SERIAL_BUFFER_SIZE]; unsigned char buffer[SERIAL_BUFFER_SIZE];
volatile int head; volatile unsigned int head;
volatile int tail; volatile unsigned int tail;
}; };
#if defined(USBCON) #if defined(USBCON)

View File

@ -41,7 +41,7 @@ size_t Print::write(const uint8_t *buffer, size_t size)
size_t Print::print(const __FlashStringHelper *ifsh) size_t Print::print(const __FlashStringHelper *ifsh)
{ {
const prog_char *p = (const prog_char *)ifsh; const char PROGMEM *p = (const char PROGMEM *)ifsh;
size_t n = 0; size_t n = 0;
while (1) { while (1) {
unsigned char c = pgm_read_byte(p++); unsigned char c = pgm_read_byte(p++);

View File

@ -101,23 +101,25 @@ bool Stream::findUntil(char *target, size_t targetLen, char *terminator, size_t
int c; int c;
if( *target == 0) if( *target == 0)
return true; // return true if target is a null string return true; // return true if target is a null string
while( (c = timedRead()) > 0){ while( (c = timedRead()) > 0){
if(c != target[index])
index = 0; // reset index if any char does not match
if( c == target[index]){ if( c == target[index]){
//////Serial.print("found "); Serial.write(c); Serial.print("index now"); Serial.println(index+1); //////Serial.print("found "); Serial.write(c); Serial.print("index now"); Serial.println(index+1);
if(++index >= targetLen){ // return true if all chars in the target match if(++index >= targetLen){ // return true if all chars in the target match
return true; return true;
} }
} }
else{
index = 0; // reset index if any char does not match
}
if(termLen > 0 && c == terminator[termIndex]){ if(termLen > 0 && c == terminator[termIndex]){
if(++termIndex >= termLen) if(++termIndex >= termLen)
return false; // return false if terminate string found before target string return false; // return false if terminate string found before target string
} }
else else
termIndex = 0; termIndex = 0;
} }
return false; return false;
} }

View File

@ -32,7 +32,7 @@
#include "wiring_private.h" #include "wiring_private.h"
volatile static voidFuncPtr intFunc[EXTERNAL_NUM_INTERRUPTS]; static volatile voidFuncPtr intFunc[EXTERNAL_NUM_INTERRUPTS];
// volatile static voidFuncPtr twiIntFunc; // volatile static voidFuncPtr twiIntFunc;
void attachInterrupt(uint8_t interruptNum, void (*userFunc)(void), int mode) { void attachInterrupt(uint8_t interruptNum, void (*userFunc)(void), int mode) {
@ -121,8 +121,6 @@ void attachInterrupt(uint8_t interruptNum, void (*userFunc)(void), int mode) {
#elif defined(MCUCR) && defined(ISC20) && defined(GIMSK) && defined(GIMSK) #elif defined(MCUCR) && defined(ISC20) && defined(GIMSK) && defined(GIMSK)
MCUCR = (MCUCR & ~((1 << ISC20) | (1 << ISC21))) | (mode << ISC20); MCUCR = (MCUCR & ~((1 << ISC20) | (1 << ISC21))) | (mode << ISC20);
GIMSK |= (1 << INT2); GIMSK |= (1 << INT2);
#else
#warning attachInterrupt may need some more work for this cpu (case 1)
#endif #endif
break; break;
#endif #endif

View File

@ -500,7 +500,7 @@ int String::lastIndexOf( char theChar ) const
int String::lastIndexOf(char ch, unsigned int fromIndex) const int String::lastIndexOf(char ch, unsigned int fromIndex) const
{ {
if (fromIndex >= len || fromIndex < 0) return -1; if (fromIndex >= len) return -1;
char tempchar = buffer[fromIndex + 1]; char tempchar = buffer[fromIndex + 1];
buffer[fromIndex + 1] = '\0'; buffer[fromIndex + 1] = '\0';
char* temp = strrchr( buffer, ch ); char* temp = strrchr( buffer, ch );
@ -516,7 +516,7 @@ int String::lastIndexOf(const String &s2) const
int String::lastIndexOf(const String &s2, unsigned int fromIndex) const int String::lastIndexOf(const String &s2, unsigned int fromIndex) const
{ {
if (s2.len == 0 || len == 0 || s2.len > len || fromIndex < 0) return -1; if (s2.len == 0 || len == 0 || s2.len > len) return -1;
if (fromIndex >= len) fromIndex = len - 1; if (fromIndex >= len) fromIndex = len - 1;
int found = -1; int found = -1;
for (char *p = buffer; p <= buffer + fromIndex; p++) { for (char *p = buffer; p <= buffer + fromIndex; p++) {

View File

@ -45,6 +45,8 @@ int analogRead(uint8_t pin)
if (pin >= 54) pin -= 54; // allow for channel or pin numbers if (pin >= 54) pin -= 54; // allow for channel or pin numbers
#elif defined(__AVR_ATmega32U4__) #elif defined(__AVR_ATmega32U4__)
if (pin >= 18) pin -= 18; // allow for channel or pin numbers if (pin >= 18) pin -= 18; // allow for channel or pin numbers
#elif defined(__AVR_ATmega1284__)
if (pin >= 24) pin -= 24; // allow for channel or pin numbers
#else #else
if (pin >= 14) pin -= 14; // allow for channel or pin numbers if (pin >= 14) pin -= 14; // allow for channel or pin numbers
#endif #endif

View File

@ -32,17 +32,25 @@ void pinMode(uint8_t pin, uint8_t mode)
{ {
uint8_t bit = digitalPinToBitMask(pin); uint8_t bit = digitalPinToBitMask(pin);
uint8_t port = digitalPinToPort(pin); uint8_t port = digitalPinToPort(pin);
volatile uint8_t *reg; volatile uint8_t *reg, *out;
if (port == NOT_A_PIN) return; if (port == NOT_A_PIN) return;
// JWS: can I let the optimizer do this? // JWS: can I let the optimizer do this?
reg = portModeRegister(port); reg = portModeRegister(port);
out = portOutputRegister(port);
if (mode == INPUT) { if (mode == INPUT) {
uint8_t oldSREG = SREG; uint8_t oldSREG = SREG;
cli(); cli();
*reg &= ~bit; *reg &= ~bit;
*out &= ~bit;
SREG = oldSREG;
} else if (mode == INPUT_PULLUP) {
uint8_t oldSREG = SREG;
cli();
*reg &= ~bit;
*out |= bit;
SREG = oldSREG; SREG = oldSREG;
} else { } else {
uint8_t oldSREG = SREG; uint8_t oldSREG = SREG;

View File

@ -11,13 +11,33 @@
int DhcpClass::beginWithDHCP(uint8_t *mac, unsigned long timeout, unsigned long responseTimeout) int DhcpClass::beginWithDHCP(uint8_t *mac, unsigned long timeout, unsigned long responseTimeout)
{ {
uint8_t dhcp_state = STATE_DHCP_START; _dhcpLeaseTime=0;
uint8_t messageType = 0; _dhcpT1=0;
_dhcpT2=0;
_lastCheck=0;
_timeout = timeout;
_responseTimeout = responseTimeout;
// zero out _dhcpMacAddr, _dhcpSubnetMask, _dhcpGatewayIp, _dhcpLocalIp, _dhcpDhcpServerIp, _dhcpDnsServerIp // zero out _dhcpMacAddr
memset(_dhcpMacAddr, 0, 26); memset(_dhcpMacAddr, 0, 6);
reset_DHCP_lease();
memcpy((void*)_dhcpMacAddr, (void*)mac, 6); memcpy((void*)_dhcpMacAddr, (void*)mac, 6);
_dhcp_state = STATE_DHCP_START;
return request_DHCP_lease();
}
void DhcpClass::reset_DHCP_lease(){
// zero out _dhcpSubnetMask, _dhcpGatewayIp, _dhcpLocalIp, _dhcpDhcpServerIp, _dhcpDnsServerIp
memset(_dhcpLocalIp, 0, 20);
}
//return:0 on error, 1 if request is sent and response is received
int DhcpClass::request_DHCP_lease(){
uint8_t messageType = 0;
// Pick an initial transaction ID // Pick an initial transaction ID
_dhcpTransactionId = random(1UL, 2000UL); _dhcpTransactionId = random(1UL, 2000UL);
@ -35,48 +55,68 @@ int DhcpClass::beginWithDHCP(uint8_t *mac, unsigned long timeout, unsigned long
unsigned long startTime = millis(); unsigned long startTime = millis();
while(dhcp_state != STATE_DHCP_LEASED) while(_dhcp_state != STATE_DHCP_LEASED)
{ {
if(dhcp_state == STATE_DHCP_START) if(_dhcp_state == STATE_DHCP_START)
{ {
_dhcpTransactionId++; _dhcpTransactionId++;
send_DHCP_MESSAGE(DHCP_DISCOVER, ((millis() - startTime) / 1000)); send_DHCP_MESSAGE(DHCP_DISCOVER, ((millis() - startTime) / 1000));
dhcp_state = STATE_DHCP_DISCOVER; _dhcp_state = STATE_DHCP_DISCOVER;
} }
else if(dhcp_state == STATE_DHCP_DISCOVER) else if(_dhcp_state == STATE_DHCP_REREQUEST){
_dhcpTransactionId++;
send_DHCP_MESSAGE(DHCP_REQUEST, ((millis() - startTime)/1000));
_dhcp_state = STATE_DHCP_REQUEST;
}
else if(_dhcp_state == STATE_DHCP_DISCOVER)
{ {
uint32_t respId; uint32_t respId;
messageType = parseDHCPResponse(responseTimeout, respId); messageType = parseDHCPResponse(_responseTimeout, respId);
if(messageType == DHCP_OFFER) if(messageType == DHCP_OFFER)
{ {
// We'll use the transaction ID that the offer came with, // We'll use the transaction ID that the offer came with,
// rather than the one we were up to // rather than the one we were up to
_dhcpTransactionId = respId; _dhcpTransactionId = respId;
send_DHCP_MESSAGE(DHCP_REQUEST, ((millis() - startTime) / 1000)); send_DHCP_MESSAGE(DHCP_REQUEST, ((millis() - startTime) / 1000));
dhcp_state = STATE_DHCP_REQUEST; _dhcp_state = STATE_DHCP_REQUEST;
} }
} }
else if(dhcp_state == STATE_DHCP_REQUEST) else if(_dhcp_state == STATE_DHCP_REQUEST)
{ {
uint32_t respId; uint32_t respId;
messageType = parseDHCPResponse(responseTimeout, respId); messageType = parseDHCPResponse(_responseTimeout, respId);
if(messageType == DHCP_ACK) if(messageType == DHCP_ACK)
{ {
dhcp_state = STATE_DHCP_LEASED; _dhcp_state = STATE_DHCP_LEASED;
result = 1; result = 1;
//use default lease time if we didn't get it
if(_dhcpLeaseTime == 0){
_dhcpLeaseTime = DEFAULT_LEASE;
}
//calculate T1 & T2 if we didn't get it
if(_dhcpT1 == 0){
//T1 should be 50% of _dhcpLeaseTime
_dhcpT1 = _dhcpLeaseTime >> 1;
}
if(_dhcpT2 == 0){
//T2 should be 87.5% (7/8ths) of _dhcpLeaseTime
_dhcpT2 = _dhcpT1 << 1;
}
_renewInSec = _dhcpT1;
_rebindInSec = _dhcpT2;
} }
else if(messageType == DHCP_NAK) else if(messageType == DHCP_NAK)
dhcp_state = STATE_DHCP_START; _dhcp_state = STATE_DHCP_START;
} }
if(messageType == 255) if(messageType == 255)
{ {
messageType = 0; messageType = 0;
dhcp_state = STATE_DHCP_START; _dhcp_state = STATE_DHCP_START;
} }
if(result != 1 && ((millis() - startTime) > timeout)) if(result != 1 && ((millis() - startTime) > _timeout))
break; break;
} }
@ -303,7 +343,25 @@ uint8_t DhcpClass::parseDHCPResponse(unsigned long responseTimeout, uint32_t& tr
} }
break; break;
case dhcpT1value :
opt_len = _dhcpUdpSocket.read();
_dhcpUdpSocket.read((uint8_t*)&_dhcpT1, sizeof(_dhcpT1));
_dhcpT1 = ntohl(_dhcpT1);
break;
case dhcpT2value :
opt_len = _dhcpUdpSocket.read();
_dhcpUdpSocket.read((uint8_t*)&_dhcpT2, sizeof(_dhcpT2));
_dhcpT2 = ntohl(_dhcpT2);
break;
case dhcpIPaddrLeaseTime : case dhcpIPaddrLeaseTime :
opt_len = _dhcpUdpSocket.read();
_dhcpUdpSocket.read((uint8_t*)&_dhcpLeaseTime, sizeof(_dhcpLeaseTime));
_dhcpLeaseTime = ntohl(_dhcpLeaseTime);
_renewInSec = _dhcpLeaseTime;
break;
default : default :
opt_len = _dhcpUdpSocket.read(); opt_len = _dhcpUdpSocket.read();
// Skip over the rest of this option // Skip over the rest of this option
@ -322,6 +380,68 @@ uint8_t DhcpClass::parseDHCPResponse(unsigned long responseTimeout, uint32_t& tr
return type; return type;
} }
/*
returns:
0/DHCP_CHECK_NONE: nothing happened
1/DHCP_CHECK_RENEW_FAIL: renew failed
2/DHCP_CHECK_RENEW_OK: renew success
3/DHCP_CHECK_REBIND_FAIL: rebind fail
4/DHCP_CHECK_REBIND_OK: rebind success
*/
int DhcpClass::checkLease(){
//this uses a signed / unsigned trick to deal with millis overflow
unsigned long now = millis();
signed long snow = (long)now;
int rc=DHCP_CHECK_NONE;
if (_lastCheck != 0){
signed long factor;
//calc how many ms past the timeout we are
factor = snow - (long)_secTimeout;
//if on or passed the timeout, reduce the counters
if ( factor >= 0 ){
//next timeout should be now plus 1000 ms minus parts of second in factor
_secTimeout = snow + 1000 - factor % 1000;
//how many seconds late are we, minimum 1
factor = factor / 1000 +1;
//reduce the counters by that mouch
//if we can assume that the cycle time (factor) is fairly constant
//and if the remainder is less than cycle time * 2
//do it early instead of late
if(_renewInSec < factor*2 )
_renewInSec = 0;
else
_renewInSec -= factor;
if(_rebindInSec < factor*2 )
_rebindInSec = 0;
else
_rebindInSec -= factor;
}
//if we have a lease but should renew, do it
if (_dhcp_state == STATE_DHCP_LEASED && _renewInSec <=0){
_dhcp_state = STATE_DHCP_REREQUEST;
rc = 1 + request_DHCP_lease();
}
//if we have a lease or is renewing but should bind, do it
if( (_dhcp_state == STATE_DHCP_LEASED || _dhcp_state == STATE_DHCP_START) && _rebindInSec <=0){
//this should basically restart completely
_dhcp_state = STATE_DHCP_START;
reset_DHCP_lease();
rc = 3 + request_DHCP_lease();
}
}
else{
_secTimeout = snow + 1000;
}
_lastCheck = now;
return rc;
}
IPAddress DhcpClass::getLocalIp() IPAddress DhcpClass::getLocalIp()
{ {
return IPAddress(_dhcpLocalIp); return IPAddress(_dhcpLocalIp);

View File

@ -45,6 +45,13 @@
#define MAX_DHCP_OPT 16 #define MAX_DHCP_OPT 16
#define HOST_NAME "WIZnet" #define HOST_NAME "WIZnet"
#define DEFAULT_LEASE (900) //default lease time in seconds
#define DHCP_CHECK_NONE (0)
#define DHCP_CHECK_RENEW_FAIL (1)
#define DHCP_CHECK_RENEW_OK (2)
#define DHCP_CHECK_REBIND_FAIL (3)
#define DHCP_CHECK_REBIND_OK (4)
enum enum
{ {
@ -139,8 +146,19 @@ private:
uint8_t _dhcpGatewayIp[4]; uint8_t _dhcpGatewayIp[4];
uint8_t _dhcpDhcpServerIp[4]; uint8_t _dhcpDhcpServerIp[4];
uint8_t _dhcpDnsServerIp[4]; uint8_t _dhcpDnsServerIp[4];
uint32_t _dhcpLeaseTime;
uint32_t _dhcpT1, _dhcpT2;
signed long _renewInSec;
signed long _rebindInSec;
signed long _lastCheck;
unsigned long _timeout;
unsigned long _responseTimeout;
unsigned long _secTimeout;
uint8_t _dhcp_state;
EthernetUDP _dhcpUdpSocket; EthernetUDP _dhcpUdpSocket;
int request_DHCP_lease();
void reset_DHCP_lease();
void presend_DHCP(); void presend_DHCP();
void send_DHCP_MESSAGE(uint8_t, uint16_t); void send_DHCP_MESSAGE(uint8_t, uint16_t);
void printByte(char *, uint8_t); void printByte(char *, uint8_t);
@ -154,6 +172,7 @@ public:
IPAddress getDnsServerIp(); IPAddress getDnsServerIp();
int beginWithDHCP(uint8_t *, unsigned long timeout = 60000, unsigned long responseTimeout = 4000); int beginWithDHCP(uint8_t *, unsigned long timeout = 60000, unsigned long responseTimeout = 4000);
int checkLease();
}; };
#endif #endif

View File

@ -10,7 +10,8 @@ uint16_t EthernetClass::_server_port[MAX_SOCK_NUM] = {
int EthernetClass::begin(uint8_t *mac_address) int EthernetClass::begin(uint8_t *mac_address)
{ {
DhcpClass dhcp; _dhcp = new DhcpClass();
// Initialise the basic info // Initialise the basic info
W5100.init(); W5100.init();
@ -18,15 +19,15 @@ int EthernetClass::begin(uint8_t *mac_address)
W5100.setIPAddress(IPAddress(0,0,0,0).raw_address()); W5100.setIPAddress(IPAddress(0,0,0,0).raw_address());
// Now try to get our config info from a DHCP server // Now try to get our config info from a DHCP server
int ret = dhcp.beginWithDHCP(mac_address); int ret = _dhcp->beginWithDHCP(mac_address);
if(ret == 1) if(ret == 1)
{ {
// We've successfully found a DHCP server and got our configuration info, so set things // We've successfully found a DHCP server and got our configuration info, so set things
// accordingly // accordingly
W5100.setIPAddress(dhcp.getLocalIp().raw_address()); W5100.setIPAddress(_dhcp->getLocalIp().raw_address());
W5100.setGatewayIp(dhcp.getGatewayIp().raw_address()); W5100.setGatewayIp(_dhcp->getGatewayIp().raw_address());
W5100.setSubnetMask(dhcp.getSubnetMask().raw_address()); W5100.setSubnetMask(_dhcp->getSubnetMask().raw_address());
_dnsServerAddress = dhcp.getDnsServerIp(); _dnsServerAddress = _dhcp->getDnsServerIp();
} }
return ret; return ret;
@ -66,6 +67,31 @@ void EthernetClass::begin(uint8_t *mac, IPAddress local_ip, IPAddress dns_server
_dnsServerAddress = dns_server; _dnsServerAddress = dns_server;
} }
int EthernetClass::maintain(){
int rc = DHCP_CHECK_NONE;
if(_dhcp != NULL){
//we have a pointer to dhcp, use it
rc = _dhcp->checkLease();
switch ( rc ){
case DHCP_CHECK_NONE:
//nothing done
break;
case DHCP_CHECK_RENEW_OK:
case DHCP_CHECK_REBIND_OK:
//we might have got a new IP.
W5100.setIPAddress(_dhcp->getLocalIp().raw_address());
W5100.setGatewayIp(_dhcp->getGatewayIp().raw_address());
W5100.setSubnetMask(_dhcp->getSubnetMask().raw_address());
_dnsServerAddress = _dhcp->getDnsServerIp();
break;
default:
//this is actually a error, it will retry though
break;
}
}
return rc;
}
IPAddress EthernetClass::localIP() IPAddress EthernetClass::localIP()
{ {
IPAddress ret; IPAddress ret;

View File

@ -6,12 +6,14 @@
#include "IPAddress.h" #include "IPAddress.h"
#include "EthernetClient.h" #include "EthernetClient.h"
#include "EthernetServer.h" #include "EthernetServer.h"
#include "Dhcp.h"
#define MAX_SOCK_NUM 4 #define MAX_SOCK_NUM 4
class EthernetClass { class EthernetClass {
private: private:
IPAddress _dnsServerAddress; IPAddress _dnsServerAddress;
DhcpClass* _dhcp;
public: public:
static uint8_t _state[MAX_SOCK_NUM]; static uint8_t _state[MAX_SOCK_NUM];
static uint16_t _server_port[MAX_SOCK_NUM]; static uint16_t _server_port[MAX_SOCK_NUM];
@ -23,6 +25,7 @@ public:
void begin(uint8_t *mac_address, IPAddress local_ip, IPAddress dns_server); void begin(uint8_t *mac_address, IPAddress local_ip, IPAddress dns_server);
void begin(uint8_t *mac_address, IPAddress local_ip, IPAddress dns_server, IPAddress gateway); void begin(uint8_t *mac_address, IPAddress local_ip, IPAddress dns_server, IPAddress gateway);
void begin(uint8_t *mac_address, IPAddress local_ip, IPAddress dns_server, IPAddress gateway, IPAddress subnet); void begin(uint8_t *mac_address, IPAddress local_ip, IPAddress dns_server, IPAddress gateway, IPAddress subnet);
int maintain();
IPAddress localIP(); IPAddress localIP();
IPAddress subnetMask(); IPAddress subnetMask();

View File

@ -41,7 +41,7 @@ int EthernetClient::connect(IPAddress ip, uint16_t port) {
for (int i = 0; i < MAX_SOCK_NUM; i++) { for (int i = 0; i < MAX_SOCK_NUM; i++) {
uint8_t s = W5100.readSnSR(i); uint8_t s = W5100.readSnSR(i);
if (s == SnSR::CLOSED || s == SnSR::FIN_WAIT) { if (s == SnSR::CLOSED || s == SnSR::FIN_WAIT || s == SnSR::CLOSE_WAIT) {
_sock = i; _sock = i;
break; break;
} }

View File

@ -52,15 +52,16 @@ uint8_t EthernetUDP::begin(uint16_t port) {
return 0; return 0;
_port = port; _port = port;
_remaining = 0;
socket(_sock, SnMR::UDP, _port, 0); socket(_sock, SnMR::UDP, _port, 0);
return 1; return 1;
} }
/* Is data available in rx buffer? Returns 0 if no, number of available bytes if yes. /* return number of bytes available in the current packet,
* returned value includes 8 byte UDP header!*/ will return zero if parsePacket hasn't been called yet */
int EthernetUDP::available() { int EthernetUDP::available() {
return W5100.getRXReceivedSize(_sock); return _remaining;
} }
/* Release any resources being used by this EthernetUDP instance */ /* Release any resources being used by this EthernetUDP instance */
@ -116,7 +117,10 @@ size_t EthernetUDP::write(const uint8_t *buffer, size_t size)
int EthernetUDP::parsePacket() int EthernetUDP::parsePacket()
{ {
if (available() > 0) // discard any remaining bytes in the last packet
flush();
if (W5100.getRXReceivedSize(_sock) > 0)
{ {
//HACK - hand-parse the UDP packet using TCP recv method //HACK - hand-parse the UDP packet using TCP recv method
uint8_t tmpBuf[8]; uint8_t tmpBuf[8];
@ -128,8 +132,11 @@ int EthernetUDP::parsePacket()
_remoteIP = tmpBuf; _remoteIP = tmpBuf;
_remotePort = tmpBuf[4]; _remotePort = tmpBuf[4];
_remotePort = (_remotePort << 8) + tmpBuf[5]; _remotePort = (_remotePort << 8) + tmpBuf[5];
_remaining = tmpBuf[6];
_remaining = (_remaining << 8) + tmpBuf[7];
// When we get here, any remaining bytes are the data // When we get here, any remaining bytes are the data
ret = available(); ret = _remaining;
} }
return ret; return ret;
} }
@ -140,34 +147,58 @@ int EthernetUDP::parsePacket()
int EthernetUDP::read() int EthernetUDP::read()
{ {
uint8_t byte; uint8_t byte;
if (recv(_sock, &byte, 1) > 0)
if ((_remaining > 0) && (recv(_sock, &byte, 1) > 0))
{ {
// We read things without any problems // We read things without any problems
_remaining--;
return byte; return byte;
} }
// If we get here, there's no data available // If we get here, there's no data available
return -1; return -1;
} }
int EthernetUDP::read(unsigned char* buffer, size_t len) int EthernetUDP::read(unsigned char* buffer, size_t len)
{ {
/* In the readPacket that copes with truncating packets, the buffer was
filled with this code. Not sure why it loops round reading out a byte if (_remaining > 0)
at a time. {
int i;
for(i=0;i<(int)bufLen;i++) { int got;
recv(_sock,tmpBuf,1);
buf[i]=tmpBuf[0]; if (_remaining <= len)
{
// data should fit in the buffer
got = recv(_sock, buffer, _remaining);
}
else
{
// too much data for the buffer,
// grab as much as will fit
got = recv(_sock, buffer, len);
}
if (got > 0)
{
_remaining -= got;
return got;
}
} }
*/
return recv(_sock, buffer, len); // If we get here, there's no data available or recv failed
return -1;
} }
int EthernetUDP::peek() int EthernetUDP::peek()
{ {
uint8_t b; uint8_t b;
// Unlike recv, peek doesn't check to see if there's any data available, so we must // Unlike recv, peek doesn't check to see if there's any data available, so we must.
if (!available()) // If the user hasn't called parsePacket yet then return nothing otherwise they
// may get the UDP header
if (!_remaining)
return -1; return -1;
::peek(_sock, &b); ::peek(_sock, &b);
return b; return b;
@ -175,7 +206,11 @@ int EthernetUDP::peek()
void EthernetUDP::flush() void EthernetUDP::flush()
{ {
while (available()) // could this fail (loop endlessly) if _remaining > 0 and recv in read fails?
// should only occur if recv fails after telling us the data is there, lets
// hope the w5100 always behaves :)
while (_remaining)
{ {
read(); read();
} }

View File

@ -48,6 +48,7 @@ private:
IPAddress _remoteIP; // remote IP address for the incoming packet whilst it's being processed IPAddress _remoteIP; // remote IP address for the incoming packet whilst it's being processed
uint16_t _remotePort; // remote port for the incoming packet whilst it's being processed uint16_t _remotePort; // remote port for the incoming packet whilst it's being processed
uint16_t _offset; // offset into the packet being sent uint16_t _offset; // offset into the packet being sent
uint16_t _remaining; // remaining bytes of incoming packet yet to be processed
public: public:
EthernetUDP(); // Constructor EthernetUDP(); // Constructor

View File

@ -12,7 +12,7 @@
created 18 Dec 2009 created 18 Dec 2009
by David A. Mellis by David A. Mellis
modified 10 August 2010 modified 12 March 2012
by Tom Igoe by Tom Igoe
*/ */
@ -23,14 +23,16 @@
// Enter a MAC address and IP address for your controller below. // Enter a MAC address and IP address for your controller below.
// The IP address will be dependent on your local network. // The IP address will be dependent on your local network.
// gateway and subnet are optional: // gateway and subnet are optional:
byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED }; byte mac[] = {
0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
IPAddress ip(192,168,1, 177); IPAddress ip(192,168,1, 177);
IPAddress gateway(192,168,1, 1); IPAddress gateway(192,168,1, 1);
IPAddress subnet(255, 255, 0, 0); IPAddress subnet(255, 255, 0, 0);
// telnet defaults to port 23 // telnet defaults to port 23
EthernetServer server(23); EthernetServer server(23);
boolean gotAMessage = false; // whether or not you got a message from the client yet boolean alreadyConnected = false; // whether or not the client was connected previously
void setup() { void setup() {
// initialize the ethernet device // initialize the ethernet device
@ -39,6 +41,8 @@ void setup() {
server.begin(); server.begin();
// open the serial port // open the serial port
Serial.begin(9600); Serial.begin(9600);
Serial.print("Chat server address:");
Serial.println(Ethernet.localIP());
} }
void loop() { void loop() {
@ -47,17 +51,24 @@ void loop() {
// when the client sends the first byte, say hello: // when the client sends the first byte, say hello:
if (client) { if (client) {
if (!gotAMessage) { if (!alreadyConnected) {
// clead out the input buffer:
client.flush();
Serial.println("We have a new client"); Serial.println("We have a new client");
client.println("Hello, client!"); client.println("Hello, client!");
gotAMessage = true; alreadyConnected = true;
} }
// read the bytes incoming from the client: if (client.available() > 0) {
char thisChar = client.read(); // read the bytes incoming from the client:
// echo the bytes back to the client: char thisChar = client.read();
server.write(thisChar); // echo the bytes back to the client:
// echo the bytes to the server as well: server.write(thisChar);
Serial.print(thisChar); // echo the bytes to the server as well:
Serial.write(thisChar);
}
} }
} }

View File

@ -6,15 +6,20 @@
the Adafruit Ethernet shield, either one will work, as long as it's got the Adafruit Ethernet shield, either one will work, as long as it's got
a Wiznet Ethernet module on board. a Wiznet Ethernet module on board.
This example has been updated to use version 2.0 of the Pachube.com API.
To make it work, create a feed with a datastream, and give it the ID
sensor1. Or change the code below to match your feed.
Circuit: Circuit:
* Analog sensor attached to analog in 0 * Analog sensor attached to analog in 0
* Ethernet shield attached to pins 10, 11, 12, 13 * Ethernet shield attached to pins 10, 11, 12, 13
created 15 March 2010 created 15 March 2010
updated 26 Oct 2011 updated 16 Mar 2012
by Tom Igoe by Tom Igoe with input from Usman Haque and Joe Saavedra
http://www.tigoe.net/pcomp/code/category/arduinowiring/873 http://arduino.cc/en/Tutorial/PachubeClient
This code is in the public domain. This code is in the public domain.
*/ */
@ -22,6 +27,10 @@
#include <SPI.h> #include <SPI.h>
#include <Ethernet.h> #include <Ethernet.h>
#define APIKEY "YOUR API KEY GOES HERE" // replace your pachube api key here
#define FEEDID 00000 // replace your feed ID
#define USERAGENT "My Project" // user agent is the project name
// assign a MAC address for the ethernet controller. // assign a MAC address for the ethernet controller.
// Newer Ethernet shields have a MAC address printed on a sticker on the shield // Newer Ethernet shields have a MAC address printed on a sticker on the shield
// fill in your address here: // fill in your address here:
@ -34,26 +43,22 @@ IPAddress ip(10,0,1,20);
// initialize the library instance: // initialize the library instance:
EthernetClient client; EthernetClient client;
long lastConnectionTime = 0; // last time you connected to the server, in milliseconds // if you don't want to use DNS (and reduce your sketch size)
boolean lastConnected = false; // state of the connection last time through the main loop // use the numeric IP instead of the name for the server:
const int postingInterval = 10000; //delay between updates to Pachube.com IPAddress server(216,52,233,122); // numeric IP for api.pachube.com
//char server[] = "api.pachube.com"; // name address for pachube API
unsigned long lastConnectionTime = 0; // last time you connected to the server, in milliseconds
boolean lastConnected = false; // state of the connection last time through the main loop
const unsigned long postingInterval = 10*1000; //delay between updates to Pachube.com
void setup() { void setup() {
// start serial port: // start serial port:
Serial.begin(9600); Serial.begin(9600);
// start the Ethernet connection: // start the Ethernet connection:
if (Ethernet.begin(mac) == 0) { if (Ethernet.begin(mac) == 0) {
Serial.println("Failed to configure Ethernet using DHCP"); Serial.println("Failed to configure Ethernet using DHCP");
// no point in carrying on, so do nothing forevermore: // DHCP failed, so use a fixed IP address:
for(;;)
;
}
// give the ethernet module time to boot up:
delay(1000);
// start the Ethernet connection:
if (Ethernet.begin(mac) == 0) {
Serial.println("Failed to configure Ethernet using DHCP");
// Configure manually:
Ethernet.begin(mac, ip); Ethernet.begin(mac, ip);
} }
} }
@ -91,34 +96,43 @@ void loop() {
// this method makes a HTTP connection to the server: // this method makes a HTTP connection to the server:
void sendData(int thisData) { void sendData(int thisData) {
// if there's a successful connection: // if there's a successful connection:
if (client.connect("www.pachube.com", 80)) { if (client.connect(server, 80)) {
Serial.println("connecting..."); Serial.println("connecting...");
// send the HTTP PUT request. // send the HTTP PUT request:
// fill in your feed address here: client.print("PUT /v2/feeds/");
client.print("PUT /api/YOUR_FEED_HERE.csv HTTP/1.1\n"); client.print(FEEDID);
client.print("Host: www.pachube.com\n"); client.println(".csv HTTP/1.1");
// fill in your Pachube API key here: client.println("Host: api.pachube.com");
client.print("X-PachubeApiKey: YOUR_KEY_HERE\n"); client.print("X-PachubeApiKey: ");
client.println(APIKEY);
client.print("User-Agent: ");
client.println(USERAGENT);
client.print("Content-Length: "); client.print("Content-Length: ");
// calculate the length of the sensor reading in bytes: // calculate the length of the sensor reading in bytes:
int thisLength = getLength(thisData); // 8 bytes for "sensor1," + number of digits of the data:
client.println(thisLength, DEC); int thisLength = 8 + getLength(thisData);
client.println(thisLength);
// last pieces of the HTTP PUT request: // last pieces of the HTTP PUT request:
client.print("Content-Type: text/csv\n"); client.println("Content-Type: text/csv");
client.println("Connection: close\n"); client.println("Connection: close");
client.println();
// here's the actual content of the PUT request: // here's the actual content of the PUT request:
client.println(thisData, DEC); client.print("sensor1,");
client.println(thisData);
// note the time that the connection was made:
lastConnectionTime = millis();
} }
else { else {
// if you couldn't make a connection: // if you couldn't make a connection:
Serial.println("connection failed"); Serial.println("connection failed");
Serial.println();
Serial.println("disconnecting.");
client.stop();
} }
// note the time that the connection was made or attempted:
lastConnectionTime = millis();
} }

View File

@ -6,6 +6,10 @@
the Adafruit Ethernet shield, either one will work, as long as it's got the Adafruit Ethernet shield, either one will work, as long as it's got
a Wiznet Ethernet module on board. a Wiznet Ethernet module on board.
This example has been updated to use version 2.0 of the Pachube.com API.
To make it work, create a feed with two datastreams, and give them the IDs
sensor1 and sensor2. Or change the code below to match your feed.
This example uses the String library, which is part of the Arduino core from This example uses the String library, which is part of the Arduino core from
version 0019. version 0019.
@ -14,9 +18,10 @@
* Ethernet shield attached to pins 10, 11, 12, 13 * Ethernet shield attached to pins 10, 11, 12, 13
created 15 March 2010 created 15 March 2010
updated 26 Oct 2011 updated 16 Mar 2012
by Tom Igoe by Tom Igoe with input from Usman Haque and Joe Saavedra
http://arduino.cc/en/Tutorial/PachubeClientString
This code is in the public domain. This code is in the public domain.
*/ */
@ -24,9 +29,14 @@
#include <SPI.h> #include <SPI.h>
#include <Ethernet.h> #include <Ethernet.h>
#define APIKEY "YOUR API KEY GOES HERE" // replace your pachube api key here
#define FEEDID 00000 // replace your feed ID
#define USERAGENT "My Project" // user agent is the project name
// assign a MAC address for the ethernet controller. // assign a MAC address for the ethernet controller.
// fill in your address here: // fill in your address here:
byte mac[] = { byte mac[] = {
0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED}; 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED};
// fill in an available IP address on your network here, // fill in an available IP address on your network here,
// for manual configuration: // for manual configuration:
@ -35,9 +45,14 @@ IPAddress ip(10,0,1,20);
// initialize the library instance: // initialize the library instance:
EthernetClient client; EthernetClient client;
long lastConnectionTime = 0; // last time you connected to the server, in milliseconds // if you don't want to use DNS (and reduce your sketch size)
boolean lastConnected = false; // state of the connection last time through the main loop // use the numeric IP instead of the name for the server:
const int postingInterval = 10000; //delay between updates to Pachube.com //IPAddress server(216,52,233,122); // numeric IP for api.pachube.com
char server[] = "api.pachube.com"; // name address for pachube API
unsigned long lastConnectionTime = 0; // last time you connected to the server, in milliseconds
boolean lastConnected = false; // state of the connection last time through the main loop
const unsigned long postingInterval = 10*1000; //delay between updates to Pachube.com
void setup() { void setup() {
// start serial port: // start serial port:
@ -47,7 +62,7 @@ void setup() {
// start the Ethernet connection: // start the Ethernet connection:
if (Ethernet.begin(mac) == 0) { if (Ethernet.begin(mac) == 0) {
Serial.println("Failed to configure Ethernet using DHCP"); Serial.println("Failed to configure Ethernet using DHCP");
// Configure manually: // DHCP failed, so use a fixed IP address:
Ethernet.begin(mac, ip); Ethernet.begin(mac, ip);
} }
} }
@ -56,13 +71,15 @@ void loop() {
// read the analog sensor: // read the analog sensor:
int sensorReading = analogRead(A0); int sensorReading = analogRead(A0);
// convert the data to a String to send it: // convert the data to a String to send it:
String dataString = String(sensorReading);
String dataString = "sensor1,";
dataString += sensorReading;
// you can append multiple readings to this String if your // you can append multiple readings to this String if your
// pachube feed is set up to handle multiple values: // pachube feed is set up to handle multiple values:
int otherSensorReading = analogRead(A1); int otherSensorReading = analogRead(A1);
dataString += ","; dataString += "\nsensor2,";
dataString += String(otherSensorReading); dataString += otherSensorReading;
// if there's incoming data from the net connection. // if there's incoming data from the net connection.
// send it out the serial port. This is for debugging // send it out the serial port. This is for debugging
@ -93,29 +110,36 @@ void loop() {
// this method makes a HTTP connection to the server: // this method makes a HTTP connection to the server:
void sendData(String thisData) { void sendData(String thisData) {
// if there's a successful connection: // if there's a successful connection:
if (client.connect("www.pachube.com", 80)) { if (client.connect(server, 80)) {
Serial.println("connecting..."); Serial.println("connecting...");
// send the HTTP PUT request. // send the HTTP PUT request:
// fill in your feed address here: client.print("PUT /v2/feeds/");
client.print("PUT /api/YOUR_FEED_HERE.csv HTTP/1.1\n"); client.print(FEEDID);
client.print("Host: www.pachube.com\n"); client.println(".csv HTTP/1.1");
// fill in your Pachube API key here: client.println("Host: api.pachube.com");
client.print("X-PachubeApiKey: YOUR_KEY_HERE\n"); client.print("X-PachubeApiKey: ");
client.println(APIKEY);
client.print("User-Agent: ");
client.println(USERAGENT);
client.print("Content-Length: "); client.print("Content-Length: ");
client.println(thisData.length(), DEC); client.println(thisData.length());
// last pieces of the HTTP PUT request: // last pieces of the HTTP PUT request:
client.print("Content-Type: text/csv\n"); client.println("Content-Type: text/csv");
client.println("Connection: close\n"); client.println("Connection: close");
client.println();
// here's the actual content of the PUT request: // here's the actual content of the PUT request:
client.println(thisData); client.println(thisData);
// note the time that the connection was made:
lastConnectionTime = millis();
} }
else { else {
// if you couldn't make a connection: // if you couldn't make a connection:
Serial.println("connection failed"); Serial.println("connection failed");
Serial.println();
Serial.println("disconnecting.");
client.stop();
} }
// note the time that the connection was made or attempted:
lastConnectionTime = millis();
} }

View File

@ -14,7 +14,7 @@
version 0019. version 0019.
Circuit: Circuit:
* Ethernet shield attached to pins 10, 11, 12, 13 * Ethernet shield attached to pins 10, 11, 12, 13
created 21 May 2011 created 21 May 2011
by Tom Igoe by Tom Igoe
@ -35,12 +35,12 @@ IPAddress ip(192,168,1,20);
// initialize the library instance: // initialize the library instance:
EthernetClient client; EthernetClient client;
const int requestInterval = 60000; // delay between requests const unsigned long requestInterval = 60000; // delay between requests
char serverName[] = "api.twitter.com"; // twitter URL char serverName[] = "api.twitter.com"; // twitter URL
boolean requested; // whether you've made a request since connecting boolean requested; // whether you've made a request since connecting
long lastAttemptTime = 0; // last time you connected to the server, in milliseconds unsigned long lastAttemptTime = 0; // last time you connected to the server, in milliseconds
String currentLine = ""; // string to hold the text from server String currentLine = ""; // string to hold the text from server
String tweet = ""; // string to hold the tweet String tweet = ""; // string to hold the tweet
@ -51,13 +51,17 @@ void setup() {
currentLine.reserve(256); currentLine.reserve(256);
tweet.reserve(150); tweet.reserve(150);
// initialize serial: // initialize serial:
Serial.begin(9600); Serial.begin(9600);
// attempt a DHCP connection: // attempt a DHCP connection:
Serial.println("Attempting to get an IP address using DHCP:");
if (!Ethernet.begin(mac)) { if (!Ethernet.begin(mac)) {
// if DHCP fails, start with a hard-coded address: // if DHCP fails, start with a hard-coded address:
Serial.println("failed to get an IP address using DHCP, trying manually");
Ethernet.begin(mac, ip); Ethernet.begin(mac, ip);
} }
Serial.print("My address:");
Serial.println(Ethernet.localIP());
// connect to Twitter: // connect to Twitter:
connectToServer(); connectToServer();
} }
@ -114,7 +118,7 @@ void connectToServer() {
Serial.println("connecting to server..."); Serial.println("connecting to server...");
if (client.connect(serverName, 80)) { if (client.connect(serverName, 80)) {
Serial.println("making HTTP request..."); Serial.println("making HTTP request...");
// make HTTP GET request to twitter: // make HTTP GET request to twitter:
client.println("GET /1/statuses/user_timeline.xml?screen_name=arduino&count=1 HTTP/1.1"); client.println("GET /1/statuses/user_timeline.xml?screen_name=arduino&count=1 HTTP/1.1");
client.println("HOST: api.twitter.com"); client.println("HOST: api.twitter.com");
client.println(); client.println();
@ -122,3 +126,4 @@ void connectToServer() {
// note the time of this connect attempt: // note the time of this connect attempt:
lastAttemptTime = millis(); lastAttemptTime = millis();
} }

View File

@ -10,7 +10,7 @@
created 18 Dec 2009 created 18 Dec 2009
by David A. Mellis by David A. Mellis
modified 4 Sep 2010 modified 20 Mar 2012
by Tom Igoe by Tom Igoe
*/ */
@ -20,7 +20,8 @@
// Enter a MAC address and IP address for your controller below. // Enter a MAC address and IP address for your controller below.
// The IP address will be dependent on your local network: // The IP address will be dependent on your local network:
byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED }; byte mac[] = {
0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
IPAddress ip(192,168,1, 177); IPAddress ip(192,168,1, 177);
// Initialize the Ethernet server library // Initialize the Ethernet server library
@ -28,23 +29,27 @@ IPAddress ip(192,168,1, 177);
// (port 80 is default for HTTP): // (port 80 is default for HTTP):
EthernetServer server(80); EthernetServer server(80);
void setup() void setup() {
{ Serial.begin(9600);
// start the Ethernet connection and the server: // start the Ethernet connection and the server:
Ethernet.begin(mac, ip); Ethernet.begin(mac, ip);
server.begin(); server.begin();
Serial.print("server is at ");
Serial.println(Ethernet.localIP());
} }
void loop()
{ void loop() {
// listen for incoming clients // listen for incoming clients
EthernetClient client = server.available(); EthernetClient client = server.available();
if (client) { if (client) {
Serial.println("new client");
// an http request ends with a blank line // an http request ends with a blank line
boolean currentLineIsBlank = true; boolean currentLineIsBlank = true;
while (client.connected()) { while (client.connected()) {
if (client.available()) { if (client.available()) {
char c = client.read(); char c = client.read();
Serial.write(c);
// if you've gotten to the end of the line (received a newline // if you've gotten to the end of the line (received a newline
// character) and the line is blank, the http request has ended, // character) and the line is blank, the http request has ended,
// so you can send a reply // so you can send a reply
@ -52,16 +57,22 @@ void loop()
// send a standard http response header // send a standard http response header
client.println("HTTP/1.1 200 OK"); client.println("HTTP/1.1 200 OK");
client.println("Content-Type: text/html"); client.println("Content-Type: text/html");
client.println("Connnection: close");
client.println(); client.println();
client.println("<!DOCTYPE HTML>");
client.println("<html>");
// add a meta refresh tag, so the browser pulls again every 5 seconds:
client.println("<meta http-equiv=\"refresh\" content=\"5\">");
// output the value of each analog input pin // output the value of each analog input pin
for (int analogChannel = 0; analogChannel < 6; analogChannel++) { for (int analogChannel = 0; analogChannel < 6; analogChannel++) {
int sensorReading = analogRead(analogChannel);
client.print("analog input "); client.print("analog input ");
client.print(analogChannel); client.print(analogChannel);
client.print(" is "); client.print(" is ");
client.print(analogRead(analogChannel)); client.print(sensorReading);
client.println("<br />"); client.println("<br />");
} }
client.println("</html>");
break; break;
} }
if (c == '\n') { if (c == '\n') {
@ -78,5 +89,7 @@ void loop()
delay(1); delay(1);
// close the connection: // close the connection:
client.stop(); client.stop();
Serial.println("client disonnected");
} }
} }

View File

@ -56,7 +56,7 @@ static UNUSEDOK int FreeRam(void) {
* \param[in] str Pointer to string stored in flash memory. * \param[in] str Pointer to string stored in flash memory.
*/ */
static NOINLINE void SerialPrint_P(PGM_P str) { static NOINLINE void SerialPrint_P(PGM_P str) {
for (uint8_t c; (c = pgm_read_byte(str)); str++) Serial.print(c); for (uint8_t c; (c = pgm_read_byte(str)); str++) Serial.write(c);
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
/** /**

View File

@ -89,7 +89,7 @@ static inline void handle_interrupts(timer16_Sequence_t timer, volatile uint16_t
} }
else { else {
// finished all channels so wait for the refresh period to expire before starting over // finished all channels so wait for the refresh period to expire before starting over
if( (unsigned)*TCNTn < (usToTicks(REFRESH_INTERVAL) + 4) ) // allow a few ticks to ensure the next OCR1A not missed if( ((unsigned)*TCNTn) + 4 < usToTicks(REFRESH_INTERVAL) ) // allow a few ticks to ensure the next OCR1A not missed
*OCRnA = (unsigned int)usToTicks(REFRESH_INTERVAL); *OCRnA = (unsigned int)usToTicks(REFRESH_INTERVAL);
else else
*OCRnA = *TCNTn + 4; // at least REFRESH_INTERVAL has elapsed *OCRnA = *TCNTn + 4; // at least REFRESH_INTERVAL has elapsed
@ -298,7 +298,7 @@ void Servo::writeMicroseconds(int value)
{ {
// calculate and store the values for the given channel // calculate and store the values for the given channel
byte channel = this->servoIndex; byte channel = this->servoIndex;
if( (channel >= 0) && (channel < MAX_SERVOS) ) // ensure channel is valid if( (channel < MAX_SERVOS) ) // ensure channel is valid
{ {
if( value < SERVO_MIN() ) // ensure pulse width is valid if( value < SERVO_MIN() ) // ensure pulse width is valid
value = SERVO_MIN(); value = SERVO_MIN();

View File

@ -1,6 +1,23 @@
/*
Software serial multple serial test
Receives from the hardware serial, sends to software serial.
Receives from software serial, sends to hardware serial.
The circuit:
* RX is digital pin 2 (connect to TX of other device)
* TX is digital pin 3 (connect to RX of other device)
created back in the mists of time
by Tom Igoe
based on Mikal Hart's example
This example code is in the public domain.
*/
#include <SoftwareSerial.h> #include <SoftwareSerial.h>
SoftwareSerial mySerial(2, 3); SoftwareSerial mySerial(2, 3); // RX, TX
void setup() void setup()
{ {

View File

@ -15,6 +15,8 @@
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
Modified 2012 by Todd Krein (todd@krein.org) to implement repeated starts
*/ */
extern "C" { extern "C" {
@ -73,14 +75,14 @@ void TwoWire::begin(int address)
begin((uint8_t)address); begin((uint8_t)address);
} }
uint8_t TwoWire::requestFrom(uint8_t address, uint8_t quantity) uint8_t TwoWire::requestFrom(uint8_t address, uint8_t quantity, uint8_t sendStop)
{ {
// clamp to buffer length // clamp to buffer length
if(quantity > BUFFER_LENGTH){ if(quantity > BUFFER_LENGTH){
quantity = BUFFER_LENGTH; quantity = BUFFER_LENGTH;
} }
// perform blocking read into buffer // perform blocking read into buffer
uint8_t read = twi_readFrom(address, rxBuffer, quantity); uint8_t read = twi_readFrom(address, rxBuffer, quantity, sendStop);
// set rx buffer iterator vars // set rx buffer iterator vars
rxBufferIndex = 0; rxBufferIndex = 0;
rxBufferLength = read; rxBufferLength = read;
@ -88,9 +90,19 @@ uint8_t TwoWire::requestFrom(uint8_t address, uint8_t quantity)
return read; return read;
} }
uint8_t TwoWire::requestFrom(uint8_t address, uint8_t quantity)
{
return requestFrom((uint8_t)address, (uint8_t)quantity, (uint8_t)true);
}
uint8_t TwoWire::requestFrom(int address, int quantity) uint8_t TwoWire::requestFrom(int address, int quantity)
{ {
return requestFrom((uint8_t)address, (uint8_t)quantity); return requestFrom((uint8_t)address, (uint8_t)quantity, (uint8_t)true);
}
uint8_t TwoWire::requestFrom(int address, int quantity, int sendStop)
{
return requestFrom((uint8_t)address, (uint8_t)quantity, (uint8_t)sendStop);
} }
void TwoWire::beginTransmission(uint8_t address) void TwoWire::beginTransmission(uint8_t address)
@ -109,10 +121,23 @@ void TwoWire::beginTransmission(int address)
beginTransmission((uint8_t)address); beginTransmission((uint8_t)address);
} }
uint8_t TwoWire::endTransmission(void) //
// Originally, 'endTransmission' was an f(void) function.
// It has been modified to take one parameter indicating
// whether or not a STOP should be performed on the bus.
// Calling endTransmission(false) allows a sketch to
// perform a repeated start.
//
// WARNING: Nothing in the library keeps track of whether
// the bus tenure has been properly ended with a STOP. It
// is very possible to leave the bus in a hung state if
// no call to endTransmission(true) is made. Some I2C
// devices will behave oddly if they do not see a STOP.
//
uint8_t TwoWire::endTransmission(uint8_t sendStop)
{ {
// transmit buffer (blocking) // transmit buffer (blocking)
int8_t ret = twi_writeTo(txAddress, txBuffer, txBufferLength, 1); int8_t ret = twi_writeTo(txAddress, txBuffer, txBufferLength, 1, sendStop);
// reset tx buffer iterator vars // reset tx buffer iterator vars
txBufferIndex = 0; txBufferIndex = 0;
txBufferLength = 0; txBufferLength = 0;
@ -121,6 +146,14 @@ uint8_t TwoWire::endTransmission(void)
return ret; return ret;
} }
// This provides backwards compatibility with the original
// definition, and expected behaviour, of endTransmission
//
uint8_t TwoWire::endTransmission(void)
{
return endTransmission(true);
}
// must be called in: // must be called in:
// slave tx event callback // slave tx event callback
// or after beginTransmission(address) // or after beginTransmission(address)

View File

@ -15,6 +15,8 @@
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
Modified 2012 by Todd Krein (todd@krein.org) to implement repeated starts
*/ */
#ifndef TwoWire_h #ifndef TwoWire_h
@ -50,8 +52,11 @@ class TwoWire : public Stream
void beginTransmission(uint8_t); void beginTransmission(uint8_t);
void beginTransmission(int); void beginTransmission(int);
uint8_t endTransmission(void); uint8_t endTransmission(void);
uint8_t endTransmission(uint8_t);
uint8_t requestFrom(uint8_t, uint8_t); uint8_t requestFrom(uint8_t, uint8_t);
uint8_t requestFrom(uint8_t, uint8_t, uint8_t);
uint8_t requestFrom(int, int); uint8_t requestFrom(int, int);
uint8_t requestFrom(int, int, int);
virtual size_t write(uint8_t); virtual size_t write(uint8_t);
virtual size_t write(const uint8_t *, size_t); virtual size_t write(const uint8_t *, size_t);
virtual int available(void); virtual int available(void);

View File

@ -15,6 +15,8 @@
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
Modified 2012 by Todd Krein (todd@krein.org) to implement repeated starts
*/ */
#include <math.h> #include <math.h>
@ -37,14 +39,16 @@
#include "twi.h" #include "twi.h"
static volatile uint8_t twi_state; static volatile uint8_t twi_state;
static uint8_t twi_slarw; static volatile uint8_t twi_slarw;
static volatile uint8_t twi_sendStop; // should the transaction end with a stop
static volatile uint8_t twi_inRepStart; // in the middle of a repeated start
static void (*twi_onSlaveTransmit)(void); static void (*twi_onSlaveTransmit)(void);
static void (*twi_onSlaveReceive)(uint8_t*, int); static void (*twi_onSlaveReceive)(uint8_t*, int);
static uint8_t twi_masterBuffer[TWI_BUFFER_LENGTH]; static uint8_t twi_masterBuffer[TWI_BUFFER_LENGTH];
static volatile uint8_t twi_masterBufferIndex; static volatile uint8_t twi_masterBufferIndex;
static uint8_t twi_masterBufferLength; static volatile uint8_t twi_masterBufferLength;
static uint8_t twi_txBuffer[TWI_BUFFER_LENGTH]; static uint8_t twi_txBuffer[TWI_BUFFER_LENGTH];
static volatile uint8_t twi_txBufferIndex; static volatile uint8_t twi_txBufferIndex;
@ -65,6 +69,8 @@ void twi_init(void)
{ {
// initialize state // initialize state
twi_state = TWI_READY; twi_state = TWI_READY;
twi_sendStop = true; // default value
twi_inRepStart = false;
// activate internal pullups for twi. // activate internal pullups for twi.
digitalWrite(SDA, 1); digitalWrite(SDA, 1);
@ -103,9 +109,10 @@ void twi_setAddress(uint8_t address)
* Input address: 7bit i2c device address * Input address: 7bit i2c device address
* data: pointer to byte array * data: pointer to byte array
* length: number of bytes to read into array * length: number of bytes to read into array
* sendStop: Boolean indicating whether to send a stop at the end
* Output number of bytes read * Output number of bytes read
*/ */
uint8_t twi_readFrom(uint8_t address, uint8_t* data, uint8_t length) uint8_t twi_readFrom(uint8_t address, uint8_t* data, uint8_t length, uint8_t sendStop)
{ {
uint8_t i; uint8_t i;
@ -119,6 +126,7 @@ uint8_t twi_readFrom(uint8_t address, uint8_t* data, uint8_t length)
continue; continue;
} }
twi_state = TWI_MRX; twi_state = TWI_MRX;
twi_sendStop = sendStop;
// reset error state (0xFF.. no error occured) // reset error state (0xFF.. no error occured)
twi_error = 0xFF; twi_error = 0xFF;
@ -135,8 +143,20 @@ uint8_t twi_readFrom(uint8_t address, uint8_t* data, uint8_t length)
twi_slarw = TW_READ; twi_slarw = TW_READ;
twi_slarw |= address << 1; twi_slarw |= address << 1;
// send start condition if (true == twi_inRepStart) {
TWCR = _BV(TWEN) | _BV(TWIE) | _BV(TWEA) | _BV(TWINT) | _BV(TWSTA); // if we're in the repeated start state, then we've already sent the start,
// (@@@ we hope), and the TWI statemachine is just waiting for the address byte.
// We need to remove ourselves from the repeated start state before we enable interrupts,
// since the ISR is ASYNC, and we could get confused if we hit the ISR before cleaning
// up. Also, don't enable the START interrupt. There may be one pending from the
// repeated start that we sent outselves, and that would really confuse things.
twi_inRepStart = false; // remember, we're dealing with an ASYNC ISR
TWDR = twi_slarw;
TWCR = _BV(TWINT) | _BV(TWEA) | _BV(TWEN) | _BV(TWIE); // enable INTs, but not START
}
else
// send start condition
TWCR = _BV(TWEN) | _BV(TWIE) | _BV(TWEA) | _BV(TWINT) | _BV(TWSTA);
// wait for read operation to complete // wait for read operation to complete
while(TWI_MRX == twi_state){ while(TWI_MRX == twi_state){
@ -162,13 +182,14 @@ uint8_t twi_readFrom(uint8_t address, uint8_t* data, uint8_t length)
* data: pointer to byte array * data: pointer to byte array
* length: number of bytes in array * length: number of bytes in array
* wait: boolean indicating to wait for write or not * wait: boolean indicating to wait for write or not
* sendStop: boolean indicating whether or not to send a stop at the end
* Output 0 .. success * Output 0 .. success
* 1 .. length to long for buffer * 1 .. length to long for buffer
* 2 .. address send, NACK received * 2 .. address send, NACK received
* 3 .. data send, NACK received * 3 .. data send, NACK received
* 4 .. other twi error (lost bus arbitration, bus error, ..) * 4 .. other twi error (lost bus arbitration, bus error, ..)
*/ */
uint8_t twi_writeTo(uint8_t address, uint8_t* data, uint8_t length, uint8_t wait) uint8_t twi_writeTo(uint8_t address, uint8_t* data, uint8_t length, uint8_t wait, uint8_t sendStop)
{ {
uint8_t i; uint8_t i;
@ -182,6 +203,7 @@ uint8_t twi_writeTo(uint8_t address, uint8_t* data, uint8_t length, uint8_t wait
continue; continue;
} }
twi_state = TWI_MTX; twi_state = TWI_MTX;
twi_sendStop = sendStop;
// reset error state (0xFF.. no error occured) // reset error state (0xFF.. no error occured)
twi_error = 0xFF; twi_error = 0xFF;
@ -198,8 +220,23 @@ uint8_t twi_writeTo(uint8_t address, uint8_t* data, uint8_t length, uint8_t wait
twi_slarw = TW_WRITE; twi_slarw = TW_WRITE;
twi_slarw |= address << 1; twi_slarw |= address << 1;
// send start condition // if we're in a repeated start, then we've already sent the START
TWCR = _BV(TWEN) | _BV(TWIE) | _BV(TWEA) | _BV(TWINT) | _BV(TWSTA); // in the ISR. Don't do it again.
//
if (true == twi_inRepStart) {
// if we're in the repeated start state, then we've already sent the start,
// (@@@ we hope), and the TWI statemachine is just waiting for the address byte.
// We need to remove ourselves from the repeated start state before we enable interrupts,
// since the ISR is ASYNC, and we could get confused if we hit the ISR before cleaning
// up. Also, don't enable the START interrupt. There may be one pending from the
// repeated start that we sent outselves, and that would really confuse things.
twi_inRepStart = false; // remember, we're dealing with an ASYNC ISR
TWDR = twi_slarw;
TWCR = _BV(TWINT) | _BV(TWEA) | _BV(TWEN) | _BV(TWIE); // enable INTs, but not START
}
else
// send start condition
TWCR = _BV(TWINT) | _BV(TWEA) | _BV(TWEN) | _BV(TWIE) | _BV(TWSTA); // enable INTs
// wait for write operation to complete // wait for write operation to complete
while(wait && (TWI_MTX == twi_state)){ while(wait && (TWI_MTX == twi_state)){
@ -343,7 +380,16 @@ SIGNAL(TWI_vect)
TWDR = twi_masterBuffer[twi_masterBufferIndex++]; TWDR = twi_masterBuffer[twi_masterBufferIndex++];
twi_reply(1); twi_reply(1);
}else{ }else{
twi_stop(); if (twi_sendStop)
twi_stop();
else {
twi_inRepStart = true; // we're gonna send the START
// don't enable the interrupt. We'll generate the start, but we
// avoid handling the interrupt until we're in the next transaction,
// at the point where we would normally issue the start.
TWCR = _BV(TWINT) | _BV(TWSTA)| _BV(TWEN) ;
twi_state = TWI_READY;
}
} }
break; break;
case TW_MT_SLA_NACK: // address sent, nack received case TW_MT_SLA_NACK: // address sent, nack received
@ -374,6 +420,17 @@ SIGNAL(TWI_vect)
case TW_MR_DATA_NACK: // data received, nack sent case TW_MR_DATA_NACK: // data received, nack sent
// put final byte into buffer // put final byte into buffer
twi_masterBuffer[twi_masterBufferIndex++] = TWDR; twi_masterBuffer[twi_masterBufferIndex++] = TWDR;
if (twi_sendStop)
twi_stop();
else {
twi_inRepStart = true; // we're gonna send the START
// don't enable the interrupt. We'll generate the start, but we
// avoid handling the interrupt until we're in the next transaction,
// at the point where we would normally issue the start.
TWCR = _BV(TWINT) | _BV(TWSTA)| _BV(TWEN) ;
twi_state = TWI_READY;
}
break;
case TW_MR_SLA_NACK: // address sent, nack received case TW_MR_SLA_NACK: // address sent, nack received
twi_stop(); twi_stop();
break; break;

View File

@ -40,8 +40,8 @@
void twi_init(void); void twi_init(void);
void twi_setAddress(uint8_t); void twi_setAddress(uint8_t);
uint8_t twi_readFrom(uint8_t, uint8_t*, uint8_t); uint8_t twi_readFrom(uint8_t, uint8_t*, uint8_t, uint8_t);
uint8_t twi_writeTo(uint8_t, uint8_t*, uint8_t, uint8_t); uint8_t twi_writeTo(uint8_t, uint8_t*, uint8_t, uint8_t, uint8_t);
uint8_t twi_transmit(const uint8_t*, uint8_t); uint8_t twi_transmit(const uint8_t*, uint8_t);
void twi_attachSlaveRxEvent( void (*)(uint8_t*, int) ); void twi_attachSlaveRxEvent( void (*)(uint8_t*, int) );
void twi_attachSlaveTxEvent( void (*)(void) ); void twi_attachSlaveTxEvent( void (*)(void) );

View File

@ -35,29 +35,29 @@
#define RXLED0 PORTB |= (1<<0) #define RXLED0 PORTB |= (1<<0)
#define RXLED1 PORTB &= ~(1<<0) #define RXLED1 PORTB &= ~(1<<0)
const static uint8_t SDA = 2; static const uint8_t SDA = 2;
const static uint8_t SCL = 3; static const uint8_t SCL = 3;
// Map SPI port to 'new' pins D14..D17 // Map SPI port to 'new' pins D14..D17
const static uint8_t SS = 17; static const uint8_t SS = 17;
const static uint8_t MOSI = 16; static const uint8_t MOSI = 16;
const static uint8_t MISO = 14; static const uint8_t MISO = 14;
const static uint8_t SCK = 15; static const uint8_t SCK = 15;
// Mapping of analog pins as digital I/O // Mapping of analog pins as digital I/O
// A6-A11 share with digital pins // A6-A11 share with digital pins
const static uint8_t A0 = 18; static const uint8_t A0 = 18;
const static uint8_t A1 = 19; static const uint8_t A1 = 19;
const static uint8_t A2 = 20; static const uint8_t A2 = 20;
const static uint8_t A3 = 21; static const uint8_t A3 = 21;
const static uint8_t A4 = 22; static const uint8_t A4 = 22;
const static uint8_t A5 = 23; static const uint8_t A5 = 23;
const static uint8_t A6 = 24; // D4 static const uint8_t A6 = 24; // D4
const static uint8_t A7 = 25; // D6 static const uint8_t A7 = 25; // D6
const static uint8_t A8 = 26; // D8 static const uint8_t A8 = 26; // D8
const static uint8_t A9 = 27; // D9 static const uint8_t A9 = 27; // D9
const static uint8_t A10 = 28; // D10 static const uint8_t A10 = 28; // D10
const static uint8_t A11 = 29; // D12 static const uint8_t A11 = 29; // D12
// __AVR_ATmega32U4__ has an unusual mapping of pins to channels // __AVR_ATmega32U4__ has an unusual mapping of pins to channels
extern const uint8_t PROGMEM analog_pin_to_channel_PGM[]; extern const uint8_t PROGMEM analog_pin_to_channel_PGM[];

View File

@ -32,31 +32,31 @@
#define analogInputToDigitalPin(p) ((p < 16) ? (p) + 54 : -1) #define analogInputToDigitalPin(p) ((p < 16) ? (p) + 54 : -1)
#define digitalPinHasPWM(p) (((p) >= 2 && (p) <= 13) || ((p) >= 44 && (p)<= 46)) #define digitalPinHasPWM(p) (((p) >= 2 && (p) <= 13) || ((p) >= 44 && (p)<= 46))
const static uint8_t SS = 53; static const uint8_t SS = 53;
const static uint8_t MOSI = 51; static const uint8_t MOSI = 51;
const static uint8_t MISO = 50; static const uint8_t MISO = 50;
const static uint8_t SCK = 52; static const uint8_t SCK = 52;
const static uint8_t SDA = 20; static const uint8_t SDA = 20;
const static uint8_t SCL = 21; static const uint8_t SCL = 21;
const static uint8_t LED_BUILTIN = 13; static const uint8_t LED_BUILTIN = 13;
const static uint8_t A0 = 54; static const uint8_t A0 = 54;
const static uint8_t A1 = 55; static const uint8_t A1 = 55;
const static uint8_t A2 = 56; static const uint8_t A2 = 56;
const static uint8_t A3 = 57; static const uint8_t A3 = 57;
const static uint8_t A4 = 58; static const uint8_t A4 = 58;
const static uint8_t A5 = 59; static const uint8_t A5 = 59;
const static uint8_t A6 = 60; static const uint8_t A6 = 60;
const static uint8_t A7 = 61; static const uint8_t A7 = 61;
const static uint8_t A8 = 62; static const uint8_t A8 = 62;
const static uint8_t A9 = 63; static const uint8_t A9 = 63;
const static uint8_t A10 = 64; static const uint8_t A10 = 64;
const static uint8_t A11 = 65; static const uint8_t A11 = 65;
const static uint8_t A12 = 66; static const uint8_t A12 = 66;
const static uint8_t A13 = 67; static const uint8_t A13 = 67;
const static uint8_t A14 = 68; static const uint8_t A14 = 68;
const static uint8_t A15 = 69; static const uint8_t A15 = 69;
// A majority of the pins are NOT PCINTs, SO BE WARNED (i.e. you cannot use them as receive pins) // 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): // Only pins available for RECEIVE (TRANSMIT can be on any pin):

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