Skip to content

Commit 7ad4de5

Browse files
committed
Added support for USB serial port 1200bps touch (Leonardo)
1 parent 3fe9246 commit 7ad4de5

File tree

1 file changed

+113
-1
lines changed

1 file changed

+113
-1
lines changed

Diff for: app/src/processing/app/debug/BasicUploader.java

+113-1
Original file line numberDiff line numberDiff line change
@@ -28,12 +28,18 @@
2828

2929
package processing.app.debug;
3030

31+
import java.util.ArrayList;
32+
import java.util.List;
33+
3134
import processing.app.Base;
3235
import processing.app.Preferences;
36+
import processing.app.Serial;
3337
import processing.app.SerialException;
3438
import processing.app.helpers.PreferencesMap;
3539
import processing.app.helpers.StringReplacer;
3640

41+
import static processing.app.I18n._;
42+
3743
public class BasicUploader extends Uploader {
3844

3945
public boolean uploadUsingPreferences(String buildPath, String className,
@@ -50,14 +56,101 @@ public boolean uploadUsingPreferences(String buildPath, String className,
5056
if (usingProgrammer || prefs.get("upload.protocol") == null) {
5157
return uploadUsingProgrammer(buildPath, className);
5258
}
59+
60+
// need to do a little dance for Leonardo and derivatives:
61+
// open then close the port at the magic baudrate (usually 1200 bps) first
62+
// to signal to the sketch that it should reset into bootloader. after doing
63+
// this wait a moment for the bootloader to enumerate. On Windows, also must
64+
// deal with the fact that the COM port number changes from bootloader to
65+
// sketch.
66+
String use1200bpsTouch = prefs.get("upload.use_1200bps_touch");
67+
boolean doTouch = use1200bpsTouch != null && use1200bpsTouch.equals("true");
68+
if (doTouch) {
69+
String uploadPort = prefs.get("serial.port");
70+
String caterinaUploadPort = null;
71+
try {
72+
// Toggle 1200 bps on selected serial port to force board reset.
73+
List<String> before = Serial.list();
74+
if (before.contains(uploadPort)) {
75+
if (verbose || Preferences.getBoolean("upload.verbose"))
76+
System.out
77+
.println(_("Forcing reset using 1200bps open/close on port ") +
78+
uploadPort);
79+
Serial.touchPort(uploadPort, 1200);
80+
81+
// Scanning for available ports seems to open the port or
82+
// otherwise assert DTR, which would cancel the WDT reset if
83+
// it happened within 250 ms. So we wait until the reset should
84+
// have already occured before we start scanning.
85+
if (!Base.isMacOS())
86+
Thread.sleep(300);
87+
}
88+
// Wait for a port to appear on the list
89+
int elapsed = 0;
90+
while (elapsed < 10000) {
91+
List<String> now = Serial.list();
92+
List<String> diff = new ArrayList<String>(now);
93+
diff.removeAll(before);
94+
if (verbose || Preferences.getBoolean("upload.verbose")) {
95+
System.out.print("PORTS {");
96+
for (String p : before)
97+
System.out.print(p + ", ");
98+
System.out.print("} / {");
99+
for (String p : now)
100+
System.out.print(p + ", ");
101+
System.out.print("} => {");
102+
for (String p : diff)
103+
System.out.print(p + ", ");
104+
System.out.println("}");
105+
}
106+
if (diff.size() > 0) {
107+
caterinaUploadPort = diff.get(0);
108+
if (verbose || Preferences.getBoolean("upload.verbose"))
109+
System.out.println("Found Leonardo upload port: " +
110+
caterinaUploadPort);
111+
break;
112+
}
113+
114+
// Keep track of port that disappears
115+
before = now;
116+
Thread.sleep(250);
117+
elapsed += 250;
118+
119+
// On Windows, it can take a long time for the port to disappear and
120+
// come back, so use a longer time out before assuming that the
121+
// selected
122+
// port is the bootloader (not the sketch).
123+
if (((!Base.isWindows() && elapsed >= 500) || elapsed >= 5000) &&
124+
now.contains(uploadPort)) {
125+
if (verbose || Preferences.getBoolean("upload.verbose"))
126+
System.out
127+
.println("Uploading using selected port: " + uploadPort);
128+
caterinaUploadPort = uploadPort;
129+
break;
130+
}
131+
}
132+
if (caterinaUploadPort == null)
133+
// Something happened while detecting port
134+
throw new RunnerException(
135+
_("Couldn’t find a Leonardo on the selected port. Check that you have the correct port selected. If it is correct, try pressing the board's reset button after initiating the upload."));
53136

137+
uploadPort = caterinaUploadPort;
138+
} catch (SerialException e) {
139+
throw new RunnerException(e.getMessage());
140+
} catch (InterruptedException e) {
141+
throw new RunnerException(e.getMessage());
142+
}
143+
prefs.put("serial.port", uploadPort);
144+
}
145+
54146
prefs.put("build.path", buildPath);
55147
prefs.put("build.project_name", className);
56148
if (verbose)
57149
prefs.put("upload.verbose", prefs.get("upload.params.verbose"));
58150
else
59151
prefs.put("upload.verbose", prefs.get("upload.params.quiet"));
60152

153+
boolean uploadResult;
61154
try {
62155
// if (prefs.get("upload.disable_flushing") == null
63156
// || prefs.get("upload.disable_flushing").toLowerCase().equals("false")) {
@@ -66,10 +159,29 @@ public boolean uploadUsingPreferences(String buildPath, String className,
66159

67160
String pattern = prefs.get("upload.pattern");
68161
String[] cmd = StringReplacer.formatAndSplit(pattern, prefs, true);
69-
return executeUploadCommand(cmd);
162+
uploadResult = executeUploadCommand(cmd);
70163
} catch (Exception e) {
71164
throw new RunnerException(e);
72165
}
166+
167+
// For Leonardo wait until the bootloader serial port disconnects and the
168+
// sketch serial port reconnects (or timeout after a few seconds if the
169+
// sketch port never comes back). Doing this saves users from accidentally
170+
// opening Serial Monitor on the soon-to-be-orphaned bootloader port.
171+
try {
172+
if (uploadResult && doTouch) {
173+
Thread.sleep(500);
174+
long timeout = System.currentTimeMillis() + 2000;
175+
while (timeout > System.currentTimeMillis()) {
176+
List<String> portList = Serial.list();
177+
if (portList.contains(Preferences.get("serial.port")))
178+
break;
179+
Thread.sleep(100);
180+
}
181+
}
182+
} catch (InterruptedException ex) {
183+
}
184+
return uploadResult;
73185
}
74186

75187
public boolean uploadUsingProgrammer(String buildPath, String className)

0 commit comments

Comments
 (0)