mirror of
https://github.com/arduino/Arduino.git
synced 2024-12-10 21:24:12 +01:00
Removed some old code, including PdePreprocessor and OldCompiler
This commit is contained in:
parent
4aeac60bea
commit
6128dace42
@ -23,7 +23,6 @@ import javax.swing.border.EmptyBorder;
|
|||||||
import javax.swing.text.DefaultCaret;
|
import javax.swing.text.DefaultCaret;
|
||||||
|
|
||||||
import cc.arduino.packages.BoardPort;
|
import cc.arduino.packages.BoardPort;
|
||||||
import processing.app.debug.TextAreaFIFO;
|
|
||||||
|
|
||||||
@SuppressWarnings("serial")
|
@SuppressWarnings("serial")
|
||||||
public abstract class AbstractTextMonitor extends AbstractMonitor {
|
public abstract class AbstractTextMonitor extends AbstractMonitor {
|
||||||
|
@ -36,7 +36,6 @@ import org.fife.ui.rsyntaxtextarea.RSyntaxUtilities;
|
|||||||
import org.fife.ui.rtextarea.Gutter;
|
import org.fife.ui.rtextarea.Gutter;
|
||||||
import org.fife.ui.rtextarea.RTextScrollPane;
|
import org.fife.ui.rtextarea.RTextScrollPane;
|
||||||
import processing.app.debug.RunnerException;
|
import processing.app.debug.RunnerException;
|
||||||
import processing.app.debug.RunnerListener;
|
|
||||||
import processing.app.forms.PasswordAuthorizationDialog;
|
import processing.app.forms.PasswordAuthorizationDialog;
|
||||||
import processing.app.helpers.OSUtils;
|
import processing.app.helpers.OSUtils;
|
||||||
import processing.app.helpers.PreferencesMapException;
|
import processing.app.helpers.PreferencesMapException;
|
||||||
|
@ -20,7 +20,7 @@
|
|||||||
Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package processing.app.debug;
|
package processing.app;
|
||||||
|
|
||||||
|
|
||||||
public interface RunnerListener {
|
public interface RunnerListener {
|
@ -18,7 +18,7 @@
|
|||||||
|
|
||||||
// adapted from https://community.oracle.com/thread/1479784
|
// adapted from https://community.oracle.com/thread/1479784
|
||||||
|
|
||||||
package processing.app.debug;
|
package processing.app;
|
||||||
|
|
||||||
import javax.swing.JTextArea;
|
import javax.swing.JTextArea;
|
||||||
import javax.swing.SwingUtilities;
|
import javax.swing.SwingUtilities;
|
@ -1,233 +0,0 @@
|
|||||||
/*
|
|
||||||
* ====================================================================
|
|
||||||
*
|
|
||||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
|
||||||
* contributor license agreements. See the NOTICE file distributed with
|
|
||||||
* this work for additional information regarding copyright ownership.
|
|
||||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
|
||||||
* (the "License"); you may not use this file except in compliance with
|
|
||||||
* the License. You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
* ====================================================================
|
|
||||||
*
|
|
||||||
* This software consists of voluntary contributions made by many
|
|
||||||
* individuals on behalf of the Apache Software Foundation. For more
|
|
||||||
* information on the Apache Software Foundation, please see
|
|
||||||
* <http://www.apache.org/>.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
package processing.app.debug;
|
|
||||||
|
|
||||||
import org.apache.commons.httpclient.ConnectTimeoutException;
|
|
||||||
import org.apache.commons.httpclient.HttpClientError;
|
|
||||||
import org.apache.commons.httpclient.params.HttpConnectionParams;
|
|
||||||
import org.apache.commons.httpclient.protocol.SecureProtocolSocketFactory;
|
|
||||||
import org.apache.commons.logging.Log;
|
|
||||||
import org.apache.commons.logging.LogFactory;
|
|
||||||
|
|
||||||
import javax.net.SocketFactory;
|
|
||||||
import javax.net.ssl.SSLContext;
|
|
||||||
import javax.net.ssl.SSLSocket;
|
|
||||||
import javax.net.ssl.TrustManager;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.net.*;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* <p>
|
|
||||||
* EasySSLProtocolSocketFactory can be used to creats SSL {@link Socket}s
|
|
||||||
* that accept self-signed certificates.
|
|
||||||
* </p>
|
|
||||||
* <p>
|
|
||||||
* This socket factory SHOULD NOT be used for productive systems
|
|
||||||
* due to security reasons, unless it is a concious decision and
|
|
||||||
* you are perfectly aware of security implications of accepting
|
|
||||||
* self-signed certificates
|
|
||||||
* </p>
|
|
||||||
* <p/>
|
|
||||||
* <p>
|
|
||||||
* Example of using custom protocol socket factory for a specific host:
|
|
||||||
* <pre>
|
|
||||||
* Protocol easyhttps = new Protocol("https", new EasySSLProtocolSocketFactory(), 443);
|
|
||||||
*
|
|
||||||
* URI uri = new URI("https://localhost/", true);
|
|
||||||
* // use relative url only
|
|
||||||
* GetMethod httpget = new GetMethod(uri.getPathQuery());
|
|
||||||
* HostConfiguration hc = new HostConfiguration();
|
|
||||||
* hc.setHost(uri.getHost(), uri.getPort(), easyhttps);
|
|
||||||
* HttpClient client = new HttpClient();
|
|
||||||
* client.executeMethod(hc, httpget);
|
|
||||||
* </pre>
|
|
||||||
* </p>
|
|
||||||
* <p>
|
|
||||||
* Example of using custom protocol socket factory per default instead of the standard one:
|
|
||||||
* <pre>
|
|
||||||
* Protocol easyhttps = new Protocol("https", new EasySSLProtocolSocketFactory(), 443);
|
|
||||||
* Protocol.registerProtocol("https", easyhttps);
|
|
||||||
*
|
|
||||||
* HttpClient client = new HttpClient();
|
|
||||||
* GetMethod httpget = new GetMethod("https://localhost/");
|
|
||||||
* client.executeMethod(httpget);
|
|
||||||
* </pre>
|
|
||||||
* </p>
|
|
||||||
*
|
|
||||||
* @author <a href="mailto:oleg -at- ural.ru">Oleg Kalnichevski</a>
|
|
||||||
* <p/>
|
|
||||||
* <p>
|
|
||||||
* DISCLAIMER: HttpClient developers DO NOT actively support this component.
|
|
||||||
* The component is provided as a reference material, which may be inappropriate
|
|
||||||
* for use without additional customization.
|
|
||||||
* </p>
|
|
||||||
*/
|
|
||||||
|
|
||||||
public class EasySSLProtocolSocketFactory implements SecureProtocolSocketFactory {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Log object for this class.
|
|
||||||
*/
|
|
||||||
private static final Log LOG = LogFactory.getLog(EasySSLProtocolSocketFactory.class);
|
|
||||||
public static final String[] SSL_PROTOCOLS = {"SSLv3", "TLSv1"};
|
|
||||||
public static final String[] SSL_CYPHER_SUITES = {"TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA", "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA", "TLS_RSA_WITH_AES_128_CBC_SHA", "TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA", "TLS_ECDH_RSA_WITH_AES_128_CBC_SHA", "TLS_DHE_RSA_WITH_AES_128_CBC_SHA", "TLS_DHE_DSS_WITH_AES_128_CBC_SHA", "TLS_ECDHE_ECDSA_WITH_RC4_128_SHA", "TLS_ECDHE_RSA_WITH_RC4_128_SHA", "SSL_RSA_WITH_RC4_128_SHA", "TLS_ECDH_ECDSA_WITH_RC4_128_SHA", "TLS_ECDH_RSA_WITH_RC4_128_SHA", "TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA", "TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA", "SSL_RSA_WITH_3DES_EDE_CBC_SHA", "TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA", "TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA", "SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA", "SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA", "SSL_RSA_WITH_RC4_128_MD5", "TLS_EMPTY_RENEGOTIATION_INFO_SCSV"};
|
|
||||||
|
|
||||||
private SSLContext sslcontext = null;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Constructor for EasySSLProtocolSocketFactory.
|
|
||||||
*/
|
|
||||||
public EasySSLProtocolSocketFactory() {
|
|
||||||
super();
|
|
||||||
}
|
|
||||||
|
|
||||||
private static SSLContext createEasySSLContext() {
|
|
||||||
try {
|
|
||||||
SSLContext context = SSLContext.getInstance("SSL");
|
|
||||||
context.init(
|
|
||||||
null,
|
|
||||||
new TrustManager[]{new EasyX509TrustManager(null)},
|
|
||||||
null);
|
|
||||||
return context;
|
|
||||||
} catch (Exception e) {
|
|
||||||
LOG.error(e.getMessage(), e);
|
|
||||||
throw new HttpClientError(e.toString());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private SSLContext getSSLContext() {
|
|
||||||
if (this.sslcontext == null) {
|
|
||||||
this.sslcontext = createEasySSLContext();
|
|
||||||
}
|
|
||||||
return this.sslcontext;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @see SecureProtocolSocketFactory#createSocket(java.lang.String, int, java.net.InetAddress, int)
|
|
||||||
*/
|
|
||||||
public Socket createSocket(
|
|
||||||
String host,
|
|
||||||
int port,
|
|
||||||
InetAddress clientHost,
|
|
||||||
int clientPort)
|
|
||||||
throws IOException, UnknownHostException {
|
|
||||||
|
|
||||||
Socket socket = getSSLContext().getSocketFactory().createSocket(
|
|
||||||
host,
|
|
||||||
port,
|
|
||||||
clientHost,
|
|
||||||
clientPort
|
|
||||||
);
|
|
||||||
return socket;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Attempts to get a new socket connection to the given host within the given time limit.
|
|
||||||
* <p>
|
|
||||||
* To circumvent the limitations of older JREs that do not support connect timeout a
|
|
||||||
* controller thread is executed. The controller thread attempts to create a new socket
|
|
||||||
* within the given limit of time. If socket constructor does not return until the
|
|
||||||
* timeout expires, the controller terminates and throws an {@link ConnectTimeoutException}
|
|
||||||
* </p>
|
|
||||||
*
|
|
||||||
* @param host the host name/IP
|
|
||||||
* @param port the port on the host
|
|
||||||
* @param clientHost the local host name/IP to bind the socket to
|
|
||||||
* @param clientPort the port on the local machine
|
|
||||||
* @param params {@link HttpConnectionParams Http connection parameters}
|
|
||||||
* @return Socket a new socket
|
|
||||||
* @throws IOException if an I/O error occurs while creating the socket
|
|
||||||
* @throws UnknownHostException if the IP address of the host cannot be
|
|
||||||
* determined
|
|
||||||
*/
|
|
||||||
public Socket createSocket(
|
|
||||||
final String host,
|
|
||||||
final int port,
|
|
||||||
final InetAddress localAddress,
|
|
||||||
final int localPort,
|
|
||||||
final HttpConnectionParams params
|
|
||||||
) throws IOException, UnknownHostException, ConnectTimeoutException {
|
|
||||||
if (params == null) {
|
|
||||||
throw new IllegalArgumentException("Parameters may not be null");
|
|
||||||
}
|
|
||||||
int timeout = params.getConnectionTimeout();
|
|
||||||
SocketFactory socketfactory = getSSLContext().getSocketFactory();
|
|
||||||
Socket socket;
|
|
||||||
if (timeout == 0) {
|
|
||||||
socket = socketfactory.createSocket(host, port, localAddress, localPort);
|
|
||||||
} else {
|
|
||||||
socket = socketfactory.createSocket();
|
|
||||||
SocketAddress localaddr = new InetSocketAddress(localAddress, localPort);
|
|
||||||
SocketAddress remoteaddr = new InetSocketAddress(host, port);
|
|
||||||
socket.bind(localaddr);
|
|
||||||
socket.connect(remoteaddr, timeout);
|
|
||||||
}
|
|
||||||
|
|
||||||
SSLSocket sslSocket = (SSLSocket) socket;
|
|
||||||
sslSocket.setEnabledProtocols(SSL_PROTOCOLS);
|
|
||||||
sslSocket.setEnabledCipherSuites(SSL_CYPHER_SUITES);
|
|
||||||
|
|
||||||
return socket;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @see SecureProtocolSocketFactory#createSocket(java.lang.String, int)
|
|
||||||
*/
|
|
||||||
public Socket createSocket(String host, int port)
|
|
||||||
throws IOException, UnknownHostException {
|
|
||||||
return getSSLContext().getSocketFactory().createSocket(
|
|
||||||
host,
|
|
||||||
port
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @see SecureProtocolSocketFactory#createSocket(java.net.Socket, java.lang.String, int, boolean)
|
|
||||||
*/
|
|
||||||
public Socket createSocket(
|
|
||||||
Socket socket,
|
|
||||||
String host,
|
|
||||||
int port,
|
|
||||||
boolean autoClose)
|
|
||||||
throws IOException, UnknownHostException {
|
|
||||||
return getSSLContext().getSocketFactory().createSocket(
|
|
||||||
socket,
|
|
||||||
host,
|
|
||||||
port,
|
|
||||||
autoClose
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean equals(Object obj) {
|
|
||||||
return ((obj != null) && obj.getClass().equals(EasySSLProtocolSocketFactory.class));
|
|
||||||
}
|
|
||||||
|
|
||||||
public int hashCode() {
|
|
||||||
return EasySSLProtocolSocketFactory.class.hashCode();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,114 +0,0 @@
|
|||||||
/*
|
|
||||||
* ====================================================================
|
|
||||||
*
|
|
||||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
|
||||||
* contributor license agreements. See the NOTICE file distributed with
|
|
||||||
* this work for additional information regarding copyright ownership.
|
|
||||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
|
||||||
* (the "License"); you may not use this file except in compliance with
|
|
||||||
* the License. You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
* ====================================================================
|
|
||||||
*
|
|
||||||
* This software consists of voluntary contributions made by many
|
|
||||||
* individuals on behalf of the Apache Software Foundation. For more
|
|
||||||
* information on the Apache Software Foundation, please see
|
|
||||||
* <http://www.apache.org/>.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
package processing.app.debug;
|
|
||||||
|
|
||||||
import java.security.KeyStore;
|
|
||||||
import java.security.KeyStoreException;
|
|
||||||
import java.security.NoSuchAlgorithmException;
|
|
||||||
import java.security.cert.CertificateException;
|
|
||||||
import java.security.cert.X509Certificate;
|
|
||||||
|
|
||||||
import javax.net.ssl.TrustManagerFactory;
|
|
||||||
import javax.net.ssl.TrustManager;
|
|
||||||
import javax.net.ssl.X509TrustManager;
|
|
||||||
import org.apache.commons.logging.Log;
|
|
||||||
import org.apache.commons.logging.LogFactory;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* <p>
|
|
||||||
* EasyX509TrustManager unlike default {@link X509TrustManager} accepts
|
|
||||||
* self-signed certificates.
|
|
||||||
* </p>
|
|
||||||
* <p>
|
|
||||||
* This trust manager SHOULD NOT be used for productive systems
|
|
||||||
* due to security reasons, unless it is a concious decision and
|
|
||||||
* you are perfectly aware of security implications of accepting
|
|
||||||
* self-signed certificates
|
|
||||||
* </p>
|
|
||||||
*
|
|
||||||
* @author <a href="mailto:adrian.sutton@ephox.com">Adrian Sutton</a>
|
|
||||||
* @author <a href="mailto:oleg@ural.ru">Oleg Kalnichevski</a>
|
|
||||||
*
|
|
||||||
* <p>
|
|
||||||
* DISCLAIMER: HttpClient developers DO NOT actively support this component.
|
|
||||||
* The component is provided as a reference material, which may be inappropriate
|
|
||||||
* for use without additional customization.
|
|
||||||
* </p>
|
|
||||||
*/
|
|
||||||
|
|
||||||
public class EasyX509TrustManager implements X509TrustManager
|
|
||||||
{
|
|
||||||
private X509TrustManager standardTrustManager = null;
|
|
||||||
|
|
||||||
/** Log object for this class. */
|
|
||||||
private static final Log LOG = LogFactory.getLog(EasyX509TrustManager.class);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Constructor for EasyX509TrustManager.
|
|
||||||
*/
|
|
||||||
public EasyX509TrustManager(KeyStore keystore) throws NoSuchAlgorithmException, KeyStoreException {
|
|
||||||
super();
|
|
||||||
TrustManagerFactory factory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
|
|
||||||
factory.init(keystore);
|
|
||||||
TrustManager[] trustmanagers = factory.getTrustManagers();
|
|
||||||
if (trustmanagers.length == 0) {
|
|
||||||
throw new NoSuchAlgorithmException("no trust manager found");
|
|
||||||
}
|
|
||||||
this.standardTrustManager = (X509TrustManager)trustmanagers[0];
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @see javax.net.ssl.X509TrustManager#checkClientTrusted(X509Certificate[],String authType)
|
|
||||||
*/
|
|
||||||
public void checkClientTrusted(X509Certificate[] certificates,String authType) throws CertificateException {
|
|
||||||
standardTrustManager.checkClientTrusted(certificates,authType);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @see javax.net.ssl.X509TrustManager#checkServerTrusted(X509Certificate[],String authType)
|
|
||||||
*/
|
|
||||||
public void checkServerTrusted(X509Certificate[] certificates,String authType) throws CertificateException {
|
|
||||||
if ((certificates != null) && LOG.isDebugEnabled()) {
|
|
||||||
LOG.debug("Server certificate chain:");
|
|
||||||
for (int i = 0; i < certificates.length; i++) {
|
|
||||||
LOG.debug("X509Certificate[" + i + "]=" + certificates[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if ((certificates != null) && (certificates.length == 1)) {
|
|
||||||
certificates[0].checkValidity();
|
|
||||||
} else {
|
|
||||||
standardTrustManager.checkServerTrusted(certificates,authType);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @see javax.net.ssl.X509TrustManager#getAcceptedIssuers()
|
|
||||||
*/
|
|
||||||
public X509Certificate[] getAcceptedIssuers() {
|
|
||||||
return this.standardTrustManager.getAcceptedIssuers();
|
|
||||||
}
|
|
||||||
}
|
|
@ -143,7 +143,7 @@ public class DiscourseFormat {
|
|||||||
} else if (c == '&') {
|
} else if (c == '&') {
|
||||||
buffer.append("&");
|
buffer.append("&");
|
||||||
} else if (c > 127) {
|
} else if (c > 127) {
|
||||||
buffer.append("&#" + ((int) c) + ";"); // use unicode entity
|
buffer.append("&#").append((int) c).append(";"); // use unicode entity
|
||||||
} else {
|
} else {
|
||||||
buffer.append(c); // normal character
|
buffer.append(c); // normal character
|
||||||
}
|
}
|
||||||
|
@ -31,14 +31,11 @@ import processing.app.Editor;
|
|||||||
*/
|
*/
|
||||||
public interface Tool extends Runnable {
|
public interface Tool extends Runnable {
|
||||||
|
|
||||||
public void init(Editor editor);
|
void init(Editor editor);
|
||||||
|
|
||||||
public void run();
|
void run();
|
||||||
|
|
||||||
// Not doing shortcuts for now, no way to resolve between tools.
|
String getMenuTitle();
|
||||||
// Also would need additional modifiers for shift and alt.
|
|
||||||
//public char getShortcutKey();
|
|
||||||
|
|
||||||
public String getMenuTitle();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,51 +0,0 @@
|
|||||||
/*
|
|
||||||
* This file is part of Arduino.
|
|
||||||
*
|
|
||||||
* Copyright 2015 Arduino LLC (http://www.arduino.cc/)
|
|
||||||
*
|
|
||||||
* Arduino is free software; you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation; either version 2 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program; if not, write to the Free Software
|
|
||||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
|
||||||
*
|
|
||||||
* As a special exception, you may use this file as part of a free software
|
|
||||||
* library without restriction. Specifically, if other files instantiate
|
|
||||||
* templates or use macros or inline functions from this file, or you compile
|
|
||||||
* this file and link it with other files to produce an executable, this
|
|
||||||
* file does not by itself cause the resulting executable to be covered by
|
|
||||||
* the GNU General Public License. This exception does not however
|
|
||||||
* invalidate any other reasons why the executable file might be covered by
|
|
||||||
* the GNU General Public License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package processing.app.debug;
|
|
||||||
|
|
||||||
import static org.junit.Assert.assertEquals;
|
|
||||||
import static processing.app.debug.OldCompiler.unescapeDepFile;
|
|
||||||
|
|
||||||
import org.junit.Test;
|
|
||||||
|
|
||||||
import processing.app.AbstractWithPreferencesTest;
|
|
||||||
|
|
||||||
public class OldCompilerTest extends AbstractWithPreferencesTest {
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void makeDepUnescapeTest() throws Exception {
|
|
||||||
assertEquals("C:\\Arduino\\hardware\\arduino\\avr\\cores\\arduino\\Stream.cpp",
|
|
||||||
unescapeDepFile("C:\\Arduino\\hardware\\arduino\\avr\\cores\\arduino\\Stream.cpp"));
|
|
||||||
assertEquals("C:\\Arduino 1.5.3\\hardware\\arduino\\avr\\cores\\arduino\\Stream.cpp",
|
|
||||||
unescapeDepFile("C:\\Arduino\\ 1.5.3\\hardware\\arduino\\avr\\cores\\arduino\\Stream.cpp"));
|
|
||||||
assertEquals("C:\\Ard$ui#\\\\ no 1.5.3\\hardware\\arduino\\avr\\cores\\arduino\\Stream.cpp",
|
|
||||||
unescapeDepFile("C:\\Ard$$ui\\#\\\\\\\\\\ no 1.5.3\\hardware\\arduino\\avr\\cores\\arduino\\Stream.cpp"));
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,303 +0,0 @@
|
|||||||
/*
|
|
||||||
* The code is released under the GNU General Public License.
|
|
||||||
* Developed by Kristian Lauszus, TKJ Electronics 2013
|
|
||||||
* This is the algorithm for the Balanduino balancing robot.
|
|
||||||
* It can be controlled by either an Android app or a Processing application via Bluetooth.
|
|
||||||
* The Android app can be found at the following link: https://github.com/TKJElectronics/BalanduinoAndroidApp
|
|
||||||
* The Processing application can be found here: https://github.com/TKJElectronics/BalanduinoProcessingApp
|
|
||||||
* It can also be controlled by a PS3, Wii or a Xbox controller
|
|
||||||
* For details, see: http://balanduino.net/
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* Use this to enable and disable the different options */
|
|
||||||
#define ENABLE_TOOLS
|
|
||||||
#define ENABLE_SPP
|
|
||||||
#define ENABLE_PS3
|
|
||||||
#define ENABLE_WII
|
|
||||||
#define ENABLE_XBOX
|
|
||||||
#define ENABLE_ADK
|
|
||||||
|
|
||||||
#include "Balanduino.h"
|
|
||||||
#include <Wire.h> // Official Arduino Wire library
|
|
||||||
#include <usbhub.h> // Some dongles can have a hub inside
|
|
||||||
|
|
||||||
#ifdef ENABLE_ADK
|
|
||||||
#include <adk.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// These are all open source libraries written by Kristian Lauszus, TKJ Electronics
|
|
||||||
// The USB libraries are located at the following link: https://github.com/felis/USB_Host_Shield_2.0
|
|
||||||
#include <Kalman.h> // Kalman filter library - see: http://blog.tkjelectronics.dk/2012/09/a-practical-approach-to-kalman-filter-and-how-to-implement-it/
|
|
||||||
|
|
||||||
#ifdef ENABLE_XBOX
|
|
||||||
#include <XBOXRECV.h>
|
|
||||||
#endif
|
|
||||||
#ifdef ENABLE_SPP
|
|
||||||
#include <SPP.h>
|
|
||||||
#endif
|
|
||||||
#ifdef ENABLE_PS3
|
|
||||||
#include <PS3BT.h>
|
|
||||||
#endif
|
|
||||||
#ifdef ENABLE_WII
|
|
||||||
#include <Wii.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Create the Kalman library instance
|
|
||||||
Kalman kalman; // See https://github.com/TKJElectronics/KalmanFilter for source code
|
|
||||||
|
|
||||||
#if defined(ENABLE_SPP) || defined(ENABLE_PS3) || defined(ENABLE_WII) || defined(ENABLE_XBOX) || defined(ENABLE_ADK)
|
|
||||||
#define ENABLE_USB
|
|
||||||
USB Usb; // This will take care of all USB communication
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef ENABLE_ADK
|
|
||||||
// Implementation for the Android Open Accessory Protocol. Simply connect your phone to get redirected to the Play Store
|
|
||||||
ADK adk(&Usb, "TKJ Electronics", // Manufacturer Name
|
|
||||||
"Balanduino", // Model Name
|
|
||||||
"Android App for Balanduino", // Description - user visible string
|
|
||||||
"0.5.0", // Version of the Android app
|
|
||||||
"https://play.google.com/store/apps/details?id=com.tkjelectronics.balanduino", // URL - web page to visit if no installed apps support the accessory
|
|
||||||
"1234"); // Serial Number - this is not used
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef ENABLE_XBOX
|
|
||||||
XBOXRECV Xbox(&Usb); // You have to connect a Xbox wireless receiver to the Arduino to control it with a wireless Xbox controller
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(ENABLE_SPP) || defined(ENABLE_PS3) || defined(ENABLE_WII)
|
|
||||||
USBHub Hub(&Usb); // Some dongles have a hub inside
|
|
||||||
BTD Btd(&Usb); // This is the main Bluetooth library, it will take care of all the USB and HCI communication with the Bluetooth dongle
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef ENABLE_SPP
|
|
||||||
SPP SerialBT(&Btd, "Balanduino", "0000"); // The SPP (Serial Port Protocol) emulates a virtual Serial port, which is supported by most computers and mobile phones
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef ENABLE_PS3
|
|
||||||
PS3BT PS3(&Btd); // The PS3 library supports all three official controllers: the Dualshock 3, Navigation and Move controller
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef ENABLE_WII
|
|
||||||
WII Wii(&Btd); // The Wii library can communicate with Wiimotes and the Nunchuck and Motion Plus extension and finally the Wii U Pro Controller
|
|
||||||
//WII Wii(&Btd,PAIR); // You will have to pair with your Wiimote first by creating the instance like this and the press 1+2 on the Wiimote
|
|
||||||
// or press sync if you are using a Wii U Pro Controller
|
|
||||||
// Or you can simply send "CW;" to the robot to start the pairing sequence
|
|
||||||
// This can also be done using the Android or Processing application
|
|
||||||
#endif
|
|
||||||
|
|
||||||
void setup() {
|
|
||||||
/* Initialize UART */
|
|
||||||
Serial.begin(115200);
|
|
||||||
|
|
||||||
/* Read the PID values, target angle and other saved values in the EEPROM */
|
|
||||||
if (!checkInitializationFlags())
|
|
||||||
readEEPROMValues(); // Only read the EEPROM values if they have not been restored
|
|
||||||
|
|
||||||
/* Setup encoders */
|
|
||||||
pinMode(leftEncoder1, INPUT);
|
|
||||||
pinMode(leftEncoder2, INPUT);
|
|
||||||
pinMode(rightEncoder1, INPUT);
|
|
||||||
pinMode(rightEncoder2, INPUT);
|
|
||||||
attachInterrupt(0, leftEncoder, CHANGE);
|
|
||||||
attachInterrupt(1, rightEncoder, CHANGE);
|
|
||||||
|
|
||||||
/* Enable the motor drivers */
|
|
||||||
pinMode(leftEnable, OUTPUT);
|
|
||||||
pinMode(rightEnable, OUTPUT);
|
|
||||||
digitalWrite(leftEnable, HIGH);
|
|
||||||
digitalWrite(rightEnable, HIGH);
|
|
||||||
|
|
||||||
/* Setup motor pins to output */
|
|
||||||
sbi(pwmPortDirection, leftPWM);
|
|
||||||
sbi(leftPortDirection, leftA);
|
|
||||||
sbi(leftPortDirection, leftB);
|
|
||||||
sbi(pwmPortDirection, rightPWM);
|
|
||||||
sbi(rightPortDirection, rightA);
|
|
||||||
sbi(rightPortDirection, rightB);
|
|
||||||
|
|
||||||
/* Set PWM frequency to 20kHz - see the datasheet http://www.atmel.com/Images/doc8272.pdf page 128-135 */
|
|
||||||
// Set up PWM, Phase and Frequency Correct on pin 18 (OC1A) & pin 17 (OC1B) with ICR1 as TOP using Timer1
|
|
||||||
TCCR1B = _BV(WGM13) | _BV(CS10); // Set PWM Phase and Frequency Correct with ICR1 as TOP and no prescaling
|
|
||||||
ICR1 = PWMVALUE; // ICR1 is the TOP value - this is set so the frequency is equal to 20kHz
|
|
||||||
|
|
||||||
/* Enable PWM on pin 18 (OC1A) & pin 17 (OC1B) */
|
|
||||||
// Clear OC1A/OC1B on compare match when up-counting
|
|
||||||
// Set OC1A/OC1B on compare match when downcounting
|
|
||||||
TCCR1A = _BV(COM1A1) | _BV(COM1B1);
|
|
||||||
setPWM(leftPWM, 0); // Turn off PWM on both pins
|
|
||||||
setPWM(rightPWM, 0);
|
|
||||||
|
|
||||||
/* Setup buzzer pin */
|
|
||||||
pinMode(buzzer, OUTPUT);
|
|
||||||
|
|
||||||
#ifdef ENABLE_USB
|
|
||||||
if (Usb.Init() == -1) { // Check if USB Host is working
|
|
||||||
Serial.print(F("OSC did not start"));
|
|
||||||
digitalWrite(buzzer, HIGH);
|
|
||||||
while (1); // Halt
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Attach onInit function */
|
|
||||||
// This is used to set the LEDs according to the voltage level and vibrate the controller to indicate the new connection
|
|
||||||
#ifdef ENABLE_PS3
|
|
||||||
PS3.attachOnInit(onInit);
|
|
||||||
#endif
|
|
||||||
#ifdef ENABLE_WII
|
|
||||||
Wii.attachOnInit(onInit);
|
|
||||||
#endif
|
|
||||||
#ifdef ENABLE_XBOX
|
|
||||||
Xbox.attachOnInit(onInit);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Setup IMU */
|
|
||||||
Wire.begin();
|
|
||||||
|
|
||||||
while (i2cRead(0x75, i2cBuffer, 1));
|
|
||||||
if (i2cBuffer[0] != 0x68) { // Read "WHO_AM_I" register
|
|
||||||
Serial.print(F("Error reading sensor"));
|
|
||||||
digitalWrite(buzzer, HIGH);
|
|
||||||
while (1); // Halt
|
|
||||||
}
|
|
||||||
|
|
||||||
i2cBuffer[0] = 19; // Set the sample rate to 400Hz - 8kHz/(19+1) = 400Hz
|
|
||||||
i2cBuffer[1] = 0x00; // Disable FSYNC and set 260 Hz Acc filtering, 256 Hz Gyro filtering, 8 KHz sampling
|
|
||||||
i2cBuffer[2] = 0x00; // Set Gyro Full Scale Range to ±250deg/s
|
|
||||||
i2cBuffer[3] = 0x00; // Set Accelerometer Full Scale Range to ±2g
|
|
||||||
while (i2cWrite(0x19, i2cBuffer, 4, false)); // Write to all four registers at once
|
|
||||||
while (i2cWrite(0x6B, 0x09, true)); // PLL with X axis gyroscope reference, disable temperature sensor and disable sleep mode
|
|
||||||
|
|
||||||
delay(100); // Wait for the sensor to get ready
|
|
||||||
|
|
||||||
/* Set Kalman and gyro starting angle */
|
|
||||||
while (i2cRead(0x3D, i2cBuffer, 4));
|
|
||||||
accY = ((i2cBuffer[0] << 8) | i2cBuffer[1]);
|
|
||||||
accZ = ((i2cBuffer[2] << 8) | i2cBuffer[3]);
|
|
||||||
// atan2 outputs the value of -π to π (radians) - see http://en.wikipedia.org/wiki/Atan2
|
|
||||||
// We then convert it to 0 to 2π and then from radians to degrees
|
|
||||||
accAngle = (atan2((double)accY - cfg.accYzero, (double)accZ - cfg.accZzero) + PI) * RAD_TO_DEG;
|
|
||||||
|
|
||||||
kalman.setAngle(accAngle); // Set starting angle
|
|
||||||
pitch = accAngle;
|
|
||||||
gyroAngle = accAngle;
|
|
||||||
|
|
||||||
/* Find gyro zero value */
|
|
||||||
calibrateGyro();
|
|
||||||
|
|
||||||
pinMode(LED_BUILTIN, OUTPUT); // LED_BUILTIN is defined in pins_arduino.h in the hardware add-on
|
|
||||||
|
|
||||||
/* Beep to indicate that it is now ready */
|
|
||||||
digitalWrite(buzzer, HIGH);
|
|
||||||
delay(100);
|
|
||||||
digitalWrite(buzzer, LOW);
|
|
||||||
|
|
||||||
/* Setup timing */
|
|
||||||
kalmanTimer = micros();
|
|
||||||
pidTimer = kalmanTimer;
|
|
||||||
encoderTimer = kalmanTimer;
|
|
||||||
imuTimer = millis();
|
|
||||||
reportTimer = imuTimer;
|
|
||||||
ledTimer = imuTimer;
|
|
||||||
blinkTimer = imuTimer;
|
|
||||||
}
|
|
||||||
|
|
||||||
void loop() {
|
|
||||||
#ifdef ENABLE_WII
|
|
||||||
if (Wii.wiimoteConnected) // We have to read much more often from the Wiimote to decrease latency
|
|
||||||
Usb.Task();
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Calculate pitch */
|
|
||||||
while (i2cRead(0x3D, i2cBuffer, 8));
|
|
||||||
accY = ((i2cBuffer[0] << 8) | i2cBuffer[1]);
|
|
||||||
accZ = ((i2cBuffer[2] << 8) | i2cBuffer[3]);
|
|
||||||
gyroX = ((i2cBuffer[6] << 8) | i2cBuffer[7]);
|
|
||||||
|
|
||||||
// atan2 outputs the value of -π to π (radians) - see http://en.wikipedia.org/wiki/Atan2
|
|
||||||
// We then convert it to 0 to 2π and then from radians to degrees
|
|
||||||
accAngle = (atan2((double)accY - cfg.accYzero, (double)accZ - cfg.accZzero) + PI) * RAD_TO_DEG;
|
|
||||||
|
|
||||||
uint32_t timer = micros();
|
|
||||||
// This fixes the 0-360 transition problem when the accelerometer angle jumps between 0 and 360 degrees
|
|
||||||
if ((accAngle < 90 && pitch > 270) || (accAngle > 270 && pitch < 90)) {
|
|
||||||
kalman.setAngle(accAngle);
|
|
||||||
pitch = accAngle;
|
|
||||||
gyroAngle = accAngle;
|
|
||||||
} else {
|
|
||||||
gyroRate = ((double)gyroX - gyroXzero) / 131.0; // Convert to deg/s
|
|
||||||
double dt = (double)(timer - kalmanTimer) / 1000000.0;
|
|
||||||
gyroAngle += gyroRate * dt; // Gyro angle is only used for debugging
|
|
||||||
if (gyroAngle < 0 || gyroAngle > 360)
|
|
||||||
gyroAngle = pitch; // Reset the gyro angle when it has drifted too much
|
|
||||||
pitch = kalman.getAngle(accAngle, gyroRate, dt); // Calculate the angle using a Kalman filter
|
|
||||||
}
|
|
||||||
kalmanTimer = timer;
|
|
||||||
//Serial.print(accAngle);Serial.print('\t');Serial.print(gyroAngle);Serial.print('\t');Serial.println(pitch);
|
|
||||||
|
|
||||||
#ifdef ENABLE_WII
|
|
||||||
if (Wii.wiimoteConnected) // We have to read much more often from the Wiimote to decrease latency
|
|
||||||
Usb.Task();
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Drive motors */
|
|
||||||
timer = micros();
|
|
||||||
// If the robot is laying down, it has to be put in a vertical position before it starts balancing
|
|
||||||
// If it's already balancing it has to be ±45 degrees before it stops trying to balance
|
|
||||||
if ((layingDown && (pitch < cfg.targetAngle - 10 || pitch > cfg.targetAngle + 10)) || (!layingDown && (pitch < cfg.targetAngle - 45 || pitch > cfg.targetAngle + 45))) {
|
|
||||||
layingDown = true; // The robot is in a unsolvable position, so turn off both motors and wait until it's vertical again
|
|
||||||
stopAndReset();
|
|
||||||
} else {
|
|
||||||
layingDown = false; // It's no longer laying down
|
|
||||||
updatePID(cfg.targetAngle, targetOffset, turningOffset, (double)(timer - pidTimer) / 1000000.0);
|
|
||||||
}
|
|
||||||
pidTimer = timer;
|
|
||||||
|
|
||||||
/* Update encoders */
|
|
||||||
timer = micros();
|
|
||||||
if (timer - encoderTimer >= 100000) { // Update encoder values every 100ms
|
|
||||||
encoderTimer = timer;
|
|
||||||
int32_t wheelPosition = getWheelsPosition();
|
|
||||||
wheelVelocity = wheelPosition - lastWheelPosition;
|
|
||||||
lastWheelPosition = wheelPosition;
|
|
||||||
//Serial.print(wheelPosition);Serial.print('\t');Serial.print(targetPosition);Serial.print('\t');Serial.println(wheelVelocity);
|
|
||||||
if (abs(wheelVelocity) <= 40 && !stopped) { // Set new targetPosition if braking
|
|
||||||
targetPosition = wheelPosition;
|
|
||||||
stopped = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
batteryCounter++;
|
|
||||||
if (batteryCounter > 10) { // Measure battery every 1s
|
|
||||||
batteryCounter = 0;
|
|
||||||
batteryVoltage = (double)analogRead(VBAT) / 63.050847458; // VBAT is connected to analog input 5 which is not broken out. This is then connected to a 47k-12k voltage divider - 1023.0/(3.3/(12.0/(12.0+47.0))) = 63.050847458
|
|
||||||
if (batteryVoltage < 10.2 && batteryVoltage > 5) // Equal to 3.4V per cell - don't turn on if it's below 5V, this means that no battery is connected
|
|
||||||
digitalWrite(buzzer, HIGH);
|
|
||||||
else
|
|
||||||
digitalWrite(buzzer, LOW);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Read the Bluetooth dongle and send PID and IMU values */
|
|
||||||
#ifdef ENABLE_USB
|
|
||||||
readUsb();
|
|
||||||
#endif
|
|
||||||
#ifdef ENABLE_TOOLS
|
|
||||||
checkSerialData();
|
|
||||||
#endif
|
|
||||||
#if defined(ENABLE_TOOLS) || defined(ENABLE_SPP)
|
|
||||||
printValues();
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(ENABLE_SPP) || defined(ENABLE_PS3) || defined(ENABLE_WII)
|
|
||||||
if (Btd.isReady()) {
|
|
||||||
timer = millis();
|
|
||||||
if ((Btd.watingForConnection && timer - blinkTimer > 1000) || (!Btd.watingForConnection && timer - blinkTimer > 100)) {
|
|
||||||
blinkTimer = timer;
|
|
||||||
ledState = !ledState;
|
|
||||||
digitalWrite(LED_BUILTIN, ledState); // Used to blink the built in LED, starts blinking faster upon an incoming Bluetooth request
|
|
||||||
}
|
|
||||||
} else if (ledState) { // The LED is on
|
|
||||||
ledState = !ledState;
|
|
||||||
digitalWrite(LED_BUILTIN, ledState); // This will turn it off
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
|
@ -1,304 +0,0 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#define ENABLE_TOOLS
|
|
||||||
#define ENABLE_SPP
|
|
||||||
#define ENABLE_PS3
|
|
||||||
#define ENABLE_WII
|
|
||||||
#define ENABLE_XBOX
|
|
||||||
#define ENABLE_ADK
|
|
||||||
|
|
||||||
#include "Balanduino.h"
|
|
||||||
#include <Wire.h>
|
|
||||||
#include <usbhub.h>
|
|
||||||
|
|
||||||
#ifdef ENABLE_ADK
|
|
||||||
#include <adk.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#include <Kalman.h>
|
|
||||||
|
|
||||||
#ifdef ENABLE_XBOX
|
|
||||||
#include <XBOXRECV.h>
|
|
||||||
#endif
|
|
||||||
#ifdef ENABLE_SPP
|
|
||||||
#include <SPP.h>
|
|
||||||
#endif
|
|
||||||
#ifdef ENABLE_PS3
|
|
||||||
#include <PS3BT.h>
|
|
||||||
#endif
|
|
||||||
#ifdef ENABLE_WII
|
|
||||||
#include <Wii.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
Kalman kalman;
|
|
||||||
|
|
||||||
#if defined(ENABLE_SPP) || defined(ENABLE_PS3) || defined(ENABLE_WII) || defined(ENABLE_XBOX) || defined(ENABLE_ADK)
|
|
||||||
#define ENABLE_USB
|
|
||||||
USB Usb;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef ENABLE_ADK
|
|
||||||
|
|
||||||
ADK adk(&Usb, "TKJ Electronics",
|
|
||||||
"Balanduino",
|
|
||||||
"Android App for Balanduino",
|
|
||||||
"0.5.0",
|
|
||||||
"https://play.google.com/store/apps/details?id=com.tkjelectronics.balanduino",
|
|
||||||
"1234");
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef ENABLE_XBOX
|
|
||||||
XBOXRECV Xbox(&Usb);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(ENABLE_SPP) || defined(ENABLE_PS3) || defined(ENABLE_WII)
|
|
||||||
USBHub Hub(&Usb);
|
|
||||||
BTD Btd(&Usb);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef ENABLE_SPP
|
|
||||||
SPP SerialBT(&Btd, "Balanduino", "0000");
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef ENABLE_PS3
|
|
||||||
PS3BT PS3(&Btd);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef ENABLE_WII
|
|
||||||
WII Wii(&Btd);
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
void setup() {
|
|
||||||
|
|
||||||
Serial.begin(115200);
|
|
||||||
|
|
||||||
|
|
||||||
if (!checkInitializationFlags())
|
|
||||||
readEEPROMValues();
|
|
||||||
|
|
||||||
|
|
||||||
pinMode(leftEncoder1, INPUT);
|
|
||||||
pinMode(leftEncoder2, INPUT);
|
|
||||||
pinMode(rightEncoder1, INPUT);
|
|
||||||
pinMode(rightEncoder2, INPUT);
|
|
||||||
attachInterrupt(0, leftEncoder, CHANGE);
|
|
||||||
attachInterrupt(1, rightEncoder, CHANGE);
|
|
||||||
|
|
||||||
|
|
||||||
pinMode(leftEnable, OUTPUT);
|
|
||||||
pinMode(rightEnable, OUTPUT);
|
|
||||||
digitalWrite(leftEnable, HIGH);
|
|
||||||
digitalWrite(rightEnable, HIGH);
|
|
||||||
|
|
||||||
|
|
||||||
sbi(pwmPortDirection, leftPWM);
|
|
||||||
sbi(leftPortDirection, leftA);
|
|
||||||
sbi(leftPortDirection, leftB);
|
|
||||||
sbi(pwmPortDirection, rightPWM);
|
|
||||||
sbi(rightPortDirection, rightA);
|
|
||||||
sbi(rightPortDirection, rightB);
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
TCCR1B = _BV(WGM13) | _BV(CS10);
|
|
||||||
ICR1 = PWMVALUE;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
TCCR1A = _BV(COM1A1) | _BV(COM1B1);
|
|
||||||
setPWM(leftPWM, 0);
|
|
||||||
setPWM(rightPWM, 0);
|
|
||||||
|
|
||||||
|
|
||||||
pinMode(buzzer, OUTPUT);
|
|
||||||
|
|
||||||
#ifdef ENABLE_USB
|
|
||||||
if (Usb.Init() == -1) {
|
|
||||||
Serial.print(F("OSC did not start"));
|
|
||||||
digitalWrite(buzzer, HIGH);
|
|
||||||
while (1);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef ENABLE_PS3
|
|
||||||
PS3.attachOnInit(onInit);
|
|
||||||
#endif
|
|
||||||
#ifdef ENABLE_WII
|
|
||||||
Wii.attachOnInit(onInit);
|
|
||||||
#endif
|
|
||||||
#ifdef ENABLE_XBOX
|
|
||||||
Xbox.attachOnInit(onInit);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
Wire.begin();
|
|
||||||
|
|
||||||
while (i2cRead(0x75, i2cBuffer, 1));
|
|
||||||
if (i2cBuffer[0] != 0x68) {
|
|
||||||
Serial.print(F("Error reading sensor"));
|
|
||||||
digitalWrite(buzzer, HIGH);
|
|
||||||
while (1);
|
|
||||||
}
|
|
||||||
|
|
||||||
i2cBuffer[0] = 19;
|
|
||||||
i2cBuffer[1] = 0x00;
|
|
||||||
i2cBuffer[2] = 0x00;
|
|
||||||
i2cBuffer[3] = 0x00;
|
|
||||||
while (i2cWrite(0x19, i2cBuffer, 4, false));
|
|
||||||
while (i2cWrite(0x6B, 0x09, true));
|
|
||||||
|
|
||||||
delay(100);
|
|
||||||
|
|
||||||
|
|
||||||
while (i2cRead(0x3D, i2cBuffer, 4));
|
|
||||||
accY = ((i2cBuffer[0] << 8) | i2cBuffer[1]);
|
|
||||||
accZ = ((i2cBuffer[2] << 8) | i2cBuffer[3]);
|
|
||||||
|
|
||||||
|
|
||||||
accAngle = (atan2((double)accY - cfg.accYzero, (double)accZ - cfg.accZzero) + PI) * RAD_TO_DEG;
|
|
||||||
|
|
||||||
kalman.setAngle(accAngle);
|
|
||||||
pitch = accAngle;
|
|
||||||
gyroAngle = accAngle;
|
|
||||||
|
|
||||||
|
|
||||||
calibrateGyro();
|
|
||||||
|
|
||||||
pinMode(LED_BUILTIN, OUTPUT);
|
|
||||||
|
|
||||||
|
|
||||||
digitalWrite(buzzer, HIGH);
|
|
||||||
delay(100);
|
|
||||||
digitalWrite(buzzer, LOW);
|
|
||||||
|
|
||||||
|
|
||||||
kalmanTimer = micros();
|
|
||||||
pidTimer = kalmanTimer;
|
|
||||||
encoderTimer = kalmanTimer;
|
|
||||||
imuTimer = millis();
|
|
||||||
reportTimer = imuTimer;
|
|
||||||
ledTimer = imuTimer;
|
|
||||||
blinkTimer = imuTimer;
|
|
||||||
}
|
|
||||||
|
|
||||||
void loop() {
|
|
||||||
#ifdef ENABLE_WII
|
|
||||||
if (Wii.wiimoteConnected)
|
|
||||||
Usb.Task();
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
while (i2cRead(0x3D, i2cBuffer, 8));
|
|
||||||
accY = ((i2cBuffer[0] << 8) | i2cBuffer[1]);
|
|
||||||
accZ = ((i2cBuffer[2] << 8) | i2cBuffer[3]);
|
|
||||||
gyroX = ((i2cBuffer[6] << 8) | i2cBuffer[7]);
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
accAngle = (atan2((double)accY - cfg.accYzero, (double)accZ - cfg.accZzero) + PI) * RAD_TO_DEG;
|
|
||||||
|
|
||||||
uint32_t timer = micros();
|
|
||||||
|
|
||||||
if ((accAngle < 90 && pitch > 270) || (accAngle > 270 && pitch < 90)) {
|
|
||||||
kalman.setAngle(accAngle);
|
|
||||||
pitch = accAngle;
|
|
||||||
gyroAngle = accAngle;
|
|
||||||
} else {
|
|
||||||
gyroRate = ((double)gyroX - gyroXzero) / 131.0;
|
|
||||||
double dt = (double)(timer - kalmanTimer) / 1000000.0;
|
|
||||||
gyroAngle += gyroRate * dt;
|
|
||||||
if (gyroAngle < 0 || gyroAngle > 360)
|
|
||||||
gyroAngle = pitch;
|
|
||||||
pitch = kalman.getAngle(accAngle, gyroRate, dt);
|
|
||||||
}
|
|
||||||
kalmanTimer = timer;
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef ENABLE_WII
|
|
||||||
if (Wii.wiimoteConnected)
|
|
||||||
Usb.Task();
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
timer = micros();
|
|
||||||
|
|
||||||
|
|
||||||
if ((layingDown && (pitch < cfg.targetAngle - 10 || pitch > cfg.targetAngle + 10)) || (!layingDown && (pitch < cfg.targetAngle - 45 || pitch > cfg.targetAngle + 45))) {
|
|
||||||
layingDown = true;
|
|
||||||
stopAndReset();
|
|
||||||
} else {
|
|
||||||
layingDown = false;
|
|
||||||
updatePID(cfg.targetAngle, targetOffset, turningOffset, (double)(timer - pidTimer) / 1000000.0);
|
|
||||||
}
|
|
||||||
pidTimer = timer;
|
|
||||||
|
|
||||||
|
|
||||||
timer = micros();
|
|
||||||
if (timer - encoderTimer >= 100000) {
|
|
||||||
encoderTimer = timer;
|
|
||||||
int32_t wheelPosition = getWheelsPosition();
|
|
||||||
wheelVelocity = wheelPosition - lastWheelPosition;
|
|
||||||
lastWheelPosition = wheelPosition;
|
|
||||||
|
|
||||||
if (abs(wheelVelocity) <= 40 && !stopped) {
|
|
||||||
targetPosition = wheelPosition;
|
|
||||||
stopped = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
batteryCounter++;
|
|
||||||
if (batteryCounter > 10) {
|
|
||||||
batteryCounter = 0;
|
|
||||||
batteryVoltage = (double)analogRead(VBAT) / 63.050847458;
|
|
||||||
if (batteryVoltage < 10.2 && batteryVoltage > 5)
|
|
||||||
digitalWrite(buzzer, HIGH);
|
|
||||||
else
|
|
||||||
digitalWrite(buzzer, LOW);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef ENABLE_USB
|
|
||||||
readUsb();
|
|
||||||
#endif
|
|
||||||
#ifdef ENABLE_TOOLS
|
|
||||||
checkSerialData();
|
|
||||||
#endif
|
|
||||||
#if defined(ENABLE_TOOLS) || defined(ENABLE_SPP)
|
|
||||||
printValues();
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(ENABLE_SPP) || defined(ENABLE_PS3) || defined(ENABLE_WII)
|
|
||||||
if (Btd.isReady()) {
|
|
||||||
timer = millis();
|
|
||||||
if ((Btd.watingForConnection && timer - blinkTimer > 1000) || (!Btd.watingForConnection && timer - blinkTimer > 100)) {
|
|
||||||
blinkTimer = timer;
|
|
||||||
ledState = !ledState;
|
|
||||||
digitalWrite(LED_BUILTIN, ledState);
|
|
||||||
}
|
|
||||||
} else if (ledState) {
|
|
||||||
ledState = !ledState;
|
|
||||||
digitalWrite(LED_BUILTIN, ledState);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
@ -1,303 +0,0 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Kalman kalman;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
USB Usb;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
ADK adk(&Usb, ,
|
|
||||||
,
|
|
||||||
,
|
|
||||||
,
|
|
||||||
,
|
|
||||||
);
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
XBOXRECV Xbox(&Usb);
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
USBHub Hub(&Usb);
|
|
||||||
BTD Btd(&Usb);
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
SPP SerialBT(&Btd, , );
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
PS3BT PS3(&Btd);
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
WII Wii(&Btd);
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void setup() {
|
|
||||||
|
|
||||||
Serial.begin(115200);
|
|
||||||
|
|
||||||
|
|
||||||
if (!checkInitializationFlags())
|
|
||||||
readEEPROMValues();
|
|
||||||
|
|
||||||
|
|
||||||
pinMode(leftEncoder1, INPUT);
|
|
||||||
pinMode(leftEncoder2, INPUT);
|
|
||||||
pinMode(rightEncoder1, INPUT);
|
|
||||||
pinMode(rightEncoder2, INPUT);
|
|
||||||
attachInterrupt(0, leftEncoder, CHANGE);
|
|
||||||
attachInterrupt(1, rightEncoder, CHANGE);
|
|
||||||
|
|
||||||
|
|
||||||
pinMode(leftEnable, OUTPUT);
|
|
||||||
pinMode(rightEnable, OUTPUT);
|
|
||||||
digitalWrite(leftEnable, HIGH);
|
|
||||||
digitalWrite(rightEnable, HIGH);
|
|
||||||
|
|
||||||
|
|
||||||
sbi(pwmPortDirection, leftPWM);
|
|
||||||
sbi(leftPortDirection, leftA);
|
|
||||||
sbi(leftPortDirection, leftB);
|
|
||||||
sbi(pwmPortDirection, rightPWM);
|
|
||||||
sbi(rightPortDirection, rightA);
|
|
||||||
sbi(rightPortDirection, rightB);
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
TCCR1B = _BV(WGM13) | _BV(CS10);
|
|
||||||
ICR1 = PWMVALUE;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
TCCR1A = _BV(COM1A1) | _BV(COM1B1);
|
|
||||||
setPWM(leftPWM, 0);
|
|
||||||
setPWM(rightPWM, 0);
|
|
||||||
|
|
||||||
|
|
||||||
pinMode(buzzer, OUTPUT);
|
|
||||||
|
|
||||||
|
|
||||||
if (Usb.Init() == -1) {
|
|
||||||
Serial.print(F( ));
|
|
||||||
digitalWrite(buzzer, HIGH);
|
|
||||||
while (1);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
PS3.attachOnInit(onInit);
|
|
||||||
|
|
||||||
|
|
||||||
Wii.attachOnInit(onInit);
|
|
||||||
|
|
||||||
|
|
||||||
Xbox.attachOnInit(onInit);
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Wire.begin();
|
|
||||||
|
|
||||||
while (i2cRead(0x75, i2cBuffer, 1));
|
|
||||||
if (i2cBuffer[0] != 0x68) {
|
|
||||||
Serial.print(F( ));
|
|
||||||
digitalWrite(buzzer, HIGH);
|
|
||||||
while (1);
|
|
||||||
}
|
|
||||||
|
|
||||||
i2cBuffer[0] = 19;
|
|
||||||
i2cBuffer[1] = 0x00;
|
|
||||||
i2cBuffer[2] = 0x00;
|
|
||||||
i2cBuffer[3] = 0x00;
|
|
||||||
while (i2cWrite(0x19, i2cBuffer, 4, false));
|
|
||||||
while (i2cWrite(0x6B, 0x09, true));
|
|
||||||
|
|
||||||
delay(100);
|
|
||||||
|
|
||||||
|
|
||||||
while (i2cRead(0x3D, i2cBuffer, 4));
|
|
||||||
accY = ((i2cBuffer[0] << 8) | i2cBuffer[1]);
|
|
||||||
accZ = ((i2cBuffer[2] << 8) | i2cBuffer[3]);
|
|
||||||
|
|
||||||
|
|
||||||
accAngle = (atan2((double)accY - cfg.accYzero, (double)accZ - cfg.accZzero) + PI) * RAD_TO_DEG;
|
|
||||||
|
|
||||||
kalman.setAngle(accAngle);
|
|
||||||
pitch = accAngle;
|
|
||||||
gyroAngle = accAngle;
|
|
||||||
|
|
||||||
|
|
||||||
calibrateGyro();
|
|
||||||
|
|
||||||
pinMode(LED_BUILTIN, OUTPUT);
|
|
||||||
|
|
||||||
|
|
||||||
digitalWrite(buzzer, HIGH);
|
|
||||||
delay(100);
|
|
||||||
digitalWrite(buzzer, LOW);
|
|
||||||
|
|
||||||
|
|
||||||
kalmanTimer = micros();
|
|
||||||
pidTimer = kalmanTimer;
|
|
||||||
encoderTimer = kalmanTimer;
|
|
||||||
imuTimer = millis();
|
|
||||||
reportTimer = imuTimer;
|
|
||||||
ledTimer = imuTimer;
|
|
||||||
blinkTimer = imuTimer;
|
|
||||||
}
|
|
||||||
|
|
||||||
void loop() {
|
|
||||||
|
|
||||||
if (Wii.wiimoteConnected)
|
|
||||||
Usb.Task();
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
while (i2cRead(0x3D, i2cBuffer, 8));
|
|
||||||
accY = ((i2cBuffer[0] << 8) | i2cBuffer[1]);
|
|
||||||
accZ = ((i2cBuffer[2] << 8) | i2cBuffer[3]);
|
|
||||||
gyroX = ((i2cBuffer[6] << 8) | i2cBuffer[7]);
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
accAngle = (atan2((double)accY - cfg.accYzero, (double)accZ - cfg.accZzero) + PI) * RAD_TO_DEG;
|
|
||||||
|
|
||||||
uint32_t timer = micros();
|
|
||||||
|
|
||||||
if ((accAngle < 90 && pitch > 270) || (accAngle > 270 && pitch < 90)) {
|
|
||||||
kalman.setAngle(accAngle);
|
|
||||||
pitch = accAngle;
|
|
||||||
gyroAngle = accAngle;
|
|
||||||
} else {
|
|
||||||
gyroRate = ((double)gyroX - gyroXzero) / 131.0;
|
|
||||||
double dt = (double)(timer - kalmanTimer) / 1000000.0;
|
|
||||||
gyroAngle += gyroRate * dt;
|
|
||||||
if (gyroAngle < 0 || gyroAngle > 360)
|
|
||||||
gyroAngle = pitch;
|
|
||||||
pitch = kalman.getAngle(accAngle, gyroRate, dt);
|
|
||||||
}
|
|
||||||
kalmanTimer = timer;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if (Wii.wiimoteConnected)
|
|
||||||
Usb.Task();
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
timer = micros();
|
|
||||||
|
|
||||||
|
|
||||||
if ((layingDown && (pitch < cfg.targetAngle - 10 || pitch > cfg.targetAngle + 10)) || (!layingDown && (pitch < cfg.targetAngle - 45 || pitch > cfg.targetAngle + 45))) {
|
|
||||||
layingDown = true;
|
|
||||||
stopAndReset();
|
|
||||||
} else {
|
|
||||||
layingDown = false;
|
|
||||||
updatePID(cfg.targetAngle, targetOffset, turningOffset, (double)(timer - pidTimer) / 1000000.0);
|
|
||||||
}
|
|
||||||
pidTimer = timer;
|
|
||||||
|
|
||||||
|
|
||||||
timer = micros();
|
|
||||||
if (timer - encoderTimer >= 100000) {
|
|
||||||
encoderTimer = timer;
|
|
||||||
int32_t wheelPosition = getWheelsPosition();
|
|
||||||
wheelVelocity = wheelPosition - lastWheelPosition;
|
|
||||||
lastWheelPosition = wheelPosition;
|
|
||||||
|
|
||||||
if (abs(wheelVelocity) <= 40 && !stopped) {
|
|
||||||
targetPosition = wheelPosition;
|
|
||||||
stopped = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
batteryCounter++;
|
|
||||||
if (batteryCounter > 10) {
|
|
||||||
batteryCounter = 0;
|
|
||||||
batteryVoltage = (double)analogRead(VBAT) / 63.050847458;
|
|
||||||
if (batteryVoltage < 10.2 && batteryVoltage > 5)
|
|
||||||
digitalWrite(buzzer, HIGH);
|
|
||||||
else
|
|
||||||
digitalWrite(buzzer, LOW);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
readUsb();
|
|
||||||
|
|
||||||
|
|
||||||
checkSerialData();
|
|
||||||
|
|
||||||
|
|
||||||
printValues();
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if (Btd.isReady()) {
|
|
||||||
timer = millis();
|
|
||||||
if ((Btd.watingForConnection && timer - blinkTimer > 1000) || (!Btd.watingForConnection && timer - blinkTimer > 100)) {
|
|
||||||
blinkTimer = timer;
|
|
||||||
ledState = !ledState;
|
|
||||||
digitalWrite(LED_BUILTIN, ledState);
|
|
||||||
}
|
|
||||||
} else if (ledState) {
|
|
||||||
ledState = !ledState;
|
|
||||||
digitalWrite(LED_BUILTIN, ledState);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,338 +0,0 @@
|
|||||||
#include <SoftwareSerial.h> // required to send and receive AT commands from the GPRS Shield
|
|
||||||
#include <Wire.h> // required for I2C communication with the RTC
|
|
||||||
|
|
||||||
// pin numbers for RTC
|
|
||||||
#define DS3231_I2C_ADDRESS 104 // 0x68 // Address for RTC
|
|
||||||
#define DS3231_TIME_CAL_ADDR 0 // 0x00
|
|
||||||
#define DS3231_ALARM1_ADDR 7 // 0x07
|
|
||||||
#define DS3231_ALARM2_ADDR 11 // 0x0B
|
|
||||||
#define DS3231_CONTROL_ADDR 14 // 0x0E
|
|
||||||
#define DS3231_STATUS_ADDR 15 // 0x0F
|
|
||||||
//#define DS3231_AGING_OFFSET_ADDR 16 // 0x10
|
|
||||||
#define DS3231_TEMPERATURE_ADDR 17 // 0x11
|
|
||||||
|
|
||||||
// Declarations for GPRS shield
|
|
||||||
SoftwareSerial GPRS( 7, 8 ); // A softwareSerial line is defined for the GPRS Shield
|
|
||||||
byte buffer[ 64 ]; // Buffer is used to transfer data from the GPRS line to the serial line
|
|
||||||
int count = 0, e = 0, count2 = 0, t = 0, q;
|
|
||||||
char temp, lastCaller[13] = "blank";
|
|
||||||
boolean callIncoming = false, done;
|
|
||||||
|
|
||||||
// Declarations for RTC
|
|
||||||
byte time[ 7 ]; // second, minute, hour, dow, day, month, year
|
|
||||||
byte time_A1[ 5 ]; // second_A1, minute_A1, hour_A1, day_A1, DY/DT
|
|
||||||
byte time_A2[ 4 ]; // minute_A2, hour_A2, day_A2, DY/DT
|
|
||||||
byte received[1]; // used to catch bytes sent from the clock
|
|
||||||
float temperature; // clock temperature is updated every 64 s
|
|
||||||
|
|
||||||
// Declarations for RemoteCallLogger
|
|
||||||
char telescopeNames[6][4];
|
|
||||||
|
|
||||||
/*
|
|
||||||
Code Exclusively for GPRS shield:
|
|
||||||
*/
|
|
||||||
|
|
||||||
//
|
|
||||||
// Default set of instructions for GPRS Shield power control
|
|
||||||
//
|
|
||||||
|
|
||||||
void setPowerStateTo( int newState )
|
|
||||||
{
|
|
||||||
if( newState != 1 && newState != 0 ) { // tests for an invalid state. In this case no change is made to powerstate
|
|
||||||
Serial.print( "Error: Invalid powerstate. Current powerstate = " );
|
|
||||||
Serial.print( getPowerState() );
|
|
||||||
Serial.print( "\n" );
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
if( newState == getPowerState() ) { // if the requested powerstate is already in effect, no action is taken
|
|
||||||
Serial.print( "Powerstate = " );
|
|
||||||
Serial.print( newState );
|
|
||||||
Serial.print( " remains unchanged.\n" );
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
powerUpOrDown(); // This is the only case where the powerstate is changed
|
|
||||||
Serial.print( "Powerstate changed from " );
|
|
||||||
Serial.print( 1 - newState );
|
|
||||||
Serial.print( " to " );
|
|
||||||
Serial.print( newState );
|
|
||||||
Serial.print( "\n" );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
delay( 5000 ); // for startup
|
|
||||||
}
|
|
||||||
|
|
||||||
int getPowerState() // returns 0 if GPRS Shield is off, and 1 if GPRS Shield is on. This corresponds to the constant HIGH LOW enumeration
|
|
||||||
{
|
|
||||||
int ret;
|
|
||||||
if ( digitalRead(18) == 0 && digitalRead(19) == 0 ) // tests pins 18 and 19 for activity. See ExFoundImportantPins sketch to find out why
|
|
||||||
ret = 1;
|
|
||||||
else
|
|
||||||
ret = 0;
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
void powerUpOrDown() // toggle the power of the shield
|
|
||||||
{
|
|
||||||
pinMode( 9, OUTPUT );
|
|
||||||
digitalWrite( 9, LOW );
|
|
||||||
delay( 1000 );
|
|
||||||
digitalWrite( 9, HIGH );
|
|
||||||
delay( 2000 );
|
|
||||||
digitalWrite( 9, LOW );
|
|
||||||
delay( 3000 );
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// End of default power control
|
|
||||||
//
|
|
||||||
|
|
||||||
void clearBufferArray() // gives each element in the buffer array a null value
|
|
||||||
{
|
|
||||||
for( int i = 0; i < count; i++ )
|
|
||||||
buffer[ i ] = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
void makeMissedCall( char num[] )
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
char in[ 18 ] = "ATD";
|
|
||||||
for( i = 3; i <= 14; i++ ) // AT command string containing telephone number is prepared
|
|
||||||
in[ i ] = num[ i - 3] ;
|
|
||||||
in[ 15 ] = ';';
|
|
||||||
in[ 16 ] = '\r';
|
|
||||||
in[ 17 ] = '\0';
|
|
||||||
GPRS.write( in ); // AT command requesting call is sent
|
|
||||||
delay( 10000 ); // enough time is given for GSM connection, and at least one ring.
|
|
||||||
GPRS.write( "ATH\r\0" ); // AT command requesting hangup is sent
|
|
||||||
delay( 1000 );
|
|
||||||
}
|
|
||||||
|
|
||||||
void sendTextMessage( char number[], char messg[] )
|
|
||||||
{
|
|
||||||
char temp[ 27 ] = "AT + CMGS = \"";
|
|
||||||
for( q = 0; q < 12; q++ ) // for-loop is used to prepare the AT command string containing the telephone number
|
|
||||||
temp[ q + 13 ] = number[ q ];
|
|
||||||
temp[ 25 ] = '\"';
|
|
||||||
temp[ 26 ] = '\0';
|
|
||||||
|
|
||||||
GPRS.println( "AT+CMGF=1\r" ); // AT command requesting SMS in text mode is sent
|
|
||||||
delay( 1000 );
|
|
||||||
GPRS.println( temp ); // AT command containing telephone number is sent
|
|
||||||
delay( 1000 );
|
|
||||||
GPRS.println( messg ); //the content of the message
|
|
||||||
delay( 1000 );
|
|
||||||
GPRS.println( (char) 26 ); //the ASCII code of the ctrl+z is 26. This character indicates the end of the message.
|
|
||||||
delay( 1000 );
|
|
||||||
}
|
|
||||||
|
|
||||||
void analise(byte incoming[], int length) // this function receives and analyses all text sent from the GPRS Shield to the serial line. It stores the cell number of the last caller.
|
|
||||||
{
|
|
||||||
e = 0; // Counter that represents a letter in the buffer
|
|
||||||
done = false; // Boolean that prevents unneccessary loop revolutions
|
|
||||||
while( e < length && !done){ // while e does not surpass the last letter index of the buffer...
|
|
||||||
temp = char( incoming[e] ); // store the character at index e in a temporary char
|
|
||||||
switch( temp ){ // inspect temp
|
|
||||||
case 'R':
|
|
||||||
{
|
|
||||||
if( length > e + 3 && !callIncoming ) { // This case responds to "RING"
|
|
||||||
if(char( incoming[e + 1] ) == 'I'
|
|
||||||
&& char( incoming[e + 2] ) == 'N'
|
|
||||||
&& char( incoming[e + 3] ) == 'G'){
|
|
||||||
GPRS.write("AT+CLCC\r"); // call information is requested
|
|
||||||
delay(500); // time is given for processing
|
|
||||||
GPRS.write("ATH\r"); // GPRS shield hangs up
|
|
||||||
callIncoming = true; // this ensures that a number cannot be stored in any other case than a missed call
|
|
||||||
done = true; // prevents the further operation of this while loop
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case '+':
|
|
||||||
{
|
|
||||||
if(char( buffer[ e + 1]) == '2' && length > e + 11 && callIncoming){ // this case responds to "+2", but only if the buffer contains enough characters for a valid cell number
|
|
||||||
for(t = 0; t < 12; t++) // and only if the callIncoming boolean had been triggered by a previous instance of this function
|
|
||||||
lastCaller[t] = char( buffer[ e + t ]); // the number of this caller is stored in lastCaller
|
|
||||||
lastCaller[12] = '\0';
|
|
||||||
callIncoming = false; // now we are ready for the next call
|
|
||||||
done = true; // prevents the further operation of this while loop
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case 'l':
|
|
||||||
Serial.println(lastCaller); // an easy way to test this function. Simply type "l" to see the value of lastCaller (default "blank")
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
e++; // buffer index is incremented
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
End of GPRS Shield code
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
Code exclusively for RTC
|
|
||||||
*/
|
|
||||||
|
|
||||||
byte decToBcd( byte b ) // converts a byte from a decimal format to a binary-coded decimal
|
|
||||||
{
|
|
||||||
return ( b / 10 << 4 ) + b % 10;
|
|
||||||
}
|
|
||||||
|
|
||||||
boolean getBit( byte addr, int pos ) // returns a single bit from a determined location in the RTC register
|
|
||||||
{
|
|
||||||
byte temp = getByte( addr );
|
|
||||||
return boolean( (temp >> pos) & B00000001 );
|
|
||||||
}
|
|
||||||
|
|
||||||
void setBit( byte addr, int pos, boolean newBit ) // ensures that a single bit from a determined location in the RTC register is a determined value
|
|
||||||
{
|
|
||||||
boolean oldBit = getBit( addr, pos ); // bits' current state is retrieved
|
|
||||||
byte temp = received[ 0 ]; // complete byte is retrieved. it is still left in received from the previous command
|
|
||||||
if ( oldBit != newBit ) // change is only made if the bit isnt already the correct value
|
|
||||||
{
|
|
||||||
if( newBit ) // if newBit is 1, then old bit must be 0, thus we must add an amount
|
|
||||||
temp += (B00000001 << pos); // 2 to the power of the bit position is added to the byte
|
|
||||||
else
|
|
||||||
temp -= (B00000001 << pos); // 2 to the power of the bit position is subtracted from the byte
|
|
||||||
}
|
|
||||||
setByte( addr, temp ); // the register is updated with the new byte
|
|
||||||
}
|
|
||||||
|
|
||||||
byte getByte( byte addr ) // returns a single byte from the given address in the RTC register
|
|
||||||
{
|
|
||||||
byte temp;
|
|
||||||
if( getBytes( addr, 1) ) // If one byte was read from the address:
|
|
||||||
temp = received[ 0 ]; // get that byte
|
|
||||||
else temp = -1; // -1 is returned as an error
|
|
||||||
return temp;
|
|
||||||
}
|
|
||||||
|
|
||||||
boolean getBytes( byte addr, int amount ) // updates the byte array "received" with the given amount of bytes, read from the given address
|
|
||||||
{ // ^ returns false if reading failed
|
|
||||||
boolean wireWorked = false;
|
|
||||||
Wire.beginTransmission( DS3231_I2C_ADDRESS ); // We transmit to the RTC
|
|
||||||
Wire.write( addr ); // We want to read from the given address
|
|
||||||
Wire.endTransmission(); // We want to receive, so we stop transmitting
|
|
||||||
Wire.requestFrom( DS3231_I2C_ADDRESS, amount ); // we request the given amount of bytes from the RTC
|
|
||||||
if( Wire.available() ){
|
|
||||||
received[amount]; // prepare the array for the amount of incoming bytes
|
|
||||||
for( int i = 0; i < amount; i++){
|
|
||||||
received[ i ] = Wire.read(); // we read the given amount of bytes
|
|
||||||
}
|
|
||||||
wireWorked = true; // everything went as planned
|
|
||||||
}
|
|
||||||
return wireWorked;
|
|
||||||
}
|
|
||||||
|
|
||||||
void setByte( byte addr, byte newByte ) // writes a given byte to a given address in the RTCs register. convenient
|
|
||||||
{
|
|
||||||
setBytes( addr, &newByte, 1); // call the setBytes function with the default amount = 1
|
|
||||||
}
|
|
||||||
|
|
||||||
void setBytes( byte addr, byte newBytes[], int amount ) // writes a given amount of bytes in a sequence starting from a given address
|
|
||||||
{
|
|
||||||
Wire.beginTransmission( DS3231_I2C_ADDRESS ); // We transmit to the RTC
|
|
||||||
Wire.write( addr ); // We want to start writing from the given address
|
|
||||||
for( int i = 0; i < amount; i++ )
|
|
||||||
Wire.write( newBytes[ i ] ); // we write each byte in sequence
|
|
||||||
Wire.endTransmission(); // we're done here
|
|
||||||
}
|
|
||||||
|
|
||||||
void getTime() // reads the current time from the register and updates the byte array containing the current time
|
|
||||||
{
|
|
||||||
if( getBytes( DS3231_TIME_CAL_ADDR, 7) ) // if 7 bytes were read in from the time address:
|
|
||||||
{
|
|
||||||
for(int i = 0; i < 7; i++) // place each byte in it's place
|
|
||||||
time[ i ] = received[ i ];
|
|
||||||
// The following conversions convert the values from binary-coded decimal format to regular binary:
|
|
||||||
time[ 0 ] = ( ( time[ 0 ] & B01110000 ) >> 4 ) * 10 + ( time[ 0 ] & B00001111 ); // second
|
|
||||||
time[ 1 ] = ( ( time[ 1 ] & B01110000 ) >> 4 ) * 10 + ( time[ 1 ] & B00001111 ); // minute
|
|
||||||
time[ 2 ] = ( ( time[ 2 ] & B00110000 ) >> 4 ) * 10 + ( time[ 2 ] & B00001111 ); // hour
|
|
||||||
time[ 4 ] = ( ( time[ 4 ] & B00110000 ) >> 4 ) * 10 + ( time[ 4 ] & B00001111 ); // day of month
|
|
||||||
time[ 5 ] = ( ( time[ 5 ] & B00010000 ) >> 4 ) * 10 + ( time[ 5 ] & B00001111 ); // month
|
|
||||||
time[ 6 ] = ( ( time[ 6 ] & B11110000 ) >> 4 ) * 10 + ( time[ 6 ] & B00001111 ); // year
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void setTime( byte newTime[ 7 ] ) // sets the time in the RTC register to the given values
|
|
||||||
{
|
|
||||||
for(int i = 0; i < 7; i++)
|
|
||||||
newTime[i] = decToBcd(newTime[i]); // the time consists of 7 bytes, each which must be converted to binary-coded decimal
|
|
||||||
setBytes( DS3231_TIME_CAL_ADDR, newTime, 7 ); // bytes are sent to be written
|
|
||||||
}
|
|
||||||
|
|
||||||
void getRTCTemperature() // reads the temperature from the register and updates the global temperature float
|
|
||||||
{
|
|
||||||
//temp registers (11h-12h) get updated automatically every 64s
|
|
||||||
if( getBytes( DS3231_TEMPERATURE_ADDR, 2 ) ) // if 2 bytes were read from the temperature addresss
|
|
||||||
{
|
|
||||||
temperature = ( received[ 0 ] & B01111111 ); // assign the integer part of the integer
|
|
||||||
temperature += ( ( received[ 1 ] >> 6 ) * 0.25 ); // assign the fractional part of the temperature
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void gprsListen()
|
|
||||||
{
|
|
||||||
if( GPRS.available() ) { // If the GPRS Shield is transmitting data to the Stalker...
|
|
||||||
while( GPRS.available() ) { // While there is still data left...
|
|
||||||
buffer[ count++ ] = GPRS.read(); // get the next byte of data
|
|
||||||
if ( count == 64 ) // we only handle a maximum of 64 bytes of data at a time
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
Serial.write( buffer, count ); // Send the data to the serial line
|
|
||||||
analise( buffer, count );
|
|
||||||
clearBufferArray(); // clear the buffer
|
|
||||||
count = 0; // reset counter
|
|
||||||
}
|
|
||||||
if (Serial.available()) // if the Stalker is transmitting data....
|
|
||||||
GPRS.write(Serial.read()); // send the data to the GPRS Shield.
|
|
||||||
}
|
|
||||||
|
|
||||||
void printTime() // updates time, and prints it in a convenient format
|
|
||||||
{
|
|
||||||
getTime();
|
|
||||||
Serial.print( int( time[ 3 ] ) ); // dow
|
|
||||||
Serial.print( ' ' );
|
|
||||||
Serial.print( int( time[ 2 ] ) ); // hour
|
|
||||||
Serial.print( ':' );
|
|
||||||
Serial.print( int( time[ 1 ] ) ); // minute
|
|
||||||
Serial.print( ':' );
|
|
||||||
Serial.print( int( time[ 0 ] ) ); // second
|
|
||||||
Serial.print( ' ' );
|
|
||||||
Serial.print( int( time[ 4 ] ) ); // day
|
|
||||||
Serial.print( '/' );
|
|
||||||
Serial.print( int( time[ 5 ] ) ); // month
|
|
||||||
Serial.print( "/20" );
|
|
||||||
Serial.print( int( time[ 6 ] ) ); // year
|
|
||||||
Serial.println();
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
End of RTC code
|
|
||||||
*/
|
|
||||||
|
|
||||||
void setup()
|
|
||||||
{
|
|
||||||
// GPRS Shield startup code
|
|
||||||
GPRS.begin( 9600 );
|
|
||||||
delay(1000);
|
|
||||||
setPowerStateTo(1);
|
|
||||||
delay(1000);
|
|
||||||
|
|
||||||
// RTC Startup code
|
|
||||||
Wire.begin();
|
|
||||||
delay(1000);
|
|
||||||
|
|
||||||
Serial.begin(9600);
|
|
||||||
delay(1000);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
void loop()
|
|
||||||
{
|
|
||||||
gprsListen(); // GPRS Shield listener. Todo: replace w interrupt
|
|
||||||
getTime(); // Updates the time. Todo: replace w interrupt
|
|
||||||
}
|
|
@ -1,339 +0,0 @@
|
|||||||
#include <SoftwareSerial.h>
|
|
||||||
#include <Wire.h>
|
|
||||||
|
|
||||||
|
|
||||||
#define DS3231_I2C_ADDRESS 104
|
|
||||||
#define DS3231_TIME_CAL_ADDR 0
|
|
||||||
#define DS3231_ALARM1_ADDR 7
|
|
||||||
#define DS3231_ALARM2_ADDR 11
|
|
||||||
#define DS3231_CONTROL_ADDR 14
|
|
||||||
#define DS3231_STATUS_ADDR 15
|
|
||||||
|
|
||||||
#define DS3231_TEMPERATURE_ADDR 17
|
|
||||||
|
|
||||||
|
|
||||||
SoftwareSerial GPRS( 7, 8 );
|
|
||||||
byte buffer[ 64 ];
|
|
||||||
int count = 0, e = 0, count2 = 0, t = 0, q;
|
|
||||||
char temp, lastCaller[13] = "blank";
|
|
||||||
boolean callIncoming = false, done;
|
|
||||||
|
|
||||||
|
|
||||||
byte time[ 7 ];
|
|
||||||
byte time_A1[ 5 ];
|
|
||||||
byte time_A2[ 4 ];
|
|
||||||
byte received[1];
|
|
||||||
float temperature;
|
|
||||||
|
|
||||||
|
|
||||||
char telescopeNames[6][4];
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void setPowerStateTo( int newState )
|
|
||||||
{
|
|
||||||
if( newState != 1 && newState != 0 ) {
|
|
||||||
Serial.print( "Error: Invalid powerstate. Current powerstate = " );
|
|
||||||
Serial.print( getPowerState() );
|
|
||||||
Serial.print( "\n" );
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
if( newState == getPowerState() ) {
|
|
||||||
Serial.print( "Powerstate = " );
|
|
||||||
Serial.print( newState );
|
|
||||||
Serial.print( " remains unchanged.\n" );
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
powerUpOrDown();
|
|
||||||
Serial.print( "Powerstate changed from " );
|
|
||||||
Serial.print( 1 - newState );
|
|
||||||
Serial.print( " to " );
|
|
||||||
Serial.print( newState );
|
|
||||||
Serial.print( "\n" );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
delay( 5000 );
|
|
||||||
}
|
|
||||||
|
|
||||||
int getPowerState()
|
|
||||||
{
|
|
||||||
int ret;
|
|
||||||
if ( digitalRead(18) == 0 && digitalRead(19) == 0 )
|
|
||||||
ret = 1;
|
|
||||||
else
|
|
||||||
ret = 0;
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
void powerUpOrDown()
|
|
||||||
{
|
|
||||||
pinMode( 9, OUTPUT );
|
|
||||||
digitalWrite( 9, LOW );
|
|
||||||
delay( 1000 );
|
|
||||||
digitalWrite( 9, HIGH );
|
|
||||||
delay( 2000 );
|
|
||||||
digitalWrite( 9, LOW );
|
|
||||||
delay( 3000 );
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void clearBufferArray()
|
|
||||||
{
|
|
||||||
for( int i = 0; i < count; i++ )
|
|
||||||
buffer[ i ] = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
void makeMissedCall( char num[] )
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
char in[ 18 ] = "ATD";
|
|
||||||
for( i = 3; i <= 14; i++ )
|
|
||||||
in[ i ] = num[ i - 3] ;
|
|
||||||
in[ 15 ] = ';';
|
|
||||||
in[ 16 ] = '\r';
|
|
||||||
in[ 17 ] = '\0';
|
|
||||||
GPRS.write( in );
|
|
||||||
delay( 10000 );
|
|
||||||
GPRS.write( "ATH\r\0" );
|
|
||||||
delay( 1000 );
|
|
||||||
}
|
|
||||||
|
|
||||||
void sendTextMessage( char number[], char messg[] )
|
|
||||||
{
|
|
||||||
char temp[ 27 ] = "AT + CMGS = \"";
|
|
||||||
for( q = 0; q < 12; q++ )
|
|
||||||
temp[ q + 13 ] = number[ q ];
|
|
||||||
temp[ 25 ] = '\"';
|
|
||||||
temp[ 26 ] = '\0';
|
|
||||||
|
|
||||||
GPRS.println( "AT+CMGF=1\r" );
|
|
||||||
delay( 1000 );
|
|
||||||
GPRS.println( temp );
|
|
||||||
delay( 1000 );
|
|
||||||
GPRS.println( messg );
|
|
||||||
delay( 1000 );
|
|
||||||
GPRS.println( (char) 26 );
|
|
||||||
delay( 1000 );
|
|
||||||
}
|
|
||||||
|
|
||||||
void analise(byte incoming[], int length)
|
|
||||||
{
|
|
||||||
e = 0;
|
|
||||||
done = false;
|
|
||||||
while( e < length && !done){
|
|
||||||
temp = char( incoming[e] );
|
|
||||||
switch( temp ){
|
|
||||||
case 'R':
|
|
||||||
{
|
|
||||||
if( length > e + 3 && !callIncoming ) {
|
|
||||||
if(char( incoming[e + 1] ) == 'I'
|
|
||||||
&& char( incoming[e + 2] ) == 'N'
|
|
||||||
&& char( incoming[e + 3] ) == 'G'){
|
|
||||||
GPRS.write("AT+CLCC\r");
|
|
||||||
delay(500);
|
|
||||||
GPRS.write("ATH\r");
|
|
||||||
callIncoming = true;
|
|
||||||
done = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case '+':
|
|
||||||
{
|
|
||||||
if(char( buffer[ e + 1]) == '2' && length > e + 11 && callIncoming){
|
|
||||||
for(t = 0; t < 12; t++)
|
|
||||||
lastCaller[t] = char( buffer[ e + t ]);
|
|
||||||
lastCaller[12] = '\0';
|
|
||||||
callIncoming = false;
|
|
||||||
done = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case 'l':
|
|
||||||
Serial.println(lastCaller);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
e++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
byte decToBcd( byte b )
|
|
||||||
{
|
|
||||||
return ( b / 10 << 4 ) + b % 10;
|
|
||||||
}
|
|
||||||
|
|
||||||
boolean getBit( byte addr, int pos )
|
|
||||||
{
|
|
||||||
byte temp = getByte( addr );
|
|
||||||
return boolean( (temp >> pos) & B00000001 );
|
|
||||||
}
|
|
||||||
|
|
||||||
void setBit( byte addr, int pos, boolean newBit )
|
|
||||||
{
|
|
||||||
boolean oldBit = getBit( addr, pos );
|
|
||||||
byte temp = received[ 0 ];
|
|
||||||
if ( oldBit != newBit )
|
|
||||||
{
|
|
||||||
if( newBit )
|
|
||||||
temp += (B00000001 << pos);
|
|
||||||
else
|
|
||||||
temp -= (B00000001 << pos);
|
|
||||||
}
|
|
||||||
setByte( addr, temp );
|
|
||||||
}
|
|
||||||
|
|
||||||
byte getByte( byte addr )
|
|
||||||
{
|
|
||||||
byte temp;
|
|
||||||
if( getBytes( addr, 1) )
|
|
||||||
temp = received[ 0 ];
|
|
||||||
else temp = -1;
|
|
||||||
return temp;
|
|
||||||
}
|
|
||||||
|
|
||||||
boolean getBytes( byte addr, int amount )
|
|
||||||
{
|
|
||||||
boolean wireWorked = false;
|
|
||||||
Wire.beginTransmission( DS3231_I2C_ADDRESS );
|
|
||||||
Wire.write( addr );
|
|
||||||
Wire.endTransmission();
|
|
||||||
Wire.requestFrom( DS3231_I2C_ADDRESS, amount );
|
|
||||||
if( Wire.available() ){
|
|
||||||
received[amount];
|
|
||||||
for( int i = 0; i < amount; i++){
|
|
||||||
received[ i ] = Wire.read();
|
|
||||||
}
|
|
||||||
wireWorked = true;
|
|
||||||
}
|
|
||||||
return wireWorked;
|
|
||||||
}
|
|
||||||
|
|
||||||
void setByte( byte addr, byte newByte )
|
|
||||||
{
|
|
||||||
setBytes( addr, &newByte, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
void setBytes( byte addr, byte newBytes[], int amount )
|
|
||||||
{
|
|
||||||
Wire.beginTransmission( DS3231_I2C_ADDRESS );
|
|
||||||
Wire.write( addr );
|
|
||||||
for( int i = 0; i < amount; i++ )
|
|
||||||
Wire.write( newBytes[ i ] );
|
|
||||||
Wire.endTransmission();
|
|
||||||
}
|
|
||||||
|
|
||||||
void getTime()
|
|
||||||
{
|
|
||||||
if( getBytes( DS3231_TIME_CAL_ADDR, 7) )
|
|
||||||
{
|
|
||||||
for(int i = 0; i < 7; i++)
|
|
||||||
time[ i ] = received[ i ];
|
|
||||||
|
|
||||||
time[ 0 ] = ( ( time[ 0 ] & B01110000 ) >> 4 ) * 10 + ( time[ 0 ] & B00001111 );
|
|
||||||
time[ 1 ] = ( ( time[ 1 ] & B01110000 ) >> 4 ) * 10 + ( time[ 1 ] & B00001111 );
|
|
||||||
time[ 2 ] = ( ( time[ 2 ] & B00110000 ) >> 4 ) * 10 + ( time[ 2 ] & B00001111 );
|
|
||||||
time[ 4 ] = ( ( time[ 4 ] & B00110000 ) >> 4 ) * 10 + ( time[ 4 ] & B00001111 );
|
|
||||||
time[ 5 ] = ( ( time[ 5 ] & B00010000 ) >> 4 ) * 10 + ( time[ 5 ] & B00001111 );
|
|
||||||
time[ 6 ] = ( ( time[ 6 ] & B11110000 ) >> 4 ) * 10 + ( time[ 6 ] & B00001111 );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void setTime( byte newTime[ 7 ] )
|
|
||||||
{
|
|
||||||
for(int i = 0; i < 7; i++)
|
|
||||||
newTime[i] = decToBcd(newTime[i]);
|
|
||||||
setBytes( DS3231_TIME_CAL_ADDR, newTime, 7 );
|
|
||||||
}
|
|
||||||
|
|
||||||
void getRTCTemperature()
|
|
||||||
{
|
|
||||||
|
|
||||||
if( getBytes( DS3231_TEMPERATURE_ADDR, 2 ) )
|
|
||||||
{
|
|
||||||
temperature = ( received[ 0 ] & B01111111 );
|
|
||||||
temperature += ( ( received[ 1 ] >> 6 ) * 0.25 );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void gprsListen()
|
|
||||||
{
|
|
||||||
if( GPRS.available() ) {
|
|
||||||
while( GPRS.available() ) {
|
|
||||||
buffer[ count++ ] = GPRS.read();
|
|
||||||
if ( count == 64 )
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
Serial.write( buffer, count );
|
|
||||||
analise( buffer, count );
|
|
||||||
clearBufferArray();
|
|
||||||
count = 0;
|
|
||||||
}
|
|
||||||
if (Serial.available())
|
|
||||||
GPRS.write(Serial.read());
|
|
||||||
}
|
|
||||||
|
|
||||||
void printTime()
|
|
||||||
{
|
|
||||||
getTime();
|
|
||||||
Serial.print( int( time[ 3 ] ) );
|
|
||||||
Serial.print( ' ' );
|
|
||||||
Serial.print( int( time[ 2 ] ) );
|
|
||||||
Serial.print( ':' );
|
|
||||||
Serial.print( int( time[ 1 ] ) );
|
|
||||||
Serial.print( ':' );
|
|
||||||
Serial.print( int( time[ 0 ] ) );
|
|
||||||
Serial.print( ' ' );
|
|
||||||
Serial.print( int( time[ 4 ] ) );
|
|
||||||
Serial.print( '/' );
|
|
||||||
Serial.print( int( time[ 5 ] ) );
|
|
||||||
Serial.print( "/20" );
|
|
||||||
Serial.print( int( time[ 6 ] ) );
|
|
||||||
Serial.println();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void setup()
|
|
||||||
{
|
|
||||||
|
|
||||||
GPRS.begin( 9600 );
|
|
||||||
delay(1000);
|
|
||||||
setPowerStateTo(1);
|
|
||||||
delay(1000);
|
|
||||||
|
|
||||||
|
|
||||||
Wire.begin();
|
|
||||||
delay(1000);
|
|
||||||
|
|
||||||
Serial.begin(9600);
|
|
||||||
delay(1000);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
void loop()
|
|
||||||
{
|
|
||||||
gprsListen();
|
|
||||||
getTime();
|
|
||||||
}
|
|
||||||
|
|
@ -1,338 +0,0 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
SoftwareSerial GPRS( 7, 8 );
|
|
||||||
byte buffer[ 64 ];
|
|
||||||
int count = 0, e = 0, count2 = 0, t = 0, q;
|
|
||||||
char temp, lastCaller[13] = ;
|
|
||||||
boolean callIncoming = false, done;
|
|
||||||
|
|
||||||
|
|
||||||
byte time[ 7 ];
|
|
||||||
byte time_A1[ 5 ];
|
|
||||||
byte time_A2[ 4 ];
|
|
||||||
byte received[1];
|
|
||||||
float temperature;
|
|
||||||
|
|
||||||
|
|
||||||
char telescopeNames[6][4];
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void setPowerStateTo( int newState )
|
|
||||||
{
|
|
||||||
if( newState != 1 && newState != 0 ) {
|
|
||||||
Serial.print( );
|
|
||||||
Serial.print( getPowerState() );
|
|
||||||
Serial.print( );
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
if( newState == getPowerState() ) {
|
|
||||||
Serial.print( );
|
|
||||||
Serial.print( newState );
|
|
||||||
Serial.print( );
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
powerUpOrDown();
|
|
||||||
Serial.print( );
|
|
||||||
Serial.print( 1 - newState );
|
|
||||||
Serial.print( );
|
|
||||||
Serial.print( newState );
|
|
||||||
Serial.print( );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
delay( 5000 );
|
|
||||||
}
|
|
||||||
|
|
||||||
int getPowerState()
|
|
||||||
{
|
|
||||||
int ret;
|
|
||||||
if ( digitalRead(18) == 0 && digitalRead(19) == 0 )
|
|
||||||
ret = 1;
|
|
||||||
else
|
|
||||||
ret = 0;
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
void powerUpOrDown()
|
|
||||||
{
|
|
||||||
pinMode( 9, OUTPUT );
|
|
||||||
digitalWrite( 9, LOW );
|
|
||||||
delay( 1000 );
|
|
||||||
digitalWrite( 9, HIGH );
|
|
||||||
delay( 2000 );
|
|
||||||
digitalWrite( 9, LOW );
|
|
||||||
delay( 3000 );
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void clearBufferArray()
|
|
||||||
{
|
|
||||||
for( int i = 0; i < count; i++ )
|
|
||||||
buffer[ i ] = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
void makeMissedCall( char num[] )
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
char in[ 18 ] = ;
|
|
||||||
for( i = 3; i <= 14; i++ )
|
|
||||||
in[ i ] = num[ i - 3] ;
|
|
||||||
in[ 15 ] = ;
|
|
||||||
in[ 16 ] = '\r';
|
|
||||||
in[ 17 ] = '\0';
|
|
||||||
GPRS.write( in );
|
|
||||||
delay( 10000 );
|
|
||||||
GPRS.write( );
|
|
||||||
delay( 1000 );
|
|
||||||
}
|
|
||||||
|
|
||||||
void sendTextMessage( char number[], char messg[] )
|
|
||||||
{
|
|
||||||
char temp[ 27 ] = ;
|
|
||||||
for( q = 0; q < 12; q++ )
|
|
||||||
temp[ q + 13 ] = number[ q ];
|
|
||||||
temp[ 25 ] = ;
|
|
||||||
temp[ 26 ] = '\0';
|
|
||||||
|
|
||||||
GPRS.println( );
|
|
||||||
delay( 1000 );
|
|
||||||
GPRS.println( temp );
|
|
||||||
delay( 1000 );
|
|
||||||
GPRS.println( messg );
|
|
||||||
delay( 1000 );
|
|
||||||
GPRS.println( (char) 26 );
|
|
||||||
delay( 1000 );
|
|
||||||
}
|
|
||||||
|
|
||||||
void analise(byte incoming[], int length)
|
|
||||||
{
|
|
||||||
e = 0;
|
|
||||||
done = false;
|
|
||||||
while( e < length && !done){
|
|
||||||
temp = char( incoming[e] );
|
|
||||||
switch( temp ){
|
|
||||||
case :
|
|
||||||
{
|
|
||||||
if( length > e + 3 && !callIncoming ) {
|
|
||||||
if(char( incoming[e + 1] ) ==
|
|
||||||
&& char( incoming[e + 2] ) ==
|
|
||||||
&& char( incoming[e + 3] ) == ){
|
|
||||||
GPRS.write( );
|
|
||||||
delay(500);
|
|
||||||
GPRS.write( );
|
|
||||||
callIncoming = true;
|
|
||||||
done = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case :
|
|
||||||
{
|
|
||||||
if(char( buffer[ e + 1]) == && length > e + 11 && callIncoming){
|
|
||||||
for(t = 0; t < 12; t++)
|
|
||||||
lastCaller[t] = char( buffer[ e + t ]);
|
|
||||||
lastCaller[12] = '\0';
|
|
||||||
callIncoming = false;
|
|
||||||
done = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case :
|
|
||||||
Serial.println(lastCaller);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
e++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
byte decToBcd( byte b )
|
|
||||||
{
|
|
||||||
return ( b / 10 << 4 ) + b % 10;
|
|
||||||
}
|
|
||||||
|
|
||||||
boolean getBit( byte addr, int pos )
|
|
||||||
{
|
|
||||||
byte temp = getByte( addr );
|
|
||||||
return boolean( (temp >> pos) & B00000001 );
|
|
||||||
}
|
|
||||||
|
|
||||||
void setBit( byte addr, int pos, boolean newBit )
|
|
||||||
{
|
|
||||||
boolean oldBit = getBit( addr, pos );
|
|
||||||
byte temp = received[ 0 ];
|
|
||||||
if ( oldBit != newBit )
|
|
||||||
{
|
|
||||||
if( newBit )
|
|
||||||
temp += (B00000001 << pos);
|
|
||||||
else
|
|
||||||
temp -= (B00000001 << pos);
|
|
||||||
}
|
|
||||||
setByte( addr, temp );
|
|
||||||
}
|
|
||||||
|
|
||||||
byte getByte( byte addr )
|
|
||||||
{
|
|
||||||
byte temp;
|
|
||||||
if( getBytes( addr, 1) )
|
|
||||||
temp = received[ 0 ];
|
|
||||||
else temp = -1;
|
|
||||||
return temp;
|
|
||||||
}
|
|
||||||
|
|
||||||
boolean getBytes( byte addr, int amount )
|
|
||||||
{
|
|
||||||
boolean wireWorked = false;
|
|
||||||
Wire.beginTransmission( DS3231_I2C_ADDRESS );
|
|
||||||
Wire.write( addr );
|
|
||||||
Wire.endTransmission();
|
|
||||||
Wire.requestFrom( DS3231_I2C_ADDRESS, amount );
|
|
||||||
if( Wire.available() ){
|
|
||||||
received[amount];
|
|
||||||
for( int i = 0; i < amount; i++){
|
|
||||||
received[ i ] = Wire.read();
|
|
||||||
}
|
|
||||||
wireWorked = true;
|
|
||||||
}
|
|
||||||
return wireWorked;
|
|
||||||
}
|
|
||||||
|
|
||||||
void setByte( byte addr, byte newByte )
|
|
||||||
{
|
|
||||||
setBytes( addr, &newByte, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
void setBytes( byte addr, byte newBytes[], int amount )
|
|
||||||
{
|
|
||||||
Wire.beginTransmission( DS3231_I2C_ADDRESS );
|
|
||||||
Wire.write( addr );
|
|
||||||
for( int i = 0; i < amount; i++ )
|
|
||||||
Wire.write( newBytes[ i ] );
|
|
||||||
Wire.endTransmission();
|
|
||||||
}
|
|
||||||
|
|
||||||
void getTime()
|
|
||||||
{
|
|
||||||
if( getBytes( DS3231_TIME_CAL_ADDR, 7) )
|
|
||||||
{
|
|
||||||
for(int i = 0; i < 7; i++)
|
|
||||||
time[ i ] = received[ i ];
|
|
||||||
|
|
||||||
time[ 0 ] = ( ( time[ 0 ] & B01110000 ) >> 4 ) * 10 + ( time[ 0 ] & B00001111 );
|
|
||||||
time[ 1 ] = ( ( time[ 1 ] & B01110000 ) >> 4 ) * 10 + ( time[ 1 ] & B00001111 );
|
|
||||||
time[ 2 ] = ( ( time[ 2 ] & B00110000 ) >> 4 ) * 10 + ( time[ 2 ] & B00001111 );
|
|
||||||
time[ 4 ] = ( ( time[ 4 ] & B00110000 ) >> 4 ) * 10 + ( time[ 4 ] & B00001111 );
|
|
||||||
time[ 5 ] = ( ( time[ 5 ] & B00010000 ) >> 4 ) * 10 + ( time[ 5 ] & B00001111 );
|
|
||||||
time[ 6 ] = ( ( time[ 6 ] & B11110000 ) >> 4 ) * 10 + ( time[ 6 ] & B00001111 );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void setTime( byte newTime[ 7 ] )
|
|
||||||
{
|
|
||||||
for(int i = 0; i < 7; i++)
|
|
||||||
newTime[i] = decToBcd(newTime[i]);
|
|
||||||
setBytes( DS3231_TIME_CAL_ADDR, newTime, 7 );
|
|
||||||
}
|
|
||||||
|
|
||||||
void getRTCTemperature()
|
|
||||||
{
|
|
||||||
|
|
||||||
if( getBytes( DS3231_TEMPERATURE_ADDR, 2 ) )
|
|
||||||
{
|
|
||||||
temperature = ( received[ 0 ] & B01111111 );
|
|
||||||
temperature += ( ( received[ 1 ] >> 6 ) * 0.25 );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void gprsListen()
|
|
||||||
{
|
|
||||||
if( GPRS.available() ) {
|
|
||||||
while( GPRS.available() ) {
|
|
||||||
buffer[ count++ ] = GPRS.read();
|
|
||||||
if ( count == 64 )
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
Serial.write( buffer, count );
|
|
||||||
analise( buffer, count );
|
|
||||||
clearBufferArray();
|
|
||||||
count = 0;
|
|
||||||
}
|
|
||||||
if (Serial.available())
|
|
||||||
GPRS.write(Serial.read());
|
|
||||||
}
|
|
||||||
|
|
||||||
void printTime()
|
|
||||||
{
|
|
||||||
getTime();
|
|
||||||
Serial.print( int( time[ 3 ] ) );
|
|
||||||
Serial.print( );
|
|
||||||
Serial.print( int( time[ 2 ] ) );
|
|
||||||
Serial.print( );
|
|
||||||
Serial.print( int( time[ 1 ] ) );
|
|
||||||
Serial.print( );
|
|
||||||
Serial.print( int( time[ 0 ] ) );
|
|
||||||
Serial.print( );
|
|
||||||
Serial.print( int( time[ 4 ] ) );
|
|
||||||
Serial.print( );
|
|
||||||
Serial.print( int( time[ 5 ] ) );
|
|
||||||
Serial.print( );
|
|
||||||
Serial.print( int( time[ 6 ] ) );
|
|
||||||
Serial.println();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void setup()
|
|
||||||
{
|
|
||||||
|
|
||||||
GPRS.begin( 9600 );
|
|
||||||
delay(1000);
|
|
||||||
setPowerStateTo(1);
|
|
||||||
delay(1000);
|
|
||||||
|
|
||||||
|
|
||||||
Wire.begin();
|
|
||||||
delay(1000);
|
|
||||||
|
|
||||||
Serial.begin(9600);
|
|
||||||
delay(1000);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
void loop()
|
|
||||||
{
|
|
||||||
gprsListen();
|
|
||||||
getTime();
|
|
||||||
}
|
|
@ -1,15 +0,0 @@
|
|||||||
#include <CapacitiveSensorDue.h>
|
|
||||||
/*
|
|
||||||
#include <WiFi.h>
|
|
||||||
*/
|
|
||||||
CapacitiveSensorDue cs_13_8 = CapacitiveSensorDue(13,8);
|
|
||||||
void setup()
|
|
||||||
{
|
|
||||||
Serial.begin(9600);
|
|
||||||
}
|
|
||||||
void loop()
|
|
||||||
{
|
|
||||||
long total1 = cs_13_8.read(30);
|
|
||||||
Serial.println(total1);
|
|
||||||
delay(100);
|
|
||||||
}
|
|
@ -1,16 +0,0 @@
|
|||||||
#include <CapacitiveSensorDue.h>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
CapacitiveSensorDue cs_13_8 = CapacitiveSensorDue(13,8);
|
|
||||||
void setup()
|
|
||||||
{
|
|
||||||
Serial.begin(9600);
|
|
||||||
}
|
|
||||||
void loop()
|
|
||||||
{
|
|
||||||
long total1 = cs_13_8.read(30);
|
|
||||||
Serial.println(total1);
|
|
||||||
delay(100);
|
|
||||||
}
|
|
||||||
|
|
@ -1,15 +0,0 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
CapacitiveSensorDue cs_13_8 = CapacitiveSensorDue(13,8);
|
|
||||||
void setup()
|
|
||||||
{
|
|
||||||
Serial.begin(9600);
|
|
||||||
}
|
|
||||||
void loop()
|
|
||||||
{
|
|
||||||
long total1 = cs_13_8.read(30);
|
|
||||||
Serial.println(total1);
|
|
||||||
delay(100);
|
|
||||||
}
|
|
@ -1,34 +0,0 @@
|
|||||||
const char *foo = "\
|
|
||||||
hello \
|
|
||||||
world\n";
|
|
||||||
|
|
||||||
//" delete this comment line and the IDE parser will crash
|
|
||||||
|
|
||||||
void setup()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void loop()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
/*
|
|
||||||
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
|
|
||||||
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
|
|
||||||
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
|
|
||||||
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
|
|
||||||
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
|
|
||||||
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
|
|
||||||
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
|
|
||||||
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
|
|
||||||
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
|
|
||||||
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
|
|
||||||
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
|
|
||||||
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
|
|
||||||
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
|
|
||||||
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
|
|
||||||
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
|
|
||||||
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
|
|
||||||
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
|
|
||||||
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
|
|
||||||
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
|
|
||||||
*/
|
|
@ -1,35 +0,0 @@
|
|||||||
const char *foo = "\
|
|
||||||
hello \
|
|
||||||
world\n";
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void setup()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void loop()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -1,34 +0,0 @@
|
|||||||
const char *foo =
|
|
||||||
|
|
||||||
;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void setup()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void loop()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -1,175 +0,0 @@
|
|||||||
/*
|
|
||||||
* This file is part of Arduino.
|
|
||||||
*
|
|
||||||
* Copyright 2015 Arduino LLC (http://www.arduino.cc/)
|
|
||||||
*
|
|
||||||
* Arduino is free software; you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation; either version 2 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program; if not, write to the Free Software
|
|
||||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
|
||||||
*
|
|
||||||
* As a special exception, you may use this file as part of a free software
|
|
||||||
* library without restriction. Specifically, if other files instantiate
|
|
||||||
* templates or use macros or inline functions from this file, or you compile
|
|
||||||
* this file and link it with other files to produce an executable, this
|
|
||||||
* file does not by itself cause the resulting executable to be covered by
|
|
||||||
* the GNU General Public License. This exception does not however
|
|
||||||
* invalidate any other reasons why the executable file might be covered by
|
|
||||||
* the GNU General Public License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package processing.app.preproc;
|
|
||||||
|
|
||||||
import org.junit.Test;
|
|
||||||
import processing.app.helpers.FileUtils;
|
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
|
|
||||||
import static org.junit.Assert.assertEquals;
|
|
||||||
|
|
||||||
public class PdePreprocessorTest {
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testSourceWithQuoteAndDoubleQuotesEscapedAndFinalQuoteShouldNotRaiseException() throws Exception {
|
|
||||||
String s = FileUtils.readFileToString(new File(PdePreprocessorTest.class.getResource("RemoteCallLogger_v1e0.ino").getFile()));
|
|
||||||
|
|
||||||
PdePreprocessor pdePreprocessor = new PdePreprocessor();
|
|
||||||
String strippedOutput = pdePreprocessor.strip(s);
|
|
||||||
String expectedStrippedOutput = FileUtils.readFileToString(new File(PdePreprocessorTest.class.getResource("RemoteCallLogger_v1e0.stripped.ino").getFile()));
|
|
||||||
|
|
||||||
assertEquals(expectedStrippedOutput, strippedOutput);
|
|
||||||
|
|
||||||
pdePreprocessor.writePrefix(s);
|
|
||||||
|
|
||||||
String actualCodeWithoutComments = pdePreprocessor.program;
|
|
||||||
String expectedCodeWithoutComments = FileUtils.readFileToString(new File(PdePreprocessorTest.class.getResource("RemoteCallLogger_v1e0.nocomments.ino").getFile()));
|
|
||||||
|
|
||||||
assertEquals(expectedCodeWithoutComments, actualCodeWithoutComments);
|
|
||||||
|
|
||||||
assertEquals(2, pdePreprocessor.getExtraImports().size());
|
|
||||||
assertEquals("SoftwareSerial.h", pdePreprocessor.getExtraImports().get(0));
|
|
||||||
assertEquals("Wire.h", pdePreprocessor.getExtraImports().get(1));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testIncludeInsideMultilineComment() throws Exception {
|
|
||||||
String s = FileUtils.readFileToString(new File(PdePreprocessorTest.class.getResource("IncludeBetweenMultilineComment.ino").getFile()));
|
|
||||||
|
|
||||||
PdePreprocessor pdePreprocessor = new PdePreprocessor();
|
|
||||||
String strippedOutput = pdePreprocessor.strip(s);
|
|
||||||
String expectedStrippedOutput = FileUtils.readFileToString(new File(PdePreprocessorTest.class.getResource("IncludeBetweenMultilineComment.stripped.ino").getFile()));
|
|
||||||
|
|
||||||
assertEquals(expectedStrippedOutput, strippedOutput);
|
|
||||||
|
|
||||||
pdePreprocessor.writePrefix(s);
|
|
||||||
|
|
||||||
String actualCodeWithoutComments = pdePreprocessor.program;
|
|
||||||
String expectedCodeWithoutComments = FileUtils.readFileToString(new File(PdePreprocessorTest.class.getResource("IncludeBetweenMultilineComment.nocomments.ino").getFile()));
|
|
||||||
|
|
||||||
assertEquals(expectedCodeWithoutComments, actualCodeWithoutComments);
|
|
||||||
|
|
||||||
assertEquals(1, pdePreprocessor.getExtraImports().size());
|
|
||||||
assertEquals("CapacitiveSensorDue.h", pdePreprocessor.getExtraImports().get(0));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testPdePreprocessorRegressionBaladuino() throws Exception {
|
|
||||||
String s = FileUtils.readFileToString(new File(PdePreprocessorTest.class.getResource("Baladuino.ino").getFile()));
|
|
||||||
|
|
||||||
PdePreprocessor pdePreprocessor = new PdePreprocessor();
|
|
||||||
String strippedOutput = pdePreprocessor.strip(s);
|
|
||||||
String expectedStrippedOutput = FileUtils.readFileToString(new File(PdePreprocessorTest.class.getResource("Baladuino.stripped.ino").getFile()));
|
|
||||||
|
|
||||||
assertEquals(expectedStrippedOutput, strippedOutput);
|
|
||||||
|
|
||||||
pdePreprocessor.writePrefix(s);
|
|
||||||
|
|
||||||
String actualCodeWithoutComments = pdePreprocessor.program;
|
|
||||||
String expectedCodeWithoutComments = FileUtils.readFileToString(new File(PdePreprocessorTest.class.getResource("Baladuino.nocomments.ino").getFile()));
|
|
||||||
|
|
||||||
assertEquals(expectedCodeWithoutComments, actualCodeWithoutComments);
|
|
||||||
|
|
||||||
assertEquals(9, pdePreprocessor.getExtraImports().size());
|
|
||||||
assertEquals("Balanduino.h", pdePreprocessor.getExtraImports().get(0));
|
|
||||||
assertEquals("Wire.h", pdePreprocessor.getExtraImports().get(1));
|
|
||||||
assertEquals("usbhub.h", pdePreprocessor.getExtraImports().get(2));
|
|
||||||
assertEquals("adk.h", pdePreprocessor.getExtraImports().get(3));
|
|
||||||
assertEquals("Kalman.h", pdePreprocessor.getExtraImports().get(4));
|
|
||||||
assertEquals("XBOXRECV.h", pdePreprocessor.getExtraImports().get(5));
|
|
||||||
assertEquals("SPP.h", pdePreprocessor.getExtraImports().get(6));
|
|
||||||
assertEquals("PS3BT.h", pdePreprocessor.getExtraImports().get(7));
|
|
||||||
assertEquals("Wii.h", pdePreprocessor.getExtraImports().get(8));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testStringWithCcomment() throws Exception {
|
|
||||||
String s = FileUtils.readFileToString(new File(PdePreprocessorTest.class.getResource("StringWithCcomment.ino").getFile()));
|
|
||||||
|
|
||||||
PdePreprocessor pdePreprocessor = new PdePreprocessor();
|
|
||||||
String strippedOutput = pdePreprocessor.strip(s);
|
|
||||||
String expectedStrippedOutput = FileUtils.readFileToString(new File(PdePreprocessorTest.class.getResource("StringWithCcomment.stripped.ino").getFile()));
|
|
||||||
|
|
||||||
assertEquals(expectedStrippedOutput, strippedOutput);
|
|
||||||
|
|
||||||
pdePreprocessor.writePrefix(s);
|
|
||||||
|
|
||||||
String actualCodeWithoutComments = pdePreprocessor.program;
|
|
||||||
String expectedCodeWithoutComments = FileUtils.readFileToString(new File(PdePreprocessorTest.class.getResource("StringWithCcomment.nocomments.ino").getFile()));
|
|
||||||
|
|
||||||
assertEquals(expectedCodeWithoutComments, actualCodeWithoutComments);
|
|
||||||
|
|
||||||
assertEquals(0, pdePreprocessor.getExtraImports().size());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testCharWithEscapedDoubleQuote() throws Exception {
|
|
||||||
String s = FileUtils.readFileToString(new File(PdePreprocessorTest.class.getResource("CharWithEscapedDoubleQuote.ino").getFile()));
|
|
||||||
|
|
||||||
PdePreprocessor pdePreprocessor = new PdePreprocessor();
|
|
||||||
String strippedOutput = pdePreprocessor.strip(s);
|
|
||||||
String expectedStrippedOutput = FileUtils.readFileToString(new File(PdePreprocessorTest.class.getResource("CharWithEscapedDoubleQuote.stripped.ino").getFile()));
|
|
||||||
|
|
||||||
assertEquals(expectedStrippedOutput, strippedOutput);
|
|
||||||
|
|
||||||
pdePreprocessor.writePrefix(s);
|
|
||||||
|
|
||||||
String actualCodeWithoutComments = pdePreprocessor.program;
|
|
||||||
String expectedCodeWithoutComments = FileUtils.readFileToString(new File(PdePreprocessorTest.class.getResource("CharWithEscapedDoubleQuote.nocomments.ino").getFile()));
|
|
||||||
|
|
||||||
assertEquals(expectedCodeWithoutComments, actualCodeWithoutComments);
|
|
||||||
|
|
||||||
assertEquals(2, pdePreprocessor.getExtraImports().size());
|
|
||||||
assertEquals("SoftwareSerial.h", pdePreprocessor.getExtraImports().get(0));
|
|
||||||
assertEquals("Wire.h", pdePreprocessor.getExtraImports().get(1));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testLineContinuations() throws Exception {
|
|
||||||
String s = FileUtils.readFileToString(new File(PdePreprocessorTest.class.getResource("LineContinuations.ino").getFile()));
|
|
||||||
|
|
||||||
PdePreprocessor pdePreprocessor = new PdePreprocessor();
|
|
||||||
String strippedOutput = pdePreprocessor.strip(s);
|
|
||||||
String expectedStrippedOutput = FileUtils.readFileToString(new File(PdePreprocessorTest.class.getResource("LineContinuations.stripped.ino").getFile()));
|
|
||||||
|
|
||||||
assertEquals(expectedStrippedOutput, strippedOutput);
|
|
||||||
|
|
||||||
pdePreprocessor.writePrefix(s);
|
|
||||||
|
|
||||||
String actualCodeWithoutComments = pdePreprocessor.program;
|
|
||||||
String expectedCodeWithoutComments = FileUtils.readFileToString(new File(PdePreprocessorTest.class.getResource("LineContinuations.nocomments.ino").getFile()));
|
|
||||||
|
|
||||||
assertEquals(expectedCodeWithoutComments, actualCodeWithoutComments);
|
|
||||||
|
|
||||||
assertEquals(0, pdePreprocessor.getExtraImports().size());
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,343 +0,0 @@
|
|||||||
|
|
||||||
#include <SoftwareSerial.h> // required to send and receive AT commands from the GPRS Shield
|
|
||||||
#include <Wire.h> // required for I2C communication with the RTC
|
|
||||||
|
|
||||||
// pin numbers for RTC
|
|
||||||
#define DS3231_I2C_ADDRESS 104 // 0x68 // Address for RTC
|
|
||||||
#define DS3231_TIME_CAL_ADDR 0 // 0x00
|
|
||||||
#define DS3231_ALARM1_ADDR 7 // 0x07
|
|
||||||
#define DS3231_ALARM2_ADDR 11 // 0x0B
|
|
||||||
#define DS3231_CONTROL_ADDR 14 // 0x0E
|
|
||||||
#define DS3231_STATUS_ADDR 15 // 0x0F
|
|
||||||
//#define DS3231_AGING_OFFSET_ADDR 16 // 0x10
|
|
||||||
#define DS3231_TEMPERATURE_ADDR 17 // 0x11
|
|
||||||
|
|
||||||
// Declarations for GPRS shield
|
|
||||||
SoftwareSerial GPRS( 7, 8 ); // A softwareSerial line is defined for the GPRS Shield
|
|
||||||
byte buffer[ 64 ]; // Buffer is used to transfer data from the GPRS line to the serial line
|
|
||||||
int count = 0, e = 0, count2 = 0, t = 0, q;
|
|
||||||
char temp, lastCaller[13] = "blank";
|
|
||||||
boolean callIncoming = false, done;
|
|
||||||
|
|
||||||
// Declarations for RTC
|
|
||||||
byte time[ 7 ]; // second, minute, hour, dow, day, month, year
|
|
||||||
byte time_A1[ 5 ]; // second_A1, minute_A1, hour_A1, day_A1, DY/DT
|
|
||||||
byte time_A2[ 4 ]; // minute_A2, hour_A2, day_A2, DY/DT
|
|
||||||
byte received[1]; // used to catch bytes sent from the clock
|
|
||||||
float temperature; // clock temperature is updated every 64 s
|
|
||||||
|
|
||||||
// Declarations for RemoteCallLogger
|
|
||||||
char telescopeNames[6][4];
|
|
||||||
|
|
||||||
/*
|
|
||||||
Code Exclusively for GPRS shield:
|
|
||||||
*/
|
|
||||||
|
|
||||||
//
|
|
||||||
// Default set of instructions for GPRS Shield power control
|
|
||||||
//
|
|
||||||
|
|
||||||
void setPowerStateTo( int newState )
|
|
||||||
{
|
|
||||||
if( newState != 1 && newState != 0 ) { // tests for an invalid state. In this case no change is made to powerstate
|
|
||||||
Serial.print( "Error: Invalid powerstate. Current powerstate = " );
|
|
||||||
Serial.print( getPowerState() );
|
|
||||||
Serial.print( "\n" );
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
if( newState == getPowerState() ) { // if the requested powerstate is already in effect, no action is taken
|
|
||||||
Serial.print( "Powerstate = " );
|
|
||||||
Serial.print( newState );
|
|
||||||
Serial.print( " remains unchanged.\n" );
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
powerUpOrDown(); // This is the only case where the powerstate is changed
|
|
||||||
Serial.print( "Powerstate changed from " );
|
|
||||||
Serial.print( 1 - newState );
|
|
||||||
Serial.print( " to " );
|
|
||||||
Serial.print( newState );
|
|
||||||
Serial.print( "\n" );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
delay( 5000 ); // for startup
|
|
||||||
}
|
|
||||||
|
|
||||||
int getPowerState() // returns 0 if GPRS Shield is off, and 1 if GPRS Shield is on. This corresponds to the constant HIGH LOW enumeration
|
|
||||||
{
|
|
||||||
int ret;
|
|
||||||
if ( digitalRead(18) == 0 && digitalRead(19) == 0 ) // tests pins 18 and 19 for activity. See ExFoundImportantPins sketch to find out why
|
|
||||||
ret = 1;
|
|
||||||
else
|
|
||||||
ret = 0;
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
void powerUpOrDown() // toggle the power of the shield
|
|
||||||
{
|
|
||||||
pinMode( 9, OUTPUT );
|
|
||||||
digitalWrite( 9, LOW );
|
|
||||||
delay( 1000 );
|
|
||||||
digitalWrite( 9, HIGH );
|
|
||||||
delay( 2000 );
|
|
||||||
digitalWrite( 9, LOW );
|
|
||||||
delay( 3000 );
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// End of default power control
|
|
||||||
//
|
|
||||||
|
|
||||||
void clearBufferArray() // gives each element in the buffer array a null value
|
|
||||||
{
|
|
||||||
for( int i = 0; i < count; i++ )
|
|
||||||
buffer[ i ] = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
void makeMissedCall( char num[] )
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
char in[ 18 ] = "ATD";
|
|
||||||
for( i = 3; i <= 14; i++ ) // AT command string containing telephone number is prepared
|
|
||||||
in[ i ] = num[ i - 3] ;
|
|
||||||
in[ 15 ] = ';';
|
|
||||||
in[ 16 ] = '\r';
|
|
||||||
in[ 17 ] = '\0';
|
|
||||||
GPRS.write( in ); // AT command requesting call is sent
|
|
||||||
delay( 10000 ); // enough time is given for GSM connection, and at least one ring.
|
|
||||||
GPRS.write( "ATH\r\0" ); // AT command requesting hangup is sent
|
|
||||||
delay( 1000 );
|
|
||||||
}
|
|
||||||
|
|
||||||
void sendTextMessage( char number[], char messg[] )
|
|
||||||
{
|
|
||||||
char temp[ 27 ] = "AT + CMGS = \"";
|
|
||||||
for( q = 0; q < 12; q++ ) // for-loop is used to prepare the AT command string containing the telephone number
|
|
||||||
temp[ q + 13 ] = number[ q ];
|
|
||||||
temp[ 25 ] = '\"';
|
|
||||||
temp[ 26 ] = '\0';
|
|
||||||
|
|
||||||
GPRS.println( "AT+CMGF=1\r" ); // AT command requesting SMS in text mode is sent
|
|
||||||
delay( 1000 );
|
|
||||||
GPRS.println( temp ); // AT command containing telephone number is sent
|
|
||||||
delay( 1000 );
|
|
||||||
GPRS.println( messg ); //the content of the message
|
|
||||||
delay( 1000 );
|
|
||||||
GPRS.println( (char) 26 ); //the ASCII code of the ctrl+z is 26. This character indicates the end of the message.
|
|
||||||
delay( 1000 );
|
|
||||||
}
|
|
||||||
|
|
||||||
void analise(byte incoming[], int length) // this function receives and analyses all text sent from the GPRS Shield to the serial line. It stores the cell number of the last caller.
|
|
||||||
{
|
|
||||||
e = 0; // Counter that represents a letter in the buffer
|
|
||||||
done = false; // Boolean that prevents unneccessary loop revolutions
|
|
||||||
while( e < length && !done){ // while e does not surpass the last letter index of the buffer...
|
|
||||||
temp = char( incoming[e] ); // store the character at index e in a temporary char
|
|
||||||
switch( temp ){ // inspect temp
|
|
||||||
case 'R':
|
|
||||||
{
|
|
||||||
if( length > e + 3 && !callIncoming ) { // This case responds to "RING"
|
|
||||||
if(char( incoming[e + 1] ) == 'I'
|
|
||||||
&& char( incoming[e + 2] ) == 'N'
|
|
||||||
&& char( incoming[e + 3] ) == 'G'){
|
|
||||||
GPRS.write("AT+CLCC\r"); // call information is requested
|
|
||||||
delay(500); // time is given for processing
|
|
||||||
GPRS.write("ATH\r"); // GPRS shield hangs up
|
|
||||||
callIncoming = true; // this ensures that a number cannot be stored in any other case than a missed call
|
|
||||||
done = true; // prevents the further operation of this while loop
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case '+':
|
|
||||||
{
|
|
||||||
if(char( buffer[ e + 1]) == '2' && length > e + 11 && callIncoming){ // this case responds to "+2", but only if the buffer contains enough characters for a valid cell number
|
|
||||||
for(t = 0; t < 12; t++) // and only if the callIncoming boolean had been triggered by a previous instance of this function
|
|
||||||
lastCaller[t] = char( buffer[ e + t ]); // the number of this caller is stored in lastCaller
|
|
||||||
lastCaller[12] = '\0';
|
|
||||||
callIncoming = false; // now we are ready for the next call
|
|
||||||
done = true; // prevents the further operation of this while loop
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case 'l':
|
|
||||||
Serial.println(lastCaller); // an easy way to test this function. Simply type "l" to see the value of lastCaller (default "blank")
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
e++; // buffer index is incremented
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
End of GPRS Shield code
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
Code exclusively for RTC
|
|
||||||
*/
|
|
||||||
|
|
||||||
byte decToBcd( byte b ) // converts a byte from a decimal format to a binary-coded decimal
|
|
||||||
{
|
|
||||||
return ( b / 10 << 4 ) + b % 10;
|
|
||||||
}
|
|
||||||
|
|
||||||
boolean getBit( byte addr, int pos ) // returns a single bit from a determined location in the RTC register
|
|
||||||
{
|
|
||||||
byte temp = getByte( addr );
|
|
||||||
return boolean( (temp >> pos) & B00000001 );
|
|
||||||
}
|
|
||||||
|
|
||||||
void setBit( byte addr, int pos, boolean newBit ) // ensures that a single bit from a determined location in the RTC register is a determined value
|
|
||||||
{
|
|
||||||
boolean oldBit = getBit( addr, pos ); // bits' current state is retrieved
|
|
||||||
byte temp = received[ 0 ]; // complete byte is retrieved. it is still left in received from the previous command
|
|
||||||
if ( oldBit != newBit ) // change is only made if the bit isnt already the correct value
|
|
||||||
{
|
|
||||||
if( newBit ) // if newBit is 1, then old bit must be 0, thus we must add an amount
|
|
||||||
temp += (B00000001 << pos); // 2 to the power of the bit position is added to the byte
|
|
||||||
else
|
|
||||||
temp -= (B00000001 << pos); // 2 to the power of the bit position is subtracted from the byte
|
|
||||||
}
|
|
||||||
setByte( addr, temp ); // the register is updated with the new byte
|
|
||||||
}
|
|
||||||
|
|
||||||
byte getByte( byte addr ) // returns a single byte from the given address in the RTC register
|
|
||||||
{
|
|
||||||
byte temp;
|
|
||||||
if( getBytes( addr, 1) ) // If one byte was read from the address:
|
|
||||||
temp = received[ 0 ]; // get that byte
|
|
||||||
else temp = -1; // -1 is returned as an error
|
|
||||||
return temp;
|
|
||||||
}
|
|
||||||
|
|
||||||
boolean getBytes( byte addr, int amount ) // updates the byte array "received" with the given amount of bytes, read from the given address
|
|
||||||
{ // ^ returns false if reading failed
|
|
||||||
boolean wireWorked = false;
|
|
||||||
Wire.beginTransmission( DS3231_I2C_ADDRESS ); // We transmit to the RTC
|
|
||||||
Wire.write( addr ); // We want to read from the given address
|
|
||||||
Wire.endTransmission(); // We want to receive, so we stop transmitting
|
|
||||||
Wire.requestFrom( DS3231_I2C_ADDRESS, amount ); // we request the given amount of bytes from the RTC
|
|
||||||
if( Wire.available() ){
|
|
||||||
received[amount]; // prepare the array for the amount of incoming bytes
|
|
||||||
for( int i = 0; i < amount; i++){
|
|
||||||
received[ i ] = Wire.read(); // we read the given amount of bytes
|
|
||||||
}
|
|
||||||
wireWorked = true; // everything went as planned
|
|
||||||
}
|
|
||||||
return wireWorked;
|
|
||||||
}
|
|
||||||
|
|
||||||
void setByte( byte addr, byte newByte ) // writes a given byte to a given address in the RTCs register. convenient
|
|
||||||
{
|
|
||||||
setBytes( addr, &newByte, 1); // call the setBytes function with the default amount = 1
|
|
||||||
}
|
|
||||||
|
|
||||||
void setBytes( byte addr, byte newBytes[], int amount ) // writes a given amount of bytes in a sequence starting from a given address
|
|
||||||
{
|
|
||||||
Wire.beginTransmission( DS3231_I2C_ADDRESS ); // We transmit to the RTC
|
|
||||||
Wire.write( addr ); // We want to start writing from the given address
|
|
||||||
for( int i = 0; i < amount; i++ )
|
|
||||||
Wire.write( newBytes[ i ] ); // we write each byte in sequence
|
|
||||||
Wire.endTransmission(); // we're done here
|
|
||||||
}
|
|
||||||
|
|
||||||
void getTime() // reads the current time from the register and updates the byte array containing the current time
|
|
||||||
{
|
|
||||||
if( getBytes( DS3231_TIME_CAL_ADDR, 7) ) // if 7 bytes were read in from the time address:
|
|
||||||
{
|
|
||||||
for(int i = 0; i < 7; i++) // place each byte in it's place
|
|
||||||
time[ i ] = received[ i ];
|
|
||||||
// The following conversions convert the values from binary-coded decimal format to regular binary:
|
|
||||||
time[ 0 ] = ( ( time[ 0 ] & B01110000 ) >> 4 ) * 10 + ( time[ 0 ] & B00001111 ); // second
|
|
||||||
time[ 1 ] = ( ( time[ 1 ] & B01110000 ) >> 4 ) * 10 + ( time[ 1 ] & B00001111 ); // minute
|
|
||||||
time[ 2 ] = ( ( time[ 2 ] & B00110000 ) >> 4 ) * 10 + ( time[ 2 ] & B00001111 ); // hour
|
|
||||||
time[ 4 ] = ( ( time[ 4 ] & B00110000 ) >> 4 ) * 10 + ( time[ 4 ] & B00001111 ); // day of month
|
|
||||||
time[ 5 ] = ( ( time[ 5 ] & B00010000 ) >> 4 ) * 10 + ( time[ 5 ] & B00001111 ); // month
|
|
||||||
time[ 6 ] = ( ( time[ 6 ] & B11110000 ) >> 4 ) * 10 + ( time[ 6 ] & B00001111 ); // year
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void setTime( byte newTime[ 7 ] ) // sets the time in the RTC register to the given values
|
|
||||||
{
|
|
||||||
for(int i = 0; i < 7; i++)
|
|
||||||
newTime[i] = decToBcd(newTime[i]); // the time consists of 7 bytes, each which must be converted to binary-coded decimal
|
|
||||||
setBytes( DS3231_TIME_CAL_ADDR, newTime, 7 ); // bytes are sent to be written
|
|
||||||
}
|
|
||||||
|
|
||||||
void getRTCTemperature() // reads the temperature from the register and updates the global temperature float
|
|
||||||
{
|
|
||||||
//temp registers (11h-12h) get updated automatically every 64s
|
|
||||||
if( getBytes( DS3231_TEMPERATURE_ADDR, 2 ) ) // if 2 bytes were read from the temperature addresss
|
|
||||||
{
|
|
||||||
temperature = ( received[ 0 ] & B01111111 ); // assign the integer part of the integer
|
|
||||||
temperature += ( ( received[ 1 ] >> 6 ) * 0.25 ); // assign the fractional part of the temperature
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void gprsListen()
|
|
||||||
{
|
|
||||||
if( GPRS.available() ) { // If the GPRS Shield is transmitting data to the Stalker...
|
|
||||||
while( GPRS.available() ) { // While there is still data left...
|
|
||||||
buffer[ count++ ] = GPRS.read(); // get the next byte of data
|
|
||||||
if ( count == 64 ) // we only handle a maximum of 64 bytes of data at a time
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
Serial.write( buffer, count ); // Send the data to the serial line
|
|
||||||
analise( buffer, count );
|
|
||||||
clearBufferArray(); // clear the buffer
|
|
||||||
count = 0; // reset counter
|
|
||||||
}
|
|
||||||
if (Serial.available()) // if the Stalker is transmitting data....
|
|
||||||
GPRS.write(Serial.read()); // send the data to the GPRS Shield.
|
|
||||||
}
|
|
||||||
|
|
||||||
void printTime() // updates time, and prints it in a convenient format
|
|
||||||
{
|
|
||||||
getTime();
|
|
||||||
Serial.print( int( time[ 3 ] ) ); // dow
|
|
||||||
Serial.print( ' ' );
|
|
||||||
Serial.print( int( time[ 2 ] ) ); // hour
|
|
||||||
Serial.print( ':' );
|
|
||||||
Serial.print( int( time[ 1 ] ) ); // minute
|
|
||||||
Serial.print( ':' );
|
|
||||||
Serial.print( int( time[ 0 ] ) ); // second
|
|
||||||
Serial.print( ' ' );
|
|
||||||
Serial.print( int( time[ 4 ] ) ); // day
|
|
||||||
Serial.print( '/' );
|
|
||||||
Serial.print( int( time[ 5 ] ) ); // month
|
|
||||||
Serial.print( "/20" );
|
|
||||||
Serial.print( int( time[ 6 ] ) ); // year
|
|
||||||
Serial.println();
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
End of RTC code
|
|
||||||
*/
|
|
||||||
|
|
||||||
void setup()
|
|
||||||
{
|
|
||||||
// GPRS Shield startup code
|
|
||||||
GPRS.begin( 9600 );
|
|
||||||
delay(1000);
|
|
||||||
setPowerStateTo(1);
|
|
||||||
delay(1000);
|
|
||||||
|
|
||||||
// RTC Startup code
|
|
||||||
Wire.begin();
|
|
||||||
delay(1000);
|
|
||||||
|
|
||||||
Serial.begin(9600);
|
|
||||||
delay(1000);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
void loop()
|
|
||||||
{
|
|
||||||
gprsListen(); // GPRS Shield listener. Todo: replace w interrupt
|
|
||||||
getTime(); // Updates the time. Todo: replace w interrupt
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -1,344 +0,0 @@
|
|||||||
|
|
||||||
#include <SoftwareSerial.h>
|
|
||||||
#include <Wire.h>
|
|
||||||
|
|
||||||
|
|
||||||
#define DS3231_I2C_ADDRESS 104
|
|
||||||
#define DS3231_TIME_CAL_ADDR 0
|
|
||||||
#define DS3231_ALARM1_ADDR 7
|
|
||||||
#define DS3231_ALARM2_ADDR 11
|
|
||||||
#define DS3231_CONTROL_ADDR 14
|
|
||||||
#define DS3231_STATUS_ADDR 15
|
|
||||||
|
|
||||||
#define DS3231_TEMPERATURE_ADDR 17
|
|
||||||
|
|
||||||
|
|
||||||
SoftwareSerial GPRS( 7, 8 );
|
|
||||||
byte buffer[ 64 ];
|
|
||||||
int count = 0, e = 0, count2 = 0, t = 0, q;
|
|
||||||
char temp, lastCaller[13] = "blank";
|
|
||||||
boolean callIncoming = false, done;
|
|
||||||
|
|
||||||
|
|
||||||
byte time[ 7 ];
|
|
||||||
byte time_A1[ 5 ];
|
|
||||||
byte time_A2[ 4 ];
|
|
||||||
byte received[1];
|
|
||||||
float temperature;
|
|
||||||
|
|
||||||
|
|
||||||
char telescopeNames[6][4];
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void setPowerStateTo( int newState )
|
|
||||||
{
|
|
||||||
if( newState != 1 && newState != 0 ) {
|
|
||||||
Serial.print( "Error: Invalid powerstate. Current powerstate = " );
|
|
||||||
Serial.print( getPowerState() );
|
|
||||||
Serial.print( "\n" );
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
if( newState == getPowerState() ) {
|
|
||||||
Serial.print( "Powerstate = " );
|
|
||||||
Serial.print( newState );
|
|
||||||
Serial.print( " remains unchanged.\n" );
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
powerUpOrDown();
|
|
||||||
Serial.print( "Powerstate changed from " );
|
|
||||||
Serial.print( 1 - newState );
|
|
||||||
Serial.print( " to " );
|
|
||||||
Serial.print( newState );
|
|
||||||
Serial.print( "\n" );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
delay( 5000 );
|
|
||||||
}
|
|
||||||
|
|
||||||
int getPowerState()
|
|
||||||
{
|
|
||||||
int ret;
|
|
||||||
if ( digitalRead(18) == 0 && digitalRead(19) == 0 )
|
|
||||||
ret = 1;
|
|
||||||
else
|
|
||||||
ret = 0;
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
void powerUpOrDown()
|
|
||||||
{
|
|
||||||
pinMode( 9, OUTPUT );
|
|
||||||
digitalWrite( 9, LOW );
|
|
||||||
delay( 1000 );
|
|
||||||
digitalWrite( 9, HIGH );
|
|
||||||
delay( 2000 );
|
|
||||||
digitalWrite( 9, LOW );
|
|
||||||
delay( 3000 );
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void clearBufferArray()
|
|
||||||
{
|
|
||||||
for( int i = 0; i < count; i++ )
|
|
||||||
buffer[ i ] = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
void makeMissedCall( char num[] )
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
char in[ 18 ] = "ATD";
|
|
||||||
for( i = 3; i <= 14; i++ )
|
|
||||||
in[ i ] = num[ i - 3] ;
|
|
||||||
in[ 15 ] = ';';
|
|
||||||
in[ 16 ] = '\r';
|
|
||||||
in[ 17 ] = '\0';
|
|
||||||
GPRS.write( in );
|
|
||||||
delay( 10000 );
|
|
||||||
GPRS.write( "ATH\r\0" );
|
|
||||||
delay( 1000 );
|
|
||||||
}
|
|
||||||
|
|
||||||
void sendTextMessage( char number[], char messg[] )
|
|
||||||
{
|
|
||||||
char temp[ 27 ] = "AT + CMGS = \"";
|
|
||||||
for( q = 0; q < 12; q++ )
|
|
||||||
temp[ q + 13 ] = number[ q ];
|
|
||||||
temp[ 25 ] = '\"';
|
|
||||||
temp[ 26 ] = '\0';
|
|
||||||
|
|
||||||
GPRS.println( "AT+CMGF=1\r" );
|
|
||||||
delay( 1000 );
|
|
||||||
GPRS.println( temp );
|
|
||||||
delay( 1000 );
|
|
||||||
GPRS.println( messg );
|
|
||||||
delay( 1000 );
|
|
||||||
GPRS.println( (char) 26 );
|
|
||||||
delay( 1000 );
|
|
||||||
}
|
|
||||||
|
|
||||||
void analise(byte incoming[], int length)
|
|
||||||
{
|
|
||||||
e = 0;
|
|
||||||
done = false;
|
|
||||||
while( e < length && !done){
|
|
||||||
temp = char( incoming[e] );
|
|
||||||
switch( temp ){
|
|
||||||
case 'R':
|
|
||||||
{
|
|
||||||
if( length > e + 3 && !callIncoming ) {
|
|
||||||
if(char( incoming[e + 1] ) == 'I'
|
|
||||||
&& char( incoming[e + 2] ) == 'N'
|
|
||||||
&& char( incoming[e + 3] ) == 'G'){
|
|
||||||
GPRS.write("AT+CLCC\r");
|
|
||||||
delay(500);
|
|
||||||
GPRS.write("ATH\r");
|
|
||||||
callIncoming = true;
|
|
||||||
done = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case '+':
|
|
||||||
{
|
|
||||||
if(char( buffer[ e + 1]) == '2' && length > e + 11 && callIncoming){
|
|
||||||
for(t = 0; t < 12; t++)
|
|
||||||
lastCaller[t] = char( buffer[ e + t ]);
|
|
||||||
lastCaller[12] = '\0';
|
|
||||||
callIncoming = false;
|
|
||||||
done = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case 'l':
|
|
||||||
Serial.println(lastCaller);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
e++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
byte decToBcd( byte b )
|
|
||||||
{
|
|
||||||
return ( b / 10 << 4 ) + b % 10;
|
|
||||||
}
|
|
||||||
|
|
||||||
boolean getBit( byte addr, int pos )
|
|
||||||
{
|
|
||||||
byte temp = getByte( addr );
|
|
||||||
return boolean( (temp >> pos) & B00000001 );
|
|
||||||
}
|
|
||||||
|
|
||||||
void setBit( byte addr, int pos, boolean newBit )
|
|
||||||
{
|
|
||||||
boolean oldBit = getBit( addr, pos );
|
|
||||||
byte temp = received[ 0 ];
|
|
||||||
if ( oldBit != newBit )
|
|
||||||
{
|
|
||||||
if( newBit )
|
|
||||||
temp += (B00000001 << pos);
|
|
||||||
else
|
|
||||||
temp -= (B00000001 << pos);
|
|
||||||
}
|
|
||||||
setByte( addr, temp );
|
|
||||||
}
|
|
||||||
|
|
||||||
byte getByte( byte addr )
|
|
||||||
{
|
|
||||||
byte temp;
|
|
||||||
if( getBytes( addr, 1) )
|
|
||||||
temp = received[ 0 ];
|
|
||||||
else temp = -1;
|
|
||||||
return temp;
|
|
||||||
}
|
|
||||||
|
|
||||||
boolean getBytes( byte addr, int amount )
|
|
||||||
{
|
|
||||||
boolean wireWorked = false;
|
|
||||||
Wire.beginTransmission( DS3231_I2C_ADDRESS );
|
|
||||||
Wire.write( addr );
|
|
||||||
Wire.endTransmission();
|
|
||||||
Wire.requestFrom( DS3231_I2C_ADDRESS, amount );
|
|
||||||
if( Wire.available() ){
|
|
||||||
received[amount];
|
|
||||||
for( int i = 0; i < amount; i++){
|
|
||||||
received[ i ] = Wire.read();
|
|
||||||
}
|
|
||||||
wireWorked = true;
|
|
||||||
}
|
|
||||||
return wireWorked;
|
|
||||||
}
|
|
||||||
|
|
||||||
void setByte( byte addr, byte newByte )
|
|
||||||
{
|
|
||||||
setBytes( addr, &newByte, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
void setBytes( byte addr, byte newBytes[], int amount )
|
|
||||||
{
|
|
||||||
Wire.beginTransmission( DS3231_I2C_ADDRESS );
|
|
||||||
Wire.write( addr );
|
|
||||||
for( int i = 0; i < amount; i++ )
|
|
||||||
Wire.write( newBytes[ i ] );
|
|
||||||
Wire.endTransmission();
|
|
||||||
}
|
|
||||||
|
|
||||||
void getTime()
|
|
||||||
{
|
|
||||||
if( getBytes( DS3231_TIME_CAL_ADDR, 7) )
|
|
||||||
{
|
|
||||||
for(int i = 0; i < 7; i++)
|
|
||||||
time[ i ] = received[ i ];
|
|
||||||
|
|
||||||
time[ 0 ] = ( ( time[ 0 ] & B01110000 ) >> 4 ) * 10 + ( time[ 0 ] & B00001111 );
|
|
||||||
time[ 1 ] = ( ( time[ 1 ] & B01110000 ) >> 4 ) * 10 + ( time[ 1 ] & B00001111 );
|
|
||||||
time[ 2 ] = ( ( time[ 2 ] & B00110000 ) >> 4 ) * 10 + ( time[ 2 ] & B00001111 );
|
|
||||||
time[ 4 ] = ( ( time[ 4 ] & B00110000 ) >> 4 ) * 10 + ( time[ 4 ] & B00001111 );
|
|
||||||
time[ 5 ] = ( ( time[ 5 ] & B00010000 ) >> 4 ) * 10 + ( time[ 5 ] & B00001111 );
|
|
||||||
time[ 6 ] = ( ( time[ 6 ] & B11110000 ) >> 4 ) * 10 + ( time[ 6 ] & B00001111 );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void setTime( byte newTime[ 7 ] )
|
|
||||||
{
|
|
||||||
for(int i = 0; i < 7; i++)
|
|
||||||
newTime[i] = decToBcd(newTime[i]);
|
|
||||||
setBytes( DS3231_TIME_CAL_ADDR, newTime, 7 );
|
|
||||||
}
|
|
||||||
|
|
||||||
void getRTCTemperature()
|
|
||||||
{
|
|
||||||
|
|
||||||
if( getBytes( DS3231_TEMPERATURE_ADDR, 2 ) )
|
|
||||||
{
|
|
||||||
temperature = ( received[ 0 ] & B01111111 );
|
|
||||||
temperature += ( ( received[ 1 ] >> 6 ) * 0.25 );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void gprsListen()
|
|
||||||
{
|
|
||||||
if( GPRS.available() ) {
|
|
||||||
while( GPRS.available() ) {
|
|
||||||
buffer[ count++ ] = GPRS.read();
|
|
||||||
if ( count == 64 )
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
Serial.write( buffer, count );
|
|
||||||
analise( buffer, count );
|
|
||||||
clearBufferArray();
|
|
||||||
count = 0;
|
|
||||||
}
|
|
||||||
if (Serial.available())
|
|
||||||
GPRS.write(Serial.read());
|
|
||||||
}
|
|
||||||
|
|
||||||
void printTime()
|
|
||||||
{
|
|
||||||
getTime();
|
|
||||||
Serial.print( int( time[ 3 ] ) );
|
|
||||||
Serial.print( ' ' );
|
|
||||||
Serial.print( int( time[ 2 ] ) );
|
|
||||||
Serial.print( ':' );
|
|
||||||
Serial.print( int( time[ 1 ] ) );
|
|
||||||
Serial.print( ':' );
|
|
||||||
Serial.print( int( time[ 0 ] ) );
|
|
||||||
Serial.print( ' ' );
|
|
||||||
Serial.print( int( time[ 4 ] ) );
|
|
||||||
Serial.print( '/' );
|
|
||||||
Serial.print( int( time[ 5 ] ) );
|
|
||||||
Serial.print( "/20" );
|
|
||||||
Serial.print( int( time[ 6 ] ) );
|
|
||||||
Serial.println();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void setup()
|
|
||||||
{
|
|
||||||
|
|
||||||
GPRS.begin( 9600 );
|
|
||||||
delay(1000);
|
|
||||||
setPowerStateTo(1);
|
|
||||||
delay(1000);
|
|
||||||
|
|
||||||
|
|
||||||
Wire.begin();
|
|
||||||
delay(1000);
|
|
||||||
|
|
||||||
Serial.begin(9600);
|
|
||||||
delay(1000);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
void loop()
|
|
||||||
{
|
|
||||||
gprsListen();
|
|
||||||
getTime();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -1,343 +0,0 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
SoftwareSerial GPRS( 7, 8 );
|
|
||||||
byte buffer[ 64 ];
|
|
||||||
int count = 0, e = 0, count2 = 0, t = 0, q;
|
|
||||||
char temp, lastCaller[13] = ;
|
|
||||||
boolean callIncoming = false, done;
|
|
||||||
|
|
||||||
|
|
||||||
byte time[ 7 ];
|
|
||||||
byte time_A1[ 5 ];
|
|
||||||
byte time_A2[ 4 ];
|
|
||||||
byte received[1];
|
|
||||||
float temperature;
|
|
||||||
|
|
||||||
|
|
||||||
char telescopeNames[6][4];
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void setPowerStateTo( int newState )
|
|
||||||
{
|
|
||||||
if( newState != 1 && newState != 0 ) {
|
|
||||||
Serial.print( );
|
|
||||||
Serial.print( getPowerState() );
|
|
||||||
Serial.print( );
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
if( newState == getPowerState() ) {
|
|
||||||
Serial.print( );
|
|
||||||
Serial.print( newState );
|
|
||||||
Serial.print( );
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
powerUpOrDown();
|
|
||||||
Serial.print( );
|
|
||||||
Serial.print( 1 - newState );
|
|
||||||
Serial.print( );
|
|
||||||
Serial.print( newState );
|
|
||||||
Serial.print( );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
delay( 5000 );
|
|
||||||
}
|
|
||||||
|
|
||||||
int getPowerState()
|
|
||||||
{
|
|
||||||
int ret;
|
|
||||||
if ( digitalRead(18) == 0 && digitalRead(19) == 0 )
|
|
||||||
ret = 1;
|
|
||||||
else
|
|
||||||
ret = 0;
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
void powerUpOrDown()
|
|
||||||
{
|
|
||||||
pinMode( 9, OUTPUT );
|
|
||||||
digitalWrite( 9, LOW );
|
|
||||||
delay( 1000 );
|
|
||||||
digitalWrite( 9, HIGH );
|
|
||||||
delay( 2000 );
|
|
||||||
digitalWrite( 9, LOW );
|
|
||||||
delay( 3000 );
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void clearBufferArray()
|
|
||||||
{
|
|
||||||
for( int i = 0; i < count; i++ )
|
|
||||||
buffer[ i ] = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
void makeMissedCall( char num[] )
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
char in[ 18 ] = ;
|
|
||||||
for( i = 3; i <= 14; i++ )
|
|
||||||
in[ i ] = num[ i - 3] ;
|
|
||||||
in[ 15 ] = ;
|
|
||||||
in[ 16 ] = '\r';
|
|
||||||
in[ 17 ] = '\0';
|
|
||||||
GPRS.write( in );
|
|
||||||
delay( 10000 );
|
|
||||||
GPRS.write( );
|
|
||||||
delay( 1000 );
|
|
||||||
}
|
|
||||||
|
|
||||||
void sendTextMessage( char number[], char messg[] )
|
|
||||||
{
|
|
||||||
char temp[ 27 ] = ;
|
|
||||||
for( q = 0; q < 12; q++ )
|
|
||||||
temp[ q + 13 ] = number[ q ];
|
|
||||||
temp[ 25 ] = ;
|
|
||||||
temp[ 26 ] = '\0';
|
|
||||||
|
|
||||||
GPRS.println( );
|
|
||||||
delay( 1000 );
|
|
||||||
GPRS.println( temp );
|
|
||||||
delay( 1000 );
|
|
||||||
GPRS.println( messg );
|
|
||||||
delay( 1000 );
|
|
||||||
GPRS.println( (char) 26 );
|
|
||||||
delay( 1000 );
|
|
||||||
}
|
|
||||||
|
|
||||||
void analise(byte incoming[], int length)
|
|
||||||
{
|
|
||||||
e = 0;
|
|
||||||
done = false;
|
|
||||||
while( e < length && !done){
|
|
||||||
temp = char( incoming[e] );
|
|
||||||
switch( temp ){
|
|
||||||
case :
|
|
||||||
{
|
|
||||||
if( length > e + 3 && !callIncoming ) {
|
|
||||||
if(char( incoming[e + 1] ) ==
|
|
||||||
&& char( incoming[e + 2] ) ==
|
|
||||||
&& char( incoming[e + 3] ) == ){
|
|
||||||
GPRS.write( );
|
|
||||||
delay(500);
|
|
||||||
GPRS.write( );
|
|
||||||
callIncoming = true;
|
|
||||||
done = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case :
|
|
||||||
{
|
|
||||||
if(char( buffer[ e + 1]) == && length > e + 11 && callIncoming){
|
|
||||||
for(t = 0; t < 12; t++)
|
|
||||||
lastCaller[t] = char( buffer[ e + t ]);
|
|
||||||
lastCaller[12] = '\0';
|
|
||||||
callIncoming = false;
|
|
||||||
done = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case :
|
|
||||||
Serial.println(lastCaller);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
e++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
byte decToBcd( byte b )
|
|
||||||
{
|
|
||||||
return ( b / 10 << 4 ) + b % 10;
|
|
||||||
}
|
|
||||||
|
|
||||||
boolean getBit( byte addr, int pos )
|
|
||||||
{
|
|
||||||
byte temp = getByte( addr );
|
|
||||||
return boolean( (temp >> pos) & B00000001 );
|
|
||||||
}
|
|
||||||
|
|
||||||
void setBit( byte addr, int pos, boolean newBit )
|
|
||||||
{
|
|
||||||
boolean oldBit = getBit( addr, pos );
|
|
||||||
byte temp = received[ 0 ];
|
|
||||||
if ( oldBit != newBit )
|
|
||||||
{
|
|
||||||
if( newBit )
|
|
||||||
temp += (B00000001 << pos);
|
|
||||||
else
|
|
||||||
temp -= (B00000001 << pos);
|
|
||||||
}
|
|
||||||
setByte( addr, temp );
|
|
||||||
}
|
|
||||||
|
|
||||||
byte getByte( byte addr )
|
|
||||||
{
|
|
||||||
byte temp;
|
|
||||||
if( getBytes( addr, 1) )
|
|
||||||
temp = received[ 0 ];
|
|
||||||
else temp = -1;
|
|
||||||
return temp;
|
|
||||||
}
|
|
||||||
|
|
||||||
boolean getBytes( byte addr, int amount )
|
|
||||||
{
|
|
||||||
boolean wireWorked = false;
|
|
||||||
Wire.beginTransmission( DS3231_I2C_ADDRESS );
|
|
||||||
Wire.write( addr );
|
|
||||||
Wire.endTransmission();
|
|
||||||
Wire.requestFrom( DS3231_I2C_ADDRESS, amount );
|
|
||||||
if( Wire.available() ){
|
|
||||||
received[amount];
|
|
||||||
for( int i = 0; i < amount; i++){
|
|
||||||
received[ i ] = Wire.read();
|
|
||||||
}
|
|
||||||
wireWorked = true;
|
|
||||||
}
|
|
||||||
return wireWorked;
|
|
||||||
}
|
|
||||||
|
|
||||||
void setByte( byte addr, byte newByte )
|
|
||||||
{
|
|
||||||
setBytes( addr, &newByte, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
void setBytes( byte addr, byte newBytes[], int amount )
|
|
||||||
{
|
|
||||||
Wire.beginTransmission( DS3231_I2C_ADDRESS );
|
|
||||||
Wire.write( addr );
|
|
||||||
for( int i = 0; i < amount; i++ )
|
|
||||||
Wire.write( newBytes[ i ] );
|
|
||||||
Wire.endTransmission();
|
|
||||||
}
|
|
||||||
|
|
||||||
void getTime()
|
|
||||||
{
|
|
||||||
if( getBytes( DS3231_TIME_CAL_ADDR, 7) )
|
|
||||||
{
|
|
||||||
for(int i = 0; i < 7; i++)
|
|
||||||
time[ i ] = received[ i ];
|
|
||||||
|
|
||||||
time[ 0 ] = ( ( time[ 0 ] & B01110000 ) >> 4 ) * 10 + ( time[ 0 ] & B00001111 );
|
|
||||||
time[ 1 ] = ( ( time[ 1 ] & B01110000 ) >> 4 ) * 10 + ( time[ 1 ] & B00001111 );
|
|
||||||
time[ 2 ] = ( ( time[ 2 ] & B00110000 ) >> 4 ) * 10 + ( time[ 2 ] & B00001111 );
|
|
||||||
time[ 4 ] = ( ( time[ 4 ] & B00110000 ) >> 4 ) * 10 + ( time[ 4 ] & B00001111 );
|
|
||||||
time[ 5 ] = ( ( time[ 5 ] & B00010000 ) >> 4 ) * 10 + ( time[ 5 ] & B00001111 );
|
|
||||||
time[ 6 ] = ( ( time[ 6 ] & B11110000 ) >> 4 ) * 10 + ( time[ 6 ] & B00001111 );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void setTime( byte newTime[ 7 ] )
|
|
||||||
{
|
|
||||||
for(int i = 0; i < 7; i++)
|
|
||||||
newTime[i] = decToBcd(newTime[i]);
|
|
||||||
setBytes( DS3231_TIME_CAL_ADDR, newTime, 7 );
|
|
||||||
}
|
|
||||||
|
|
||||||
void getRTCTemperature()
|
|
||||||
{
|
|
||||||
|
|
||||||
if( getBytes( DS3231_TEMPERATURE_ADDR, 2 ) )
|
|
||||||
{
|
|
||||||
temperature = ( received[ 0 ] & B01111111 );
|
|
||||||
temperature += ( ( received[ 1 ] >> 6 ) * 0.25 );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void gprsListen()
|
|
||||||
{
|
|
||||||
if( GPRS.available() ) {
|
|
||||||
while( GPRS.available() ) {
|
|
||||||
buffer[ count++ ] = GPRS.read();
|
|
||||||
if ( count == 64 )
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
Serial.write( buffer, count );
|
|
||||||
analise( buffer, count );
|
|
||||||
clearBufferArray();
|
|
||||||
count = 0;
|
|
||||||
}
|
|
||||||
if (Serial.available())
|
|
||||||
GPRS.write(Serial.read());
|
|
||||||
}
|
|
||||||
|
|
||||||
void printTime()
|
|
||||||
{
|
|
||||||
getTime();
|
|
||||||
Serial.print( int( time[ 3 ] ) );
|
|
||||||
Serial.print( );
|
|
||||||
Serial.print( int( time[ 2 ] ) );
|
|
||||||
Serial.print( );
|
|
||||||
Serial.print( int( time[ 1 ] ) );
|
|
||||||
Serial.print( );
|
|
||||||
Serial.print( int( time[ 0 ] ) );
|
|
||||||
Serial.print( );
|
|
||||||
Serial.print( int( time[ 4 ] ) );
|
|
||||||
Serial.print( );
|
|
||||||
Serial.print( int( time[ 5 ] ) );
|
|
||||||
Serial.print( );
|
|
||||||
Serial.print( int( time[ 6 ] ) );
|
|
||||||
Serial.println();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void setup()
|
|
||||||
{
|
|
||||||
|
|
||||||
GPRS.begin( 9600 );
|
|
||||||
delay(1000);
|
|
||||||
setPowerStateTo(1);
|
|
||||||
delay(1000);
|
|
||||||
|
|
||||||
|
|
||||||
Wire.begin();
|
|
||||||
delay(1000);
|
|
||||||
|
|
||||||
Serial.begin(9600);
|
|
||||||
delay(1000);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
void loop()
|
|
||||||
{
|
|
||||||
gprsListen();
|
|
||||||
getTime();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -1,13 +0,0 @@
|
|||||||
void setup() {
|
|
||||||
// put your setup code here, to run once:
|
|
||||||
// "comment with a double quote
|
|
||||||
/* \" other comment with double quote */
|
|
||||||
Serial.println("Accept: */*");
|
|
||||||
Serial.println("Accept: \" */*");
|
|
||||||
Serial.println("Accept: \\"); // */*");
|
|
||||||
}
|
|
||||||
|
|
||||||
void loop() {
|
|
||||||
// put your main code here, to run repeatedly:
|
|
||||||
|
|
||||||
}
|
|
@ -1,14 +0,0 @@
|
|||||||
void setup() {
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Serial.println("Accept: */*");
|
|
||||||
Serial.println("Accept: \" */*");
|
|
||||||
Serial.println("Accept: \\"); // */*");
|
|
||||||
}
|
|
||||||
|
|
||||||
void loop() {
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -1,13 +0,0 @@
|
|||||||
void setup() {
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Serial.println( );
|
|
||||||
Serial.println( );
|
|
||||||
Serial.println( );
|
|
||||||
}
|
|
||||||
|
|
||||||
void loop() {
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
@ -29,7 +29,6 @@
|
|||||||
|
|
||||||
package cc.arduino.packages.uploaders;
|
package cc.arduino.packages.uploaders;
|
||||||
|
|
||||||
import cc.arduino.Compiler;
|
|
||||||
import cc.arduino.CompilerUtils;
|
import cc.arduino.CompilerUtils;
|
||||||
import cc.arduino.packages.BoardPort;
|
import cc.arduino.packages.BoardPort;
|
||||||
import cc.arduino.packages.Uploader;
|
import cc.arduino.packages.Uploader;
|
||||||
|
@ -25,7 +25,6 @@ package processing.app;
|
|||||||
import processing.app.helpers.FileUtils;
|
import processing.app.helpers.FileUtils;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.FileFilter;
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
@ -1,1529 +0,0 @@
|
|||||||
/* -*- mode: java; c-basic-offset: 2; indent-tabs-mode: nil -*- */
|
|
||||||
|
|
||||||
/*
|
|
||||||
Part of the Processing project - http://processing.org
|
|
||||||
|
|
||||||
Copyright (c) 2004-08 Ben Fry and Casey Reas
|
|
||||||
Copyright (c) 2001-04 Massachusetts Institute of Technology
|
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
|
||||||
it under the terms of the GNU General Public License as published by
|
|
||||||
the Free Software Foundation; either version 2 of the License, or
|
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
|
||||||
along with this program; if not, write to the Free Software Foundation,
|
|
||||||
Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
||||||
*/
|
|
||||||
|
|
||||||
package processing.app.debug;
|
|
||||||
|
|
||||||
import cc.arduino.Constants;
|
|
||||||
import cc.arduino.LoadVIDPIDSpecificPreferences;
|
|
||||||
import cc.arduino.MyStreamPumper;
|
|
||||||
import cc.arduino.contributions.packages.ContributedPlatform;
|
|
||||||
import cc.arduino.contributions.packages.ContributedTool;
|
|
||||||
import cc.arduino.packages.BoardPort;
|
|
||||||
import cc.arduino.packages.Uploader;
|
|
||||||
import cc.arduino.packages.UploaderFactory;
|
|
||||||
import cc.arduino.packages.uploaders.MergeSketchWithBooloader;
|
|
||||||
import cc.arduino.utils.Pair;
|
|
||||||
import org.apache.commons.compress.utils.IOUtils;
|
|
||||||
import org.apache.commons.exec.CommandLine;
|
|
||||||
import org.apache.commons.exec.DefaultExecutor;
|
|
||||||
import org.apache.commons.exec.PumpStreamHandler;
|
|
||||||
import processing.app.*;
|
|
||||||
import processing.app.helpers.FileUtils;
|
|
||||||
import processing.app.helpers.PreferencesMap;
|
|
||||||
import processing.app.helpers.PreferencesMapException;
|
|
||||||
import processing.app.helpers.StringReplacer;
|
|
||||||
import processing.app.helpers.filefilters.OnlyDirs;
|
|
||||||
import processing.app.legacy.PApplet;
|
|
||||||
import processing.app.packages.LegacyUserLibrary;
|
|
||||||
import processing.app.packages.LibraryList;
|
|
||||||
import processing.app.packages.UserLibrary;
|
|
||||||
import processing.app.preproc.PdePreprocessor;
|
|
||||||
import processing.app.tools.DoubleQuotedArgumentsOnWindowsCommandLine;
|
|
||||||
|
|
||||||
import java.io.*;
|
|
||||||
import java.nio.file.Files;
|
|
||||||
import java.nio.file.Path;
|
|
||||||
import java.nio.file.Paths;
|
|
||||||
import java.nio.file.StandardCopyOption;
|
|
||||||
import java.util.*;
|
|
||||||
import java.util.stream.Collectors;
|
|
||||||
import java.util.stream.Stream;
|
|
||||||
|
|
||||||
import static processing.app.I18n.tr;
|
|
||||||
|
|
||||||
@Deprecated
|
|
||||||
public class OldCompiler implements MessageConsumer {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* File inside the build directory that contains the build options
|
|
||||||
* used for the last build.
|
|
||||||
*/
|
|
||||||
static final public String BUILD_PREFS_FILE = "buildprefs.txt";
|
|
||||||
private static final int ADDITIONAL_FILES_COPY_MAX_DEPTH = 5;
|
|
||||||
|
|
||||||
private SketchData sketch;
|
|
||||||
private PreferencesMap prefs;
|
|
||||||
private boolean verbose;
|
|
||||||
private boolean saveHex;
|
|
||||||
|
|
||||||
private List<File> objectFiles;
|
|
||||||
|
|
||||||
private boolean sketchIsCompiled;
|
|
||||||
|
|
||||||
private RunnerException exception;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Listener interface for progress update on the GUI
|
|
||||||
*/
|
|
||||||
public interface ProgressListener {
|
|
||||||
void progress(int percent);
|
|
||||||
}
|
|
||||||
|
|
||||||
private ProgressListener progressListener;
|
|
||||||
|
|
||||||
static public String build(SketchData data, String buildPath, File tempBuildFolder, ProgressListener progListener, boolean verbose, boolean save) throws RunnerException, PreferencesMapException {
|
|
||||||
if (SketchData.checkSketchFile(data.getPrimaryFile()) == null)
|
|
||||||
BaseNoGui.showError(tr("Bad file selected"),
|
|
||||||
tr("Bad sketch primary file or bad sketch directory structure"), null);
|
|
||||||
|
|
||||||
String primaryClassName = data.getName() + ".cpp";
|
|
||||||
OldCompiler compiler = new OldCompiler(data, buildPath, primaryClassName);
|
|
||||||
File buildPrefsFile = new File(buildPath, BUILD_PREFS_FILE);
|
|
||||||
String newBuildPrefs = compiler.buildPrefsString();
|
|
||||||
|
|
||||||
// Do a forced cleanup (throw everything away) if the previous
|
|
||||||
// build settings do not match the previous ones
|
|
||||||
boolean prefsChanged = compiler.buildPreferencesChanged(buildPrefsFile, newBuildPrefs);
|
|
||||||
compiler.cleanup(prefsChanged, tempBuildFolder);
|
|
||||||
|
|
||||||
if (prefsChanged) {
|
|
||||||
PrintWriter out = null;
|
|
||||||
try {
|
|
||||||
out = new PrintWriter(buildPrefsFile);
|
|
||||||
out.print(newBuildPrefs);
|
|
||||||
} catch (IOException e) {
|
|
||||||
System.err.println(tr("Could not write build preferences file"));
|
|
||||||
} finally {
|
|
||||||
IOUtils.closeQuietly(out);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
compiler.setProgressListener(progListener);
|
|
||||||
|
|
||||||
// compile the program. errors will happen as a RunnerException
|
|
||||||
// that will bubble up to whomever called build().
|
|
||||||
try {
|
|
||||||
if (compiler.compile(verbose, save)) {
|
|
||||||
compiler.size(compiler.getBuildPreferences());
|
|
||||||
return primaryClassName;
|
|
||||||
}
|
|
||||||
} catch (RunnerException e) {
|
|
||||||
// when the compile fails, take this opportunity to show
|
|
||||||
// any helpful info possible before throwing the exception
|
|
||||||
compiler.adviseDuplicateLibraries();
|
|
||||||
throw e;
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
static public Uploader getUploaderByPreferences(boolean noUploadPort) {
|
|
||||||
TargetPlatform target = BaseNoGui.getTargetPlatform();
|
|
||||||
String board = PreferencesData.get("board");
|
|
||||||
|
|
||||||
BoardPort boardPort = null;
|
|
||||||
if (!noUploadPort) {
|
|
||||||
boardPort = BaseNoGui.getDiscoveryManager().find(PreferencesData.get("serial.port"));
|
|
||||||
}
|
|
||||||
|
|
||||||
return new UploaderFactory().newUploader(target.getBoards().get(board), boardPort, noUploadPort);
|
|
||||||
}
|
|
||||||
|
|
||||||
static public boolean upload(SketchData data, Uploader uploader, String buildPath, String suggestedClassName, boolean usingProgrammer, boolean noUploadPort, List<String> warningsAccumulator) throws Exception {
|
|
||||||
|
|
||||||
if (uploader == null)
|
|
||||||
uploader = getUploaderByPreferences(noUploadPort);
|
|
||||||
|
|
||||||
boolean success = false;
|
|
||||||
|
|
||||||
if (uploader.requiresAuthorization() && !PreferencesData.has(uploader.getAuthorizationKey())) {
|
|
||||||
BaseNoGui.showError(tr("Authorization required"),
|
|
||||||
tr("No authorization data found"), null);
|
|
||||||
}
|
|
||||||
|
|
||||||
boolean useNewWarningsAccumulator = false;
|
|
||||||
if (warningsAccumulator == null) {
|
|
||||||
warningsAccumulator = new LinkedList<String>();
|
|
||||||
useNewWarningsAccumulator = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
success = uploader.uploadUsingPreferences(data.getFolder(), buildPath, suggestedClassName, usingProgrammer, warningsAccumulator);
|
|
||||||
} finally {
|
|
||||||
if (uploader.requiresAuthorization() && !success) {
|
|
||||||
PreferencesData.remove(uploader.getAuthorizationKey());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (useNewWarningsAccumulator) {
|
|
||||||
for (String warning : warningsAccumulator) {
|
|
||||||
System.out.print(tr("Warning"));
|
|
||||||
System.out.print(": ");
|
|
||||||
System.out.println(warning);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return success;
|
|
||||||
}
|
|
||||||
|
|
||||||
static public File findCompiledSketch(PreferencesMap prefs) throws PreferencesMapException {
|
|
||||||
List<String> paths = Arrays.asList(
|
|
||||||
"{build.path}/sketch/{build.project_name}.with_bootloader.hex",
|
|
||||||
"{build.path}/sketch/{build.project_name}.hex",
|
|
||||||
"{build.path}/{build.project_name}.with_bootloader.hex",
|
|
||||||
"{build.path}/{build.project_name}.hex",
|
|
||||||
"{build.path}/sketch/{build.project_name}.bin",
|
|
||||||
"{build.path}/{build.project_name}.bin"
|
|
||||||
);
|
|
||||||
Optional<File> sketch = paths.stream().
|
|
||||||
map(path -> StringReplacer.replaceFromMapping(path, prefs)).
|
|
||||||
map(File::new).
|
|
||||||
filter(File::exists).
|
|
||||||
findFirst();
|
|
||||||
return sketch.orElseThrow(() -> new IllegalStateException(tr("No compiled sketch found")));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create a new Compiler
|
|
||||||
* @param _sketch Sketch object to be compiled.
|
|
||||||
* @param _buildPath Where the temporary files live and will be built from.
|
|
||||||
* @param _primaryClassName the name of the combined sketch file w/ extension
|
|
||||||
*/
|
|
||||||
public OldCompiler(SketchData _sketch, String _buildPath, String _primaryClassName)
|
|
||||||
throws RunnerException {
|
|
||||||
sketch = _sketch;
|
|
||||||
prefs = createBuildPreferences(_buildPath, _primaryClassName);
|
|
||||||
|
|
||||||
// provide access to the source tree
|
|
||||||
prefs.put("build.source.path", _sketch.getFolder().getAbsolutePath());
|
|
||||||
|
|
||||||
// Start with an empty progress listener
|
|
||||||
progressListener = new ProgressListener() {
|
|
||||||
@Override
|
|
||||||
public void progress(int percent) {
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Check if the build preferences used on the previous build in
|
|
||||||
* buildPath match the ones given.
|
|
||||||
*/
|
|
||||||
protected boolean buildPreferencesChanged(File buildPrefsFile, String newBuildPrefs) {
|
|
||||||
// No previous build, so no match
|
|
||||||
if (!buildPrefsFile.exists())
|
|
||||||
return true;
|
|
||||||
|
|
||||||
String previousPrefs;
|
|
||||||
try {
|
|
||||||
previousPrefs = FileUtils.readFileToString(buildPrefsFile);
|
|
||||||
} catch (IOException e) {
|
|
||||||
System.err.println(tr("Could not read prevous build preferences file, rebuilding all"));
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!previousPrefs.equals(newBuildPrefs)) {
|
|
||||||
System.out.println(tr("Build options changed, rebuilding all"));
|
|
||||||
return true;
|
|
||||||
} else {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the build preferences of the given compiler as a string.
|
|
||||||
* Only includes build-specific preferences, to make sure unrelated
|
|
||||||
* preferences don't cause a rebuild (in particular preferences that
|
|
||||||
* change on every start, like last.ide.xxx.daterun). */
|
|
||||||
protected String buildPrefsString() {
|
|
||||||
PreferencesMap buildPrefs = getBuildPreferences();
|
|
||||||
String res = "";
|
|
||||||
SortedSet<String> treeSet = new TreeSet<String>(buildPrefs.keySet());
|
|
||||||
for (String k : treeSet) {
|
|
||||||
if (k.startsWith("build.") || k.startsWith("compiler.") || k.startsWith("recipes."))
|
|
||||||
res += k + " = " + buildPrefs.get(k) + "\n";
|
|
||||||
}
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void setProgressListener(ProgressListener _progressListener) {
|
|
||||||
progressListener = (_progressListener == null ?
|
|
||||||
new ProgressListener() {
|
|
||||||
@Override
|
|
||||||
public void progress(int percent) {
|
|
||||||
}
|
|
||||||
} : _progressListener);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Cleanup temporary files used during a build/run.
|
|
||||||
*/
|
|
||||||
protected void cleanup(boolean force, File tempBuildFolder) {
|
|
||||||
// if the java runtime is holding onto any files in the build dir, we
|
|
||||||
// won't be able to delete them, so we need to force a gc here
|
|
||||||
System.gc();
|
|
||||||
|
|
||||||
if (force) {
|
|
||||||
// delete the entire directory and all contents
|
|
||||||
// when we know something changed and all objects
|
|
||||||
// need to be recompiled, or if the board does not
|
|
||||||
// use setting build.dependency
|
|
||||||
//Base.removeDir(tempBuildFolder);
|
|
||||||
|
|
||||||
// note that we can't remove the builddir itself, otherwise
|
|
||||||
// the next time we start up, internal runs using Runner won't
|
|
||||||
// work because the build dir won't exist at startup, so the classloader
|
|
||||||
// will ignore the fact that that dir is in the CLASSPATH in run.sh
|
|
||||||
BaseNoGui.removeDescendants(tempBuildFolder);
|
|
||||||
} else {
|
|
||||||
// delete only stale source files, from the previously
|
|
||||||
// compiled sketch. This allows multiple windows to be
|
|
||||||
// used. Keep everything else, which might be reusable
|
|
||||||
if (tempBuildFolder.exists()) {
|
|
||||||
String files[] = tempBuildFolder.list();
|
|
||||||
if (files != null) {
|
|
||||||
for (String file : files) {
|
|
||||||
if (file.endsWith(".c") || file.endsWith(".cpp") || file.endsWith(".s")) {
|
|
||||||
File deleteMe = new File(tempBuildFolder, file);
|
|
||||||
if (!deleteMe.delete()) {
|
|
||||||
System.err.println("Could not delete " + deleteMe);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create a fresh applet folder (needed before preproc is run below)
|
|
||||||
//tempBuildFolder.mkdirs();
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void size(PreferencesMap prefs) throws RunnerException {
|
|
||||||
String maxTextSizeString = prefs.get("upload.maximum_size");
|
|
||||||
String maxDataSizeString = prefs.get("upload.maximum_data_size");
|
|
||||||
if (maxTextSizeString == null)
|
|
||||||
return;
|
|
||||||
long maxTextSize = Integer.parseInt(maxTextSizeString);
|
|
||||||
long maxDataSize = -1;
|
|
||||||
if (maxDataSizeString != null)
|
|
||||||
maxDataSize = Integer.parseInt(maxDataSizeString);
|
|
||||||
Sizer sizer = new Sizer(prefs);
|
|
||||||
long[] sizes;
|
|
||||||
try {
|
|
||||||
sizes = sizer.computeSize();
|
|
||||||
} catch (RunnerException e) {
|
|
||||||
System.err.println(I18n.format(tr("Couldn't determine program size: {0}"),
|
|
||||||
e.getMessage()));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
long textSize = sizes[0];
|
|
||||||
long dataSize = sizes[1];
|
|
||||||
System.out.println();
|
|
||||||
System.out.println(I18n
|
|
||||||
.format(tr("Sketch uses {0} bytes ({2}%%) of program storage space. Maximum is {1} bytes."),
|
|
||||||
textSize, maxTextSize, textSize * 100 / maxTextSize));
|
|
||||||
if (dataSize >= 0) {
|
|
||||||
if (maxDataSize > 0) {
|
|
||||||
System.out
|
|
||||||
.println(I18n
|
|
||||||
.format(
|
|
||||||
tr("Global variables use {0} bytes ({2}%%) of dynamic memory, leaving {3} bytes for local variables. Maximum is {1} bytes."),
|
|
||||||
dataSize, maxDataSize, dataSize * 100 / maxDataSize,
|
|
||||||
maxDataSize - dataSize));
|
|
||||||
} else {
|
|
||||||
System.out.println(I18n
|
|
||||||
.format(tr("Global variables use {0} bytes of dynamic memory."), dataSize));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (textSize > maxTextSize)
|
|
||||||
throw new RunnerException(
|
|
||||||
tr("Sketch too big; see http://www.arduino.cc/en/Guide/Troubleshooting#size for tips on reducing it."));
|
|
||||||
|
|
||||||
if (maxDataSize > 0 && dataSize > maxDataSize)
|
|
||||||
throw new RunnerException(
|
|
||||||
tr("Not enough memory; see http://www.arduino.cc/en/Guide/Troubleshooting#size for tips on reducing your footprint."));
|
|
||||||
|
|
||||||
int warnDataPercentage = Integer.parseInt(prefs.get("build.warn_data_percentage"));
|
|
||||||
if (maxDataSize > 0 && dataSize > maxDataSize*warnDataPercentage/100)
|
|
||||||
System.err.println(tr("Low memory available, stability problems may occur."));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Compile sketch.
|
|
||||||
* @param _verbose
|
|
||||||
*
|
|
||||||
* @return true if successful.
|
|
||||||
* @throws RunnerException Only if there's a problem. Only then.
|
|
||||||
*/
|
|
||||||
public boolean compile(boolean _verbose, boolean _save) throws RunnerException, PreferencesMapException {
|
|
||||||
File sketchBuildFolder = new File(prefs.get("build.path"), "sketch");
|
|
||||||
if (!sketchBuildFolder.exists() && !sketchBuildFolder.mkdirs()) {
|
|
||||||
throw new RunnerException("Unable to create folder " + sketchBuildFolder);
|
|
||||||
}
|
|
||||||
preprocess(sketchBuildFolder.getAbsolutePath());
|
|
||||||
|
|
||||||
verbose = _verbose || PreferencesData.getBoolean("build.verbose");
|
|
||||||
saveHex = _save;
|
|
||||||
sketchIsCompiled = false;
|
|
||||||
|
|
||||||
// Hook runs at Start of Compilation
|
|
||||||
runActions("hooks.prebuild", prefs);
|
|
||||||
|
|
||||||
objectFiles = new ArrayList<File>();
|
|
||||||
|
|
||||||
// 0. include paths for core + all libraries
|
|
||||||
progressListener.progress(20);
|
|
||||||
List<File> includeFolders = new ArrayList<File>();
|
|
||||||
includeFolders.add(prefs.getFile("build.core.path"));
|
|
||||||
if (prefs.getFile("build.variant.path") != null)
|
|
||||||
includeFolders.add(prefs.getFile("build.variant.path"));
|
|
||||||
for (UserLibrary lib : importedLibraries) {
|
|
||||||
if (verbose) {
|
|
||||||
String legacy = "";
|
|
||||||
if (lib instanceof LegacyUserLibrary) {
|
|
||||||
legacy = "(legacy)";
|
|
||||||
}
|
|
||||||
|
|
||||||
if (lib.getParsedVersion() == null) {
|
|
||||||
System.out.println(I18n.format(tr("Using library {0} in folder: {1} {2}"), lib.getName(), lib.getInstalledFolder(), legacy));
|
|
||||||
} else {
|
|
||||||
System.out.println(I18n.format(tr("Using library {0} at version {1} in folder: {2} {3}"), lib.getName(), lib.getParsedVersion(), lib.getInstalledFolder(), legacy));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
includeFolders.add(lib.getSrcFolder());
|
|
||||||
}
|
|
||||||
|
|
||||||
if (verbose) {
|
|
||||||
System.out.println();
|
|
||||||
}
|
|
||||||
|
|
||||||
List<String> archs = new ArrayList<String>();
|
|
||||||
archs.add(BaseNoGui.getTargetPlatform().getId());
|
|
||||||
if (prefs.containsKey("architecture.override_check")) {
|
|
||||||
String[] overrides = prefs.get("architecture.override_check").split(",");
|
|
||||||
archs.addAll(Arrays.asList(overrides));
|
|
||||||
}
|
|
||||||
for (UserLibrary lib : importedLibraries) {
|
|
||||||
if (!lib.supportsArchitecture(archs)) {
|
|
||||||
System.err.println(I18n
|
|
||||||
.format(tr("WARNING: library {0} claims to run on {1} "
|
|
||||||
+ "architecture(s) and may be incompatible with your"
|
|
||||||
+ " current board which runs on {2} architecture(s)."), lib
|
|
||||||
.getName(), lib.getArchitectures(), archs));
|
|
||||||
System.err.println();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
runActions("hooks.sketch.prebuild", prefs);
|
|
||||||
|
|
||||||
// 1. compile the sketch (already in the buildPath)
|
|
||||||
progressListener.progress(20);
|
|
||||||
compileSketch(includeFolders, sketchBuildFolder);
|
|
||||||
sketchIsCompiled = true;
|
|
||||||
|
|
||||||
runActions("hooks.sketch.postbuild", prefs);
|
|
||||||
|
|
||||||
runActions("hooks.libraries.prebuild", prefs);
|
|
||||||
|
|
||||||
// 2. compile the libraries, outputting .o files to: <buildPath>/<library>/
|
|
||||||
// Doesn't really use configPreferences
|
|
||||||
progressListener.progress(30);
|
|
||||||
compileLibraries(includeFolders);
|
|
||||||
|
|
||||||
runActions("hooks.libraries.postbuild", prefs);
|
|
||||||
|
|
||||||
runActions("hooks.core.prebuild", prefs);
|
|
||||||
|
|
||||||
// 3. compile the core, outputting .o files to <buildPath> and then
|
|
||||||
// collecting them into the core.a library file.
|
|
||||||
progressListener.progress(40);
|
|
||||||
compileCore();
|
|
||||||
|
|
||||||
runActions("hooks.core.postbuild", prefs);
|
|
||||||
|
|
||||||
runActions("hooks.linking.prelink", prefs);
|
|
||||||
|
|
||||||
// 4. link it all together into the .elf file
|
|
||||||
progressListener.progress(50);
|
|
||||||
compileLink();
|
|
||||||
|
|
||||||
runActions("hooks.linking.postlink", prefs);
|
|
||||||
|
|
||||||
runActions("hooks.objcopy.preobjcopy", prefs);
|
|
||||||
|
|
||||||
// 5. run objcopy to generate output files
|
|
||||||
progressListener.progress(60);
|
|
||||||
List<String> objcopyPatterns = new ArrayList<String>();
|
|
||||||
for (String key : prefs.keySet()) {
|
|
||||||
if (key.startsWith("recipe.objcopy.") && key.endsWith(".pattern"))
|
|
||||||
objcopyPatterns.add(key);
|
|
||||||
}
|
|
||||||
Collections.sort(objcopyPatterns);
|
|
||||||
for (String recipe : objcopyPatterns) {
|
|
||||||
runRecipe(recipe);
|
|
||||||
}
|
|
||||||
|
|
||||||
runActions("hooks.objcopy.postobjcopy", prefs);
|
|
||||||
|
|
||||||
progressListener.progress(70);
|
|
||||||
try {
|
|
||||||
mergeSketchWithBootloaderIfAppropriate(sketch.getName() + ".cpp", prefs);
|
|
||||||
} catch (IOException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
// ignore
|
|
||||||
}
|
|
||||||
|
|
||||||
// 7. save the hex file
|
|
||||||
if (saveHex) {
|
|
||||||
runActions("hooks.savehex.presavehex", prefs);
|
|
||||||
|
|
||||||
progressListener.progress(80);
|
|
||||||
saveHex();
|
|
||||||
|
|
||||||
runActions("hooks.savehex.postsavehex", prefs);
|
|
||||||
}
|
|
||||||
|
|
||||||
progressListener.progress(90);
|
|
||||||
|
|
||||||
// Hook runs at End of Compilation
|
|
||||||
runActions("hooks.postbuild", prefs);
|
|
||||||
adviseDuplicateLibraries();
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void adviseDuplicateLibraries() {
|
|
||||||
if (importedDuplicateHeaders == null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
for (int i=0; i < importedDuplicateHeaders.size(); i++) {
|
|
||||||
System.out.println(I18n.format(tr("Multiple libraries were found for \"{0}\""),
|
|
||||||
importedDuplicateHeaders.get(i)));
|
|
||||||
boolean first = true;
|
|
||||||
for (UserLibrary lib : importedDuplicateLibraries.get(i)) {
|
|
||||||
if (first) {
|
|
||||||
System.out.println(I18n.format(tr(" Used: {0}"),
|
|
||||||
lib.getInstalledFolder().getPath()));
|
|
||||||
first = false;
|
|
||||||
} else {
|
|
||||||
System.out.println(I18n.format(tr(" Not used: {0}"),
|
|
||||||
lib.getInstalledFolder().getPath()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private PreferencesMap createBuildPreferences(String _buildPath,
|
|
||||||
String _primaryClassName)
|
|
||||||
throws RunnerException {
|
|
||||||
|
|
||||||
if (BaseNoGui.getBoardPreferences() == null) {
|
|
||||||
RunnerException re = new RunnerException(
|
|
||||||
tr("No board selected; please choose a board from the Tools > Board menu."));
|
|
||||||
re.hideStackTrace();
|
|
||||||
throw re;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check if the board needs a platform from another package
|
|
||||||
TargetPlatform targetPlatform = BaseNoGui.getTargetPlatform();
|
|
||||||
TargetPlatform corePlatform = null;
|
|
||||||
PreferencesMap boardPreferences = BaseNoGui.getBoardPreferences();
|
|
||||||
String core = boardPreferences.get("build.core", "arduino");
|
|
||||||
if (core.contains(":")) {
|
|
||||||
String[] split = core.split(":");
|
|
||||||
core = split[1];
|
|
||||||
corePlatform = BaseNoGui.getTargetPlatform(split[0], targetPlatform.getId());
|
|
||||||
if (corePlatform == null) {
|
|
||||||
RunnerException re = new RunnerException(I18n
|
|
||||||
.format(tr("Selected board depends on '{0}' core (not installed)."),
|
|
||||||
split[0]));
|
|
||||||
re.hideStackTrace();
|
|
||||||
throw re;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Merge all the global preference configuration in order of priority
|
|
||||||
PreferencesMap buildPref = new PreferencesMap();
|
|
||||||
buildPref.putAll(PreferencesData.getMap());
|
|
||||||
if (corePlatform != null) {
|
|
||||||
buildPref.putAll(corePlatform.getPreferences());
|
|
||||||
}
|
|
||||||
buildPref.putAll(targetPlatform.getPreferences());
|
|
||||||
buildPref.putAll(BaseNoGui.getBoardPreferences());
|
|
||||||
for (String k : buildPref.keySet()) {
|
|
||||||
if (buildPref.get(k) == null) {
|
|
||||||
buildPref.put(k, "");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
buildPref.put("build.path", _buildPath);
|
|
||||||
buildPref.put("build.project_name", _primaryClassName);
|
|
||||||
buildPref.put("build.arch", targetPlatform.getId().toUpperCase());
|
|
||||||
|
|
||||||
// Platform.txt should define its own compiler.path. For
|
|
||||||
// compatibility with earlier 1.5 versions, we define a (ugly,
|
|
||||||
// avr-specific) default for it, but this should be removed at some
|
|
||||||
// point.
|
|
||||||
if (!buildPref.containsKey("compiler.path")) {
|
|
||||||
System.err.println(tr("Third-party platform.txt does not define compiler.path. Please report this to the third-party hardware maintainer."));
|
|
||||||
buildPref.put("compiler.path", BaseNoGui.getAvrBasePath());
|
|
||||||
}
|
|
||||||
|
|
||||||
TargetPlatform referencePlatform = null;
|
|
||||||
if (corePlatform != null) {
|
|
||||||
referencePlatform = corePlatform;
|
|
||||||
} else {
|
|
||||||
referencePlatform = targetPlatform;
|
|
||||||
}
|
|
||||||
|
|
||||||
buildPref.put("build.platform.path", referencePlatform.getFolder().getAbsolutePath());
|
|
||||||
|
|
||||||
// Core folder
|
|
||||||
File coreFolder = new File(referencePlatform.getFolder(), "cores");
|
|
||||||
coreFolder = new File(coreFolder, core);
|
|
||||||
buildPref.put("build.core", core);
|
|
||||||
buildPref.put("build.core.path", coreFolder.getAbsolutePath());
|
|
||||||
|
|
||||||
// System Folder
|
|
||||||
File systemFolder = referencePlatform.getFolder();
|
|
||||||
systemFolder = new File(systemFolder, "system");
|
|
||||||
buildPref.put("build.system.path", systemFolder.getAbsolutePath());
|
|
||||||
|
|
||||||
// Variant Folder
|
|
||||||
String variant = buildPref.get("build.variant");
|
|
||||||
if (variant != null) {
|
|
||||||
TargetPlatform t;
|
|
||||||
if (!variant.contains(":")) {
|
|
||||||
t = targetPlatform;
|
|
||||||
} else {
|
|
||||||
String[] split = variant.split(":", 2);
|
|
||||||
t = BaseNoGui.getTargetPlatform(split[0], targetPlatform.getId());
|
|
||||||
variant = split[1];
|
|
||||||
}
|
|
||||||
File variantFolder = new File(t.getFolder(), "variants");
|
|
||||||
variantFolder = new File(variantFolder, variant);
|
|
||||||
buildPref.put("build.variant.path", variantFolder.getAbsolutePath());
|
|
||||||
} else {
|
|
||||||
buildPref.put("build.variant.path", "");
|
|
||||||
}
|
|
||||||
|
|
||||||
ContributedPlatform installedPlatform = BaseNoGui.indexer.getInstalled(referencePlatform.getContainerPackage().getId(), referencePlatform.getId());
|
|
||||||
if (installedPlatform != null) {
|
|
||||||
List<ContributedTool> tools = installedPlatform.getResolvedTools();
|
|
||||||
BaseNoGui.createToolPreferences(tools, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Build Time
|
|
||||||
GregorianCalendar cal = new GregorianCalendar();
|
|
||||||
long current = new Date().getTime() / 1000;
|
|
||||||
long timezone = cal.get(Calendar.ZONE_OFFSET) / 1000;
|
|
||||||
long daylight = cal.get(Calendar.DST_OFFSET) / 1000;
|
|
||||||
buildPref.put("extra.time.utc", Long.toString(current));
|
|
||||||
buildPref.put("extra.time.local", Long.toString(current + timezone + daylight));
|
|
||||||
buildPref.put("extra.time.zone", Long.toString(timezone));
|
|
||||||
buildPref.put("extra.time.dst", Long.toString(daylight));
|
|
||||||
|
|
||||||
List<Map.Entry<String, String>> unsetPrefs = buildPref.entrySet().stream()
|
|
||||||
.filter(entry -> Constants.PREF_REMOVE_PLACEHOLDER.equals(entry.getValue()))
|
|
||||||
.collect(Collectors.toList());
|
|
||||||
|
|
||||||
buildPref.entrySet().stream()
|
|
||||||
.filter(entry -> unsetPrefs.stream()
|
|
||||||
.filter(unsetPrefEntry -> entry.getValue().contains(unsetPrefEntry.getKey()))
|
|
||||||
.count() > 0)
|
|
||||||
.forEach(invalidEntry -> buildPref.put(invalidEntry.getKey(), ""));
|
|
||||||
|
|
||||||
new LoadVIDPIDSpecificPreferences().load(buildPref);
|
|
||||||
|
|
||||||
return buildPref;
|
|
||||||
}
|
|
||||||
|
|
||||||
private List<File> compileFiles(File outputPath, File sourcePath,
|
|
||||||
boolean recurse, List<File> includeFolders)
|
|
||||||
throws RunnerException, PreferencesMapException {
|
|
||||||
List<File> sSources = findFilesInFolder(sourcePath, "S", recurse);
|
|
||||||
List<File> cSources = findFilesInFolder(sourcePath, "c", recurse);
|
|
||||||
List<File> cppSources = findFilesInFolder(sourcePath, "cpp", recurse);
|
|
||||||
List<File> objectPaths = new ArrayList<File>();
|
|
||||||
|
|
||||||
for (File file : sSources) {
|
|
||||||
File objectFile = new File(outputPath, file.getName() + ".o");
|
|
||||||
objectPaths.add(objectFile);
|
|
||||||
String[] cmd = getCommandCompilerByRecipe(includeFolders, file, objectFile, "recipe.S.o.pattern");
|
|
||||||
execAsynchronously(cmd);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (File file : cSources) {
|
|
||||||
File objectFile = new File(outputPath, file.getName() + ".o");
|
|
||||||
File dependFile = new File(outputPath, file.getName() + ".d");
|
|
||||||
objectPaths.add(objectFile);
|
|
||||||
if (isAlreadyCompiled(file, objectFile, dependFile, prefs))
|
|
||||||
continue;
|
|
||||||
String[] cmd = getCommandCompilerByRecipe(includeFolders, file, objectFile, "recipe.c.o.pattern");
|
|
||||||
execAsynchronously(cmd);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (File file : cppSources) {
|
|
||||||
File objectFile = new File(outputPath, file.getName() + ".o");
|
|
||||||
File dependFile = new File(outputPath, file.getName() + ".d");
|
|
||||||
objectPaths.add(objectFile);
|
|
||||||
if (isAlreadyCompiled(file, objectFile, dependFile, prefs))
|
|
||||||
continue;
|
|
||||||
String[] cmd = getCommandCompilerByRecipe(includeFolders, file, objectFile, "recipe.cpp.o.pattern");
|
|
||||||
execAsynchronously(cmd);
|
|
||||||
}
|
|
||||||
|
|
||||||
return objectPaths;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Strip escape sequences used in makefile dependency files (.d)
|
|
||||||
* https://github.com/arduino/Arduino/issues/2255#issuecomment-57645845
|
|
||||||
*
|
|
||||||
* @param line
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
protected static String unescapeDepFile(String line) {
|
|
||||||
// Replaces: "\\" -> "\"
|
|
||||||
// Replaces: "\ " -> " "
|
|
||||||
// Replaces: "\#" -> "#"
|
|
||||||
line = line.replaceAll("\\\\([ #\\\\])", "$1");
|
|
||||||
// Replaces: "$$" -> "$"
|
|
||||||
line = line.replace("$$", "$");
|
|
||||||
return line;
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean isAlreadyCompiled(File src, File obj, File dep, Map<String, String> prefs) {
|
|
||||||
boolean ret=true;
|
|
||||||
BufferedReader reader = null;
|
|
||||||
try {
|
|
||||||
//System.out.println("\n isAlreadyCompiled: begin checks: " + obj.getPath());
|
|
||||||
if (!obj.exists()) return false; // object file (.o) does not exist
|
|
||||||
if (!dep.exists()) return false; // dep file (.d) does not exist
|
|
||||||
long src_modified = src.lastModified();
|
|
||||||
long obj_modified = obj.lastModified();
|
|
||||||
if (src_modified >= obj_modified) return false; // source modified since object compiled
|
|
||||||
if (src_modified >= dep.lastModified()) return false; // src modified since dep compiled
|
|
||||||
reader = new BufferedReader(new FileReader(dep.getPath()));
|
|
||||||
String line;
|
|
||||||
boolean need_obj_parse = true;
|
|
||||||
while ((line = reader.readLine()) != null) {
|
|
||||||
if (line.endsWith("\\")) {
|
|
||||||
line = line.substring(0, line.length() - 1);
|
|
||||||
}
|
|
||||||
line = line.trim();
|
|
||||||
line = unescapeDepFile(line);
|
|
||||||
if (line.length() == 0) continue; // ignore blank lines
|
|
||||||
if (need_obj_parse) {
|
|
||||||
// line is supposed to be the object file - make sure it really is!
|
|
||||||
if (line.endsWith(":")) {
|
|
||||||
line = line.substring(0, line.length() - 1);
|
|
||||||
String objpath = obj.getCanonicalPath();
|
|
||||||
File linefile = new File(line);
|
|
||||||
String linepath = linefile.getCanonicalPath();
|
|
||||||
//System.out.println(" isAlreadyCompiled: obj = " + objpath);
|
|
||||||
//System.out.println(" isAlreadyCompiled: line = " + linepath);
|
|
||||||
if (objpath.compareTo(linepath) == 0) {
|
|
||||||
need_obj_parse = false;
|
|
||||||
continue;
|
|
||||||
} else {
|
|
||||||
ret = false; // object named inside .d file is not the correct file!
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
ret = false; // object file supposed to end with ':', but didn't
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// line is a prerequisite file
|
|
||||||
File prereq = new File(line);
|
|
||||||
if (!prereq.exists()) {
|
|
||||||
ret = false; // prerequisite file did not exist
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (prereq.lastModified() >= obj_modified) {
|
|
||||||
ret = false; // prerequisite modified since object was compiled
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
//System.out.println(" isAlreadyCompiled: prerequisite ok");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (Exception e) {
|
|
||||||
return false; // any error reading dep file = recompile it
|
|
||||||
} finally {
|
|
||||||
IOUtils.closeQuietly(reader);
|
|
||||||
}
|
|
||||||
if (ret && verbose) {
|
|
||||||
System.out.println(I18n.format(tr("Using previously compiled file: {0}"), obj.getPath()));
|
|
||||||
}
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Either succeeds or throws a RunnerException fit for public consumption.
|
|
||||||
*/
|
|
||||||
private void execAsynchronously(String[] command) throws RunnerException {
|
|
||||||
|
|
||||||
// eliminate any empty array entries
|
|
||||||
List<String> stringList = new ArrayList<String>();
|
|
||||||
for (String string : command) {
|
|
||||||
string = string.trim();
|
|
||||||
if (string.length() != 0)
|
|
||||||
stringList.add(string);
|
|
||||||
}
|
|
||||||
command = stringList.toArray(new String[stringList.size()]);
|
|
||||||
if (command.length == 0)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (verbose) {
|
|
||||||
for (String c : command)
|
|
||||||
System.out.print(c + " ");
|
|
||||||
System.out.println();
|
|
||||||
}
|
|
||||||
|
|
||||||
DefaultExecutor executor = new DefaultExecutor();
|
|
||||||
executor.setStreamHandler(new PumpStreamHandler() {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected Thread createPump(InputStream is, OutputStream os, boolean closeWhenExhausted) {
|
|
||||||
final Thread result = new Thread(new MyStreamPumper(is, OldCompiler.this));
|
|
||||||
result.setDaemon(true);
|
|
||||||
return result;
|
|
||||||
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
CommandLine commandLine = new DoubleQuotedArgumentsOnWindowsCommandLine(command[0]);
|
|
||||||
for (int i = 1; i < command.length; i++) {
|
|
||||||
commandLine.addArgument(command[i], false);
|
|
||||||
}
|
|
||||||
|
|
||||||
int result;
|
|
||||||
executor.setExitValues(null);
|
|
||||||
try {
|
|
||||||
result = executor.execute(commandLine);
|
|
||||||
} catch (IOException e) {
|
|
||||||
RunnerException re = new RunnerException(e.getMessage());
|
|
||||||
re.hideStackTrace();
|
|
||||||
throw re;
|
|
||||||
}
|
|
||||||
executor.setExitValues(new int[0]);
|
|
||||||
|
|
||||||
// an error was queued up by message(), barf this back to compile(),
|
|
||||||
// which will barf it back to Editor. if you're having trouble
|
|
||||||
// discerning the imagery, consider how cows regurgitate their food
|
|
||||||
// to digest it, and the fact that they have five stomaches.
|
|
||||||
//
|
|
||||||
//System.out.println("throwing up " + exception);
|
|
||||||
if (exception != null)
|
|
||||||
throw exception;
|
|
||||||
|
|
||||||
if (result > 1) {
|
|
||||||
// a failure in the tool (e.g. unable to locate a sub-executable)
|
|
||||||
System.err
|
|
||||||
.println(I18n.format(tr("{0} returned {1}"), command[0], result));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (result != 0) {
|
|
||||||
RunnerException re = new RunnerException(tr("Error compiling."));
|
|
||||||
re.hideStackTrace();
|
|
||||||
throw re;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Part of the MessageConsumer interface, this is called
|
|
||||||
* whenever a piece (usually a line) of error message is spewed
|
|
||||||
* out from the compiler. The errors are parsed for their contents
|
|
||||||
* and line number, which is then reported back to Editor.
|
|
||||||
*/
|
|
||||||
public void message(String s) {
|
|
||||||
int i;
|
|
||||||
|
|
||||||
// remove the build path so people only see the filename
|
|
||||||
// can't use replaceAll() because the path may have characters in it which
|
|
||||||
// have meaning in a regular expression.
|
|
||||||
if (!verbose) {
|
|
||||||
String buildPath = prefs.get("build.path");
|
|
||||||
while ((i = s.indexOf(buildPath + File.separator)) != -1) {
|
|
||||||
s = s.substring(0, i) + s.substring(i + (buildPath + File.separator).length());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// look for error line, which contains file name, line number,
|
|
||||||
// and at least the first line of the error message
|
|
||||||
String errorFormat = "(.+\\.\\w+):(\\d+)(:\\d+)*:\\s*error:\\s*(.*)\\s*";
|
|
||||||
String[] pieces = PApplet.match(s, errorFormat);
|
|
||||||
|
|
||||||
// if (pieces != null && exception == null) {
|
|
||||||
// exception = sketch.placeException(pieces[3], pieces[1], PApplet.parseInt(pieces[2]) - 1);
|
|
||||||
// if (exception != null) exception.hideStackTrace();
|
|
||||||
// }
|
|
||||||
|
|
||||||
if (pieces != null) {
|
|
||||||
String error = pieces[pieces.length - 1], msg = "";
|
|
||||||
|
|
||||||
if (error.trim().equals("SPI.h: No such file or directory")) {
|
|
||||||
error = tr("Please import the SPI library from the Sketch > Import Library menu.");
|
|
||||||
msg = tr("\nAs of Arduino 0019, the Ethernet library depends on the SPI library." +
|
|
||||||
"\nYou appear to be using it or another library that depends on the SPI library.\n\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (error.trim().equals("'BYTE' was not declared in this scope")) {
|
|
||||||
error = tr("The 'BYTE' keyword is no longer supported.");
|
|
||||||
msg = tr("\nAs of Arduino 1.0, the 'BYTE' keyword is no longer supported." +
|
|
||||||
"\nPlease use Serial.write() instead.\n\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (error.trim().equals("no matching function for call to 'Server::Server(int)'")) {
|
|
||||||
error = tr("The Server class has been renamed EthernetServer.");
|
|
||||||
msg = tr("\nAs of Arduino 1.0, the Server class in the Ethernet library " +
|
|
||||||
"has been renamed to EthernetServer.\n\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (error.trim().equals("no matching function for call to 'Client::Client(byte [4], int)'")) {
|
|
||||||
error = tr("The Client class has been renamed EthernetClient.");
|
|
||||||
msg = tr("\nAs of Arduino 1.0, the Client class in the Ethernet library " +
|
|
||||||
"has been renamed to EthernetClient.\n\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (error.trim().equals("'Udp' was not declared in this scope")) {
|
|
||||||
error = tr("The Udp class has been renamed EthernetUdp.");
|
|
||||||
msg = tr("\nAs of Arduino 1.0, the Udp class in the Ethernet library " +
|
|
||||||
"has been renamed to EthernetUdp.\n\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (error.trim().equals("'class TwoWire' has no member named 'send'")) {
|
|
||||||
error = tr("Wire.send() has been renamed Wire.write().");
|
|
||||||
msg = tr("\nAs of Arduino 1.0, the Wire.send() function was renamed " +
|
|
||||||
"to Wire.write() for consistency with other libraries.\n\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (error.trim().equals("'class TwoWire' has no member named 'receive'")) {
|
|
||||||
error = tr("Wire.receive() has been renamed Wire.read().");
|
|
||||||
msg = tr("\nAs of Arduino 1.0, the Wire.receive() function was renamed " +
|
|
||||||
"to Wire.read() for consistency with other libraries.\n\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (error.trim().equals("'Mouse' was not declared in this scope")) {
|
|
||||||
error = tr("'Mouse' only supported on the Arduino Leonardo");
|
|
||||||
//msg = _("\nThe 'Mouse' class is only supported on the Arduino Leonardo.\n\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (error.trim().equals("'Keyboard' was not declared in this scope")) {
|
|
||||||
error = tr("'Keyboard' only supported on the Arduino Leonardo");
|
|
||||||
//msg = _("\nThe 'Keyboard' class is only supported on the Arduino Leonardo.\n\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
RunnerException e = null;
|
|
||||||
if (!sketchIsCompiled) {
|
|
||||||
// Place errors when compiling the sketch, but never while compiling libraries
|
|
||||||
// or the core. The user's sketch might contain the same filename!
|
|
||||||
e = placeException(error, pieces[1], PApplet.parseInt(pieces[2]) - 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
// replace full file path with the name of the sketch tab (unless we're
|
|
||||||
// in verbose mode, in which case don't modify the compiler output)
|
|
||||||
if (e != null && !verbose) {
|
|
||||||
SketchCode code = sketch.getCode(e.getCodeIndex());
|
|
||||||
String fileName = (code.isExtension("ino") || code.isExtension("pde")) ? code.getPrettyName() : code.getFileName();
|
|
||||||
int lineNum = e.getCodeLine() + 1;
|
|
||||||
s = fileName + ":" + lineNum + ": error: " + error + msg;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (e != null) {
|
|
||||||
if (exception == null || exception.getMessage().equals(e.getMessage())) {
|
|
||||||
exception = e;
|
|
||||||
exception.hideStackTrace();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (s.contains("undefined reference to `SPIClass::begin()'") &&
|
|
||||||
s.contains("libraries/Robot_Control")) {
|
|
||||||
String error = tr("Please import the SPI library from the Sketch > Import Library menu.");
|
|
||||||
exception = new RunnerException(error);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (s.contains("undefined reference to `Wire'") &&
|
|
||||||
s.contains("libraries/Robot_Control")) {
|
|
||||||
String error = tr("Please import the Wire library from the Sketch > Import Library menu.");
|
|
||||||
exception = new RunnerException(error);
|
|
||||||
}
|
|
||||||
|
|
||||||
System.err.print(s);
|
|
||||||
}
|
|
||||||
|
|
||||||
private String[] getCommandCompilerByRecipe(List<File> includeFolders, File sourceFile, File objectFile, String recipe) throws PreferencesMapException, RunnerException {
|
|
||||||
String includes = prepareIncludes(includeFolders);
|
|
||||||
PreferencesMap dict = new PreferencesMap(prefs);
|
|
||||||
dict.put("ide_version", "" + BaseNoGui.REVISION);
|
|
||||||
dict.put("includes", includes);
|
|
||||||
dict.put("source_file", sourceFile.getAbsolutePath());
|
|
||||||
dict.put("object_file", objectFile.getAbsolutePath());
|
|
||||||
|
|
||||||
setupWarningFlags(dict);
|
|
||||||
|
|
||||||
String cmd = prefs.getOrExcept(recipe);
|
|
||||||
try {
|
|
||||||
return StringReplacer.formatAndSplit(cmd, dict, true);
|
|
||||||
} catch (Exception e) {
|
|
||||||
throw new RunnerException(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void setupWarningFlags(PreferencesMap dict) {
|
|
||||||
if (dict.containsKey("compiler.warning_level")) {
|
|
||||||
String key = "compiler.warning_flags." + dict.get("compiler.warning_level");
|
|
||||||
dict.put("compiler.warning_flags", dict.get(key));
|
|
||||||
} else {
|
|
||||||
dict.put("compiler.warning_flags", dict.get("compiler.warning_flags.none"));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (dict.get("compiler.warning_flags") == null) {
|
|
||||||
dict.remove("compiler.warning_flags");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
private void createFolder(File folder) throws RunnerException {
|
|
||||||
if (folder.isDirectory())
|
|
||||||
return;
|
|
||||||
if (!folder.mkdir())
|
|
||||||
throw new RunnerException("Couldn't create: " + folder);
|
|
||||||
}
|
|
||||||
|
|
||||||
static public List<File> findFilesInFolder(File folder, String extension,
|
|
||||||
boolean recurse) {
|
|
||||||
List<File> files = new ArrayList<File>();
|
|
||||||
|
|
||||||
if (FileUtils.isSCCSOrHiddenFile(folder)) {
|
|
||||||
return files;
|
|
||||||
}
|
|
||||||
|
|
||||||
File[] listFiles = folder.listFiles();
|
|
||||||
if (listFiles == null) {
|
|
||||||
return files;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (File file : listFiles) {
|
|
||||||
if (FileUtils.isSCCSOrHiddenFile(file)) {
|
|
||||||
continue; // skip hidden files
|
|
||||||
}
|
|
||||||
|
|
||||||
if (file.getName().endsWith("." + extension))
|
|
||||||
files.add(file);
|
|
||||||
|
|
||||||
if (recurse && file.isDirectory()) {
|
|
||||||
files.addAll(findFilesInFolder(file, extension, true));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return files;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 1. compile the sketch (already in the buildPath)
|
|
||||||
void compileSketch(List<File> includeFolders, File buildPath) throws RunnerException, PreferencesMapException {
|
|
||||||
objectFiles.addAll(compileFiles(buildPath, buildPath, false, includeFolders));
|
|
||||||
}
|
|
||||||
|
|
||||||
// 2. compile the libraries, outputting .o files to:
|
|
||||||
// <buildPath>/<library>/
|
|
||||||
void compileLibraries(List<File> includeFolders) throws RunnerException, PreferencesMapException {
|
|
||||||
for (UserLibrary lib : importedLibraries) {
|
|
||||||
compileLibrary(lib, includeFolders);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void compileLibrary(UserLibrary lib, List<File> includeFolders)
|
|
||||||
throws RunnerException, PreferencesMapException {
|
|
||||||
File libFolder = lib.getSrcFolder();
|
|
||||||
File librariesFolder = new File(prefs.getFile("build.path"), "libraries");
|
|
||||||
if (!librariesFolder.exists() && !librariesFolder.mkdirs()) {
|
|
||||||
throw new RunnerException("Unable to create folder " + librariesFolder);
|
|
||||||
}
|
|
||||||
|
|
||||||
File libBuildFolder = new File(librariesFolder, lib.getName());
|
|
||||||
|
|
||||||
if (lib.useRecursion()) {
|
|
||||||
// libBuildFolder == {build.path}/LibName
|
|
||||||
// libFolder == {lib.path}/src
|
|
||||||
recursiveCompileFilesInFolder(libBuildFolder, libFolder, includeFolders);
|
|
||||||
|
|
||||||
} else {
|
|
||||||
// libFolder == {lib.path}/
|
|
||||||
// utilityFolder == {lib.path}/utility
|
|
||||||
// libBuildFolder == {build.path}/LibName
|
|
||||||
// utilityBuildFolder == {build.path}/LibName/utility
|
|
||||||
File utilityFolder = new File(libFolder, "utility");
|
|
||||||
File utilityBuildFolder = new File(libBuildFolder, "utility");
|
|
||||||
|
|
||||||
includeFolders.add(utilityFolder);
|
|
||||||
compileFilesInFolder(libBuildFolder, libFolder, includeFolders);
|
|
||||||
compileFilesInFolder(utilityBuildFolder, utilityFolder, includeFolders);
|
|
||||||
|
|
||||||
// other libraries should not see this library's utility/ folder
|
|
||||||
includeFolders.remove(utilityFolder);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void recursiveCompileFilesInFolder(File srcBuildFolder, File srcFolder, List<File> includeFolders) throws RunnerException, PreferencesMapException {
|
|
||||||
compileFilesInFolder(srcBuildFolder, srcFolder, includeFolders);
|
|
||||||
for (File subFolder : srcFolder.listFiles(new OnlyDirs())) {
|
|
||||||
File subBuildFolder = new File(srcBuildFolder, subFolder.getName());
|
|
||||||
recursiveCompileFilesInFolder(subBuildFolder, subFolder, includeFolders);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void compileFilesInFolder(File buildFolder, File srcFolder, List<File> includeFolders) throws RunnerException, PreferencesMapException {
|
|
||||||
createFolder(buildFolder);
|
|
||||||
List<File> objects = compileFiles(buildFolder, srcFolder, false, includeFolders);
|
|
||||||
objectFiles.addAll(objects);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 3. compile the core, outputting .o files to <buildPath> and then
|
|
||||||
// collecting them into the core.a library file.
|
|
||||||
// Also compiles the variant (if it supplies actual source files),
|
|
||||||
// which are included in the link directly (not through core.a)
|
|
||||||
void compileCore()
|
|
||||||
throws RunnerException, PreferencesMapException {
|
|
||||||
|
|
||||||
File coreFolder = prefs.getFile("build.core.path");
|
|
||||||
File variantFolder = prefs.getFile("build.variant.path");
|
|
||||||
File buildFolder = new File(prefs.getFile("build.path"), "core");
|
|
||||||
if (!buildFolder.exists() && !buildFolder.mkdirs()) {
|
|
||||||
throw new RunnerException("Unable to create folder " + buildFolder);
|
|
||||||
}
|
|
||||||
|
|
||||||
List<File> includeFolders = new ArrayList<File>();
|
|
||||||
includeFolders.add(coreFolder); // include core path only
|
|
||||||
if (variantFolder != null)
|
|
||||||
includeFolders.add(variantFolder);
|
|
||||||
|
|
||||||
|
|
||||||
if (variantFolder != null)
|
|
||||||
objectFiles.addAll(compileFiles(buildFolder, variantFolder, true,
|
|
||||||
includeFolders));
|
|
||||||
|
|
||||||
File afile = new File(buildFolder, "core.a");
|
|
||||||
|
|
||||||
List<File> coreObjectFiles = compileFiles(buildFolder, coreFolder, true,
|
|
||||||
includeFolders);
|
|
||||||
|
|
||||||
// See if the .a file is already uptodate
|
|
||||||
if (afile.exists()) {
|
|
||||||
boolean changed = false;
|
|
||||||
for (File file : coreObjectFiles) {
|
|
||||||
if (file.lastModified() > afile.lastModified()) {
|
|
||||||
changed = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// If none of the object files is newer than the .a file, don't
|
|
||||||
// bother rebuilding the .a file. There is a small corner case
|
|
||||||
// here: If a source file was removed, but no other source file
|
|
||||||
// was modified, this will not rebuild core.a even when it
|
|
||||||
// should. It's hard to fix and not a realistic case, so it
|
|
||||||
// shouldn't be a problem.
|
|
||||||
if (!changed) {
|
|
||||||
if (verbose)
|
|
||||||
System.out.println(I18n.format(tr("Using previously compiled file: {0}"), afile.getPath()));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Delete the .a file, to prevent any previous code from lingering
|
|
||||||
afile.delete();
|
|
||||||
|
|
||||||
try {
|
|
||||||
for (File file : coreObjectFiles) {
|
|
||||||
|
|
||||||
PreferencesMap dict = new PreferencesMap(prefs);
|
|
||||||
dict.put("ide_version", "" + BaseNoGui.REVISION);
|
|
||||||
dict.put("archive_file", afile.getName());
|
|
||||||
dict.put("object_file", file.getAbsolutePath());
|
|
||||||
dict.put("build.path", buildFolder.getAbsolutePath());
|
|
||||||
|
|
||||||
String[] cmdArray;
|
|
||||||
String cmd = prefs.getOrExcept("recipe.ar.pattern");
|
|
||||||
try {
|
|
||||||
cmdArray = StringReplacer.formatAndSplit(cmd, dict, true);
|
|
||||||
} catch (Exception e) {
|
|
||||||
throw new RunnerException(e);
|
|
||||||
}
|
|
||||||
execAsynchronously(cmdArray);
|
|
||||||
}
|
|
||||||
} catch (RunnerException e) {
|
|
||||||
afile.delete();
|
|
||||||
throw e;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 4. link it all together into the .elf file
|
|
||||||
void compileLink()
|
|
||||||
throws RunnerException, PreferencesMapException {
|
|
||||||
|
|
||||||
// TODO: Make the --relax thing in configuration files.
|
|
||||||
|
|
||||||
// For atmega2560, need --relax linker option to link larger
|
|
||||||
// programs correctly.
|
|
||||||
String optRelax = "";
|
|
||||||
if (prefs.get("build.mcu").equals("atmega2560"))
|
|
||||||
optRelax = ",--relax";
|
|
||||||
|
|
||||||
String objectFileList = "";
|
|
||||||
for (File file : objectFiles)
|
|
||||||
objectFileList += " \"" + file.getAbsolutePath() + '"';
|
|
||||||
objectFileList = objectFileList.substring(1);
|
|
||||||
|
|
||||||
PreferencesMap dict = new PreferencesMap(prefs);
|
|
||||||
String flags = dict.get("compiler.c.elf.flags") + optRelax;
|
|
||||||
dict.put("compiler.c.elf.flags", flags);
|
|
||||||
dict.put("archive_file", new File("core", "core.a").getPath());
|
|
||||||
dict.put("object_files", objectFileList);
|
|
||||||
dict.put("ide_version", "" + BaseNoGui.REVISION);
|
|
||||||
|
|
||||||
setupWarningFlags(dict);
|
|
||||||
|
|
||||||
String[] cmdArray;
|
|
||||||
String cmd = prefs.getOrExcept("recipe.c.combine.pattern");
|
|
||||||
try {
|
|
||||||
cmdArray = StringReplacer.formatAndSplit(cmd, dict, true);
|
|
||||||
} catch (Exception e) {
|
|
||||||
throw new RunnerException(e);
|
|
||||||
}
|
|
||||||
execAsynchronously(cmdArray);
|
|
||||||
}
|
|
||||||
|
|
||||||
void runActions(String recipeClass, PreferencesMap prefs) throws RunnerException, PreferencesMapException {
|
|
||||||
List<String> patterns = new ArrayList<String>();
|
|
||||||
for (String key : prefs.keySet()) {
|
|
||||||
if (key.startsWith("recipe."+recipeClass) && key.endsWith(".pattern"))
|
|
||||||
patterns.add(key);
|
|
||||||
}
|
|
||||||
Collections.sort(patterns);
|
|
||||||
for (String recipe : patterns) {
|
|
||||||
runRecipe(recipe);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void runRecipe(String recipe) throws RunnerException, PreferencesMapException {
|
|
||||||
PreferencesMap dict = new PreferencesMap(prefs);
|
|
||||||
dict.put("ide_version", "" + BaseNoGui.REVISION);
|
|
||||||
dict.put("sketch_path", sketch.getFolder().getAbsolutePath());
|
|
||||||
|
|
||||||
String[] cmdArray;
|
|
||||||
String cmd = prefs.getOrExcept(recipe);
|
|
||||||
try {
|
|
||||||
cmdArray = StringReplacer.formatAndSplit(cmd, dict, true);
|
|
||||||
} catch (Exception e) {
|
|
||||||
throw new RunnerException(e);
|
|
||||||
}
|
|
||||||
execAsynchronously(cmdArray);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void mergeSketchWithBootloaderIfAppropriate(String className, PreferencesMap prefs) throws IOException {
|
|
||||||
if (!prefs.containsKey("bootloader.noblink") && !prefs.containsKey("bootloader.file")) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
String buildPath = prefs.get("build.path");
|
|
||||||
|
|
||||||
Path sketch;
|
|
||||||
Path sketchInSubfolder = Paths.get(buildPath, "sketch", className + ".hex");
|
|
||||||
Path sketchInBuildPath = Paths.get(buildPath, className + ".hex");
|
|
||||||
if (Files.exists(sketchInSubfolder)) {
|
|
||||||
sketch = sketchInSubfolder;
|
|
||||||
} else if (Files.exists(sketchInBuildPath)) {
|
|
||||||
sketch = sketchInBuildPath;
|
|
||||||
} else {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
String bootloaderNoBlink = prefs.get("bootloader.noblink");
|
|
||||||
if (bootloaderNoBlink == null) {
|
|
||||||
bootloaderNoBlink = prefs.get("bootloader.file");
|
|
||||||
}
|
|
||||||
|
|
||||||
Path bootloader = Paths.get(prefs.get("runtime.platform.path"), "bootloaders", bootloaderNoBlink);
|
|
||||||
if (!Files.exists(bootloader)) {
|
|
||||||
System.err.println(I18n.format(tr("Bootloader file specified but missing: {0}"), bootloader));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
Path mergedSketch;
|
|
||||||
if ("sketch".equals(sketch.getParent().getFileName().toString())) {
|
|
||||||
mergedSketch = Paths.get(buildPath, "sketch", className + ".with_bootloader.hex");
|
|
||||||
} else {
|
|
||||||
mergedSketch = Paths.get(buildPath, className + ".with_bootloader.hex");
|
|
||||||
}
|
|
||||||
|
|
||||||
Files.copy(sketch, mergedSketch, StandardCopyOption.REPLACE_EXISTING);
|
|
||||||
|
|
||||||
new MergeSketchWithBooloader().merge(mergedSketch.toFile(), bootloader.toFile());
|
|
||||||
}
|
|
||||||
|
|
||||||
//7. Save the .hex file
|
|
||||||
void saveHex() throws RunnerException {
|
|
||||||
List<String> compiledSketches = new ArrayList<>(prefs.subTree("recipe.output.tmp_file", 1).values());
|
|
||||||
List<String> copyOfCompiledSketches = new ArrayList<>(prefs.subTree("recipe.output.save_file", 1).values());
|
|
||||||
|
|
||||||
if (isExportCompiledSketchSupported(compiledSketches, copyOfCompiledSketches)) {
|
|
||||||
System.err.println(tr("Warning: This core does not support exporting sketches. Please consider upgrading it or contacting its author"));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
PreferencesMap dict = new PreferencesMap(prefs);
|
|
||||||
dict.put("ide_version", "" + BaseNoGui.REVISION);
|
|
||||||
|
|
||||||
if (!compiledSketches.isEmpty()) {
|
|
||||||
for (int i = 0; i < compiledSketches.size(); i++) {
|
|
||||||
saveHex(compiledSketches.get(i), copyOfCompiledSketches.get(i), prefs);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
try {
|
|
||||||
saveHex(prefs.getOrExcept("recipe.output.tmp_file"), prefs.getOrExcept("recipe.output.save_file"), prefs);
|
|
||||||
} catch (PreferencesMapException e) {
|
|
||||||
throw new RunnerException(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean isExportCompiledSketchSupported(List<String> compiledSketches, List<String> copyOfCompiledSketches) {
|
|
||||||
return (compiledSketches.isEmpty() || copyOfCompiledSketches.isEmpty() || copyOfCompiledSketches.size() < compiledSketches.size()) && (!prefs.containsKey("recipe.output.tmp_file") || !prefs.containsKey("recipe.output.save_file"));
|
|
||||||
}
|
|
||||||
|
|
||||||
private void saveHex(String compiledSketch, String copyOfCompiledSketch, PreferencesMap dict) throws RunnerException {
|
|
||||||
try {
|
|
||||||
compiledSketch = StringReplacer.replaceFromMapping(compiledSketch, dict);
|
|
||||||
copyOfCompiledSketch = StringReplacer.replaceFromMapping(copyOfCompiledSketch, dict);
|
|
||||||
|
|
||||||
Path compiledSketchPath;
|
|
||||||
Path compiledSketchPathInSubfolder = Paths.get(prefs.get("build.path"), "sketch", compiledSketch);
|
|
||||||
Path compiledSketchPathInBuildPath = Paths.get(prefs.get("build.path"), compiledSketch);
|
|
||||||
if (Files.exists(compiledSketchPathInSubfolder)) {
|
|
||||||
compiledSketchPath = compiledSketchPathInSubfolder;
|
|
||||||
} else {
|
|
||||||
compiledSketchPath = compiledSketchPathInBuildPath;
|
|
||||||
}
|
|
||||||
|
|
||||||
Path copyOfCompiledSketchFilePath = Paths.get(this.sketch.getFolder().getAbsolutePath(), copyOfCompiledSketch);
|
|
||||||
|
|
||||||
Files.copy(compiledSketchPath, copyOfCompiledSketchFilePath, StandardCopyOption.REPLACE_EXISTING);
|
|
||||||
} catch (IOException e) {
|
|
||||||
throw new RunnerException(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static String prepareIncludes(List<File> includeFolders) {
|
|
||||||
String res = "";
|
|
||||||
for (File p : includeFolders)
|
|
||||||
res += " \"-I" + p.getAbsolutePath() + '"';
|
|
||||||
|
|
||||||
// Remove first space
|
|
||||||
return res.substring(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
public PreferencesMap getBuildPreferences() {
|
|
||||||
return prefs;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Build all the code for this sketch.
|
|
||||||
*
|
|
||||||
* In an advanced program, the returned class name could be different,
|
|
||||||
* which is why the className is set based on the return value.
|
|
||||||
* A compilation error will burp up a RunnerException.
|
|
||||||
*
|
|
||||||
* Setting purty to 'true' will cause exception line numbers to be incorrect.
|
|
||||||
* Unless you know the code compiles, you should first run the preprocessor
|
|
||||||
* with purty set to false to make sure there are no errors, then once
|
|
||||||
* successful, re-export with purty set to true.
|
|
||||||
*
|
|
||||||
* @param buildPath Location to copy all the .java files
|
|
||||||
* @return null if compilation failed, main class name if not
|
|
||||||
*/
|
|
||||||
public void preprocess(String buildPath) throws RunnerException {
|
|
||||||
preprocess(buildPath, new PdePreprocessor());
|
|
||||||
}
|
|
||||||
|
|
||||||
public void preprocess(String buildPath, PdePreprocessor preprocessor) throws RunnerException {
|
|
||||||
|
|
||||||
// 1. concatenate all .pde files to the 'main' pde
|
|
||||||
// store line number for starting point of each code bit
|
|
||||||
|
|
||||||
StringBuffer bigCode = new StringBuffer();
|
|
||||||
int bigCount = 0;
|
|
||||||
for (SketchCode sc : sketch.getCodes()) {
|
|
||||||
if (sc.isExtension(SketchData.SKETCH_EXTENSIONS)) {
|
|
||||||
sc.setPreprocOffset(bigCount);
|
|
||||||
// These #line directives help the compiler report errors with
|
|
||||||
// correct the filename and line number (issue 281 & 907)
|
|
||||||
bigCode.append("#line 1 \"" + sc.getFileName() + "\"\n");
|
|
||||||
bigCode.append(sc.getProgram());
|
|
||||||
bigCode.append('\n');
|
|
||||||
bigCount += sc.getLineCount();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Note that the headerOffset isn't applied until compile and run, because
|
|
||||||
// it only applies to the code after it's been written to the .java file.
|
|
||||||
int headerOffset = 0;
|
|
||||||
try {
|
|
||||||
headerOffset = preprocessor.writePrefix(bigCode.toString());
|
|
||||||
} catch (FileNotFoundException fnfe) {
|
|
||||||
fnfe.printStackTrace();
|
|
||||||
String msg = tr("Build folder disappeared or could not be written");
|
|
||||||
throw new RunnerException(msg);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 2. run preproc on that code using the sugg class name
|
|
||||||
// to create a single .java file and write to buildpath
|
|
||||||
|
|
||||||
FileOutputStream outputStream = null;
|
|
||||||
try {
|
|
||||||
// Output file
|
|
||||||
File streamFile = new File(buildPath, sketch.getName() + ".cpp");
|
|
||||||
outputStream = new FileOutputStream(streamFile);
|
|
||||||
preprocessor.write(outputStream);
|
|
||||||
} catch (FileNotFoundException fnfe) {
|
|
||||||
fnfe.printStackTrace();
|
|
||||||
String msg = tr("Build folder disappeared or could not be written");
|
|
||||||
throw new RunnerException(msg);
|
|
||||||
} catch (RunnerException pe) {
|
|
||||||
// RunnerExceptions are caught here and re-thrown, so that they don't
|
|
||||||
// get lost in the more general "Exception" handler below.
|
|
||||||
throw pe;
|
|
||||||
|
|
||||||
} catch (Exception ex) {
|
|
||||||
// TODO better method for handling this?
|
|
||||||
System.err.println(I18n.format(tr("Uncaught exception type: {0}"), ex.getClass()));
|
|
||||||
ex.printStackTrace();
|
|
||||||
throw new RunnerException(ex.toString());
|
|
||||||
} finally {
|
|
||||||
IOUtils.closeQuietly(outputStream);
|
|
||||||
}
|
|
||||||
|
|
||||||
// grab the imports from the code just preproc'd
|
|
||||||
|
|
||||||
importedLibraries = new LibraryList();
|
|
||||||
importedDuplicateHeaders = new ArrayList<String>();
|
|
||||||
importedDuplicateLibraries = new ArrayList<LibraryList>();
|
|
||||||
for (String item : preprocessor.getExtraImports()) {
|
|
||||||
LibraryList list = BaseNoGui.importToLibraryTable.get(item);
|
|
||||||
if (list != null) {
|
|
||||||
UserLibrary lib = list.peekFirst();
|
|
||||||
if (lib != null && !importedLibraries.contains(lib)) {
|
|
||||||
importedLibraries.add(lib);
|
|
||||||
if (list.size() > 1) {
|
|
||||||
importedDuplicateHeaders.add(item);
|
|
||||||
importedDuplicateLibraries.add(list);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 3. then loop over the code[] and save each .java file
|
|
||||||
for (SketchCode sc : sketch.getCodes()) {
|
|
||||||
if (sc.isExtension(SketchData.OTHER_ALLOWED_EXTENSIONS)) {
|
|
||||||
// no pre-processing services necessary for java files
|
|
||||||
// just write the the contents of 'program' to a .java file
|
|
||||||
// into the build directory. uses byte stream and reader/writer
|
|
||||||
// shtuff so that unicode bunk is properly handled
|
|
||||||
String filename = sc.getFileName(); //code[i].name + ".java";
|
|
||||||
try {
|
|
||||||
BaseNoGui.saveFile(sc.getProgram(), new File(buildPath, filename));
|
|
||||||
} catch (IOException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
throw new RunnerException(I18n.format(tr("Problem moving {0} to the build folder"), filename));
|
|
||||||
}
|
|
||||||
|
|
||||||
} else if (sc.isExtension("ino") || sc.isExtension("pde")) {
|
|
||||||
// The compiler and runner will need this to have a proper offset
|
|
||||||
sc.addPreprocOffset(headerOffset);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
copyAdditionalFilesToBuildFolderSavingOriginalFolderStructure(sketch, buildPath);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void copyAdditionalFilesToBuildFolderSavingOriginalFolderStructure(SketchData sketch, String buildPath) throws RunnerException {
|
|
||||||
Path sketchPath = Paths.get(sketch.getFolder().getAbsolutePath());
|
|
||||||
Stream<Path> otherFilesStream;
|
|
||||||
try {
|
|
||||||
otherFilesStream = Files.find(sketchPath, ADDITIONAL_FILES_COPY_MAX_DEPTH, (path, attribs) -> !attribs.isDirectory() && isPathInASubfolder(sketchPath, path) && FileUtils.hasExtension(path.toFile(), SketchData.OTHER_ALLOWED_EXTENSIONS));
|
|
||||||
} catch (IOException e) {
|
|
||||||
throw new RunnerException(e);
|
|
||||||
}
|
|
||||||
otherFilesStream.map((path) -> new Pair<>(path, Paths.get(buildPath, sketchPath.relativize(path).toString())))
|
|
||||||
.forEach((pair) -> {
|
|
||||||
try {
|
|
||||||
Files.createDirectories(pair.value.getParent());
|
|
||||||
Files.copy(pair.key, pair.value, StandardCopyOption.REPLACE_EXISTING);
|
|
||||||
} catch (IOException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
throw new RuntimeException(I18n.format(tr("Problem moving {0} to the build folder"), sketchPath.relativize(pair.key).toString()));
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean isPathInASubfolder(Path sketchPath, Path path) {
|
|
||||||
return sketchPath.relativize(path).getNameCount() > 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* List of library folders.
|
|
||||||
*/
|
|
||||||
private LibraryList importedLibraries;
|
|
||||||
private List<String> importedDuplicateHeaders;
|
|
||||||
private List<LibraryList> importedDuplicateLibraries;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Map an error from a set of processed .java files back to its location
|
|
||||||
* in the actual sketch.
|
|
||||||
* @param message The error message.
|
|
||||||
* @param dotJavaFilename The .java file where the exception was found.
|
|
||||||
* @param dotJavaLine Line number of the .java file for the exception (0-indexed!)
|
|
||||||
* @return A RunnerException to be sent to the editor, or null if it wasn't
|
|
||||||
* possible to place the exception to the sketch code.
|
|
||||||
*/
|
|
||||||
public RunnerException placeException(String message,
|
|
||||||
String dotJavaFilename,
|
|
||||||
int dotJavaLine) {
|
|
||||||
// Placing errors is simple, because we inserted #line directives
|
|
||||||
// into the preprocessed source. The compiler gives us correct
|
|
||||||
// the file name and line number. :-)
|
|
||||||
for (SketchCode code : sketch.getCodes()) {
|
|
||||||
if (dotJavaFilename.equals(code.getFileName())) {
|
|
||||||
return new RunnerException(message, sketch.indexOfCode(code), dotJavaLine);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,9 +0,0 @@
|
|||||||
*Lexer.java
|
|
||||||
*Recognizer.java
|
|
||||||
*TokenTypes.java
|
|
||||||
*TokenTypes.txt
|
|
||||||
*TreeParser.java
|
|
||||||
*TreeParserTokenTypes.java
|
|
||||||
*TreeParserTokenTypes.txt
|
|
||||||
expanded*.g
|
|
||||||
|
|
@ -1,435 +0,0 @@
|
|||||||
/* -*- mode: jde; c-basic-offset: 2; indent-tabs-mode: nil -*- */
|
|
||||||
|
|
||||||
/*
|
|
||||||
PdePreprocessor - wrapper for default ANTLR-generated parser
|
|
||||||
Part of the Wiring project - http://wiring.org.co
|
|
||||||
|
|
||||||
Copyright (c) 2004-05 Hernando Barragan
|
|
||||||
|
|
||||||
Processing version Copyright (c) 2004-05 Ben Fry and Casey Reas
|
|
||||||
Copyright (c) 2001-04 Massachusetts Institute of Technology
|
|
||||||
|
|
||||||
ANTLR-generated parser and several supporting classes written
|
|
||||||
by Dan Mosedale via funding from the Interaction Institute IVREA.
|
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
|
||||||
it under the terms of the GNU General Public License as published by
|
|
||||||
the Free Software Foundation; either version 2 of the License, or
|
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
|
||||||
along with this program; if not, write to the Free Software Foundation,
|
|
||||||
Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
||||||
*/
|
|
||||||
|
|
||||||
package processing.app.preproc;
|
|
||||||
|
|
||||||
import static processing.app.I18n.tr;
|
|
||||||
import processing.app.*;
|
|
||||||
import processing.app.legacy.PApplet;
|
|
||||||
|
|
||||||
import java.io.*;
|
|
||||||
import java.util.*;
|
|
||||||
import java.util.regex.*;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Class that orchestrates preprocessing p5 syntax into straight Java.
|
|
||||||
*/
|
|
||||||
public class PdePreprocessor {
|
|
||||||
|
|
||||||
private static final String IMPORT_REGEX = "^\\s*#include\\s*[<\"](\\S+)[\">]";
|
|
||||||
|
|
||||||
// stores number of built user-defined function prototypes
|
|
||||||
public int prototypeCount = 0;
|
|
||||||
|
|
||||||
// stores number of included library headers written
|
|
||||||
// we always write one header: Arduino.h
|
|
||||||
public int headerCount = 1;
|
|
||||||
|
|
||||||
// the prototypes that are generated by the preprocessor
|
|
||||||
List<String> prototypes;
|
|
||||||
|
|
||||||
// these ones have the .* at the end, since a class name might be at the end
|
|
||||||
// instead of .* which would make trouble other classes using this can lop
|
|
||||||
// off the . and anything after it to produce a package name consistently.
|
|
||||||
List<String> programImports;
|
|
||||||
|
|
||||||
// imports just from the code folder, treated differently
|
|
||||||
// than the others, since the imports are auto-generated.
|
|
||||||
List<String> codeFolderImports;
|
|
||||||
|
|
||||||
String program;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Setup a new preprocessor.
|
|
||||||
*/
|
|
||||||
public PdePreprocessor() {
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Writes out the head of the c++ code generated for a sketch.
|
|
||||||
* Called from processing.app.Sketch.
|
|
||||||
* @param program the concatenated code from all tabs containing pde-files
|
|
||||||
*/
|
|
||||||
public int writePrefix(String program)
|
|
||||||
throws FileNotFoundException {
|
|
||||||
// if the program ends with no CR or LF an OutOfMemoryError will happen.
|
|
||||||
// not gonna track down the bug now, so here's a hack for it:
|
|
||||||
// http://dev.processing.org/bugs/show_bug.cgi?id=5
|
|
||||||
program += "\n";
|
|
||||||
|
|
||||||
// if the program ends with an unterminated multi-line comment,
|
|
||||||
// an OutOfMemoryError or NullPointerException will happen.
|
|
||||||
// again, not gonna bother tracking this down, but here's a hack.
|
|
||||||
// http://dev.processing.org/bugs/show_bug.cgi?id=16
|
|
||||||
program = scrubComments(program);
|
|
||||||
// If there are errors, an exception is thrown and this fxn exits.
|
|
||||||
|
|
||||||
if (PreferencesData.getBoolean("preproc.substitute_unicode")) {
|
|
||||||
program = substituteUnicode(program);
|
|
||||||
}
|
|
||||||
|
|
||||||
//String importRegexp = "(?:^|\\s|;)(import\\s+)(\\S+)(\\s*;)";
|
|
||||||
programImports = new ArrayList<String>();
|
|
||||||
|
|
||||||
String[][] pieces = PApplet.matchAll(program, IMPORT_REGEX);
|
|
||||||
|
|
||||||
if (pieces != null)
|
|
||||||
for (int i = 0; i < pieces.length; i++)
|
|
||||||
programImports.add(pieces[i][1]); // the package name
|
|
||||||
|
|
||||||
codeFolderImports = new ArrayList<String>();
|
|
||||||
// if (codeFolderPackages != null) {
|
|
||||||
// for (String item : codeFolderPackages) {
|
|
||||||
// codeFolderImports.add(item + ".*");
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
prototypes = prototypes(program);
|
|
||||||
|
|
||||||
// store # of prototypes so that line number reporting can be adjusted
|
|
||||||
prototypeCount = prototypes.size();
|
|
||||||
|
|
||||||
// do this after the program gets re-combobulated
|
|
||||||
this.program = program;
|
|
||||||
|
|
||||||
return headerCount + prototypeCount;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static List<String> findIncludes(String code){
|
|
||||||
|
|
||||||
String[][] pieces = PApplet.matchAll(code, IMPORT_REGEX);
|
|
||||||
|
|
||||||
ArrayList programImports = new ArrayList<String>();
|
|
||||||
|
|
||||||
if (pieces != null)
|
|
||||||
for (int i = 0; i < pieces.length; i++)
|
|
||||||
programImports.add(pieces[i][1]); // the package name
|
|
||||||
|
|
||||||
return programImports;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static String substituteUnicode(String program) {
|
|
||||||
// check for non-ascii chars (these will be/must be in unicode format)
|
|
||||||
char p[] = program.toCharArray();
|
|
||||||
int unicodeCount = 0;
|
|
||||||
for (int i = 0; i < p.length; i++) {
|
|
||||||
if (p[i] > 127) unicodeCount++;
|
|
||||||
}
|
|
||||||
// if non-ascii chars are in there, convert to unicode escapes
|
|
||||||
if (unicodeCount != 0) {
|
|
||||||
// add unicodeCount * 5.. replacing each unicode char
|
|
||||||
// with six digit uXXXX sequence (xxxx is in hex)
|
|
||||||
// (except for nbsp chars which will be a replaced with a space)
|
|
||||||
int index = 0;
|
|
||||||
char p2[] = new char[p.length + unicodeCount*5];
|
|
||||||
for (int i = 0; i < p.length; i++) {
|
|
||||||
if (p[i] < 128) {
|
|
||||||
p2[index++] = p[i];
|
|
||||||
|
|
||||||
} else if (p[i] == 160) { // unicode for non-breaking space
|
|
||||||
p2[index++] = ' ';
|
|
||||||
|
|
||||||
} else {
|
|
||||||
int c = p[i];
|
|
||||||
p2[index++] = '\\';
|
|
||||||
p2[index++] = 'u';
|
|
||||||
char str[] = Integer.toHexString(c).toCharArray();
|
|
||||||
// add leading zeros, so that the length is 4
|
|
||||||
//for (int i = 0; i < 4 - str.length; i++) p2[index++] = '0';
|
|
||||||
for (int m = 0; m < 4 - str.length; m++) p2[index++] = '0';
|
|
||||||
System.arraycopy(str, 0, p2, index, str.length);
|
|
||||||
index += str.length;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
program = new String(p2, 0, index);
|
|
||||||
}
|
|
||||||
return program;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* preprocesses a pde file and writes out a cpp file into the specified
|
|
||||||
* OutputStream
|
|
||||||
*
|
|
||||||
* @param output
|
|
||||||
* @throws Exception
|
|
||||||
*/
|
|
||||||
public void write(OutputStream output) throws Exception {
|
|
||||||
PrintStream stream = new PrintStream(output);
|
|
||||||
writeProgram(stream, program, prototypes);
|
|
||||||
writeFooter(stream);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Write the pde program to the cpp file
|
|
||||||
protected void writeProgram(PrintStream out, String program, List<String> prototypes) {
|
|
||||||
int prototypeInsertionPoint = firstStatement(program);
|
|
||||||
|
|
||||||
out.print(program.substring(0, prototypeInsertionPoint));
|
|
||||||
out.print("#include \"Arduino.h\"\n");
|
|
||||||
|
|
||||||
// print user defined prototypes
|
|
||||||
for (int i = 0; i < prototypes.size(); i++) {
|
|
||||||
out.print(prototypes.get(i) + "\n");
|
|
||||||
}
|
|
||||||
String[] lines = program.substring(0, prototypeInsertionPoint).split("\n", -1);
|
|
||||||
out.println("#line " + (lines.length - 1));
|
|
||||||
out.print(program.substring(prototypeInsertionPoint));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Write any necessary closing text.
|
|
||||||
*
|
|
||||||
* @param out PrintStream to write it to.
|
|
||||||
*/
|
|
||||||
protected void writeFooter(PrintStream out) throws java.lang.Exception {}
|
|
||||||
|
|
||||||
|
|
||||||
public List<String> getExtraImports() {
|
|
||||||
return programImports;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the index of the first character that's not whitespace, a comment
|
|
||||||
* or a pre-processor directive.
|
|
||||||
*/
|
|
||||||
public int firstStatement(String in) {
|
|
||||||
// whitespace
|
|
||||||
String p = "\\s+";
|
|
||||||
|
|
||||||
// multi-line and single-line comment
|
|
||||||
//p += "|" + "(//\\s*?$)|(/\\*\\s*?\\*/)";
|
|
||||||
p += "|(/\\*[^*]*(?:\\*(?!/)[^*]*)*\\*/)|(//.*?$)";
|
|
||||||
|
|
||||||
// pre-processor directive
|
|
||||||
p += "|(#(?:\\\\\\n|.)*)";
|
|
||||||
Pattern pattern = Pattern.compile(p, Pattern.MULTILINE);
|
|
||||||
|
|
||||||
Matcher matcher = pattern.matcher(in);
|
|
||||||
int i = 0;
|
|
||||||
while (matcher.find()) {
|
|
||||||
if (matcher.start()!=i)
|
|
||||||
break;
|
|
||||||
i = matcher.end();
|
|
||||||
}
|
|
||||||
|
|
||||||
return i;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Strips comments, pre-processor directives, single- and double-quoted
|
|
||||||
* strings from a string.
|
|
||||||
* @param in the String to strip
|
|
||||||
* @return the stripped String
|
|
||||||
*/
|
|
||||||
public String strip(String in) {
|
|
||||||
// XXX: doesn't properly handle special single-quoted characters
|
|
||||||
// single-quoted character
|
|
||||||
String p = "('.')";
|
|
||||||
|
|
||||||
p += "|('\\\\\"')";
|
|
||||||
|
|
||||||
// double-quoted string
|
|
||||||
p += "|(\"(?:[^\"\\\\]|\\\\.)*\")";
|
|
||||||
|
|
||||||
// single and multi-line comment
|
|
||||||
//p += "|" + "(//\\s*?$)|(/\\*\\s*?\\*/)";
|
|
||||||
p += "|(//.*?$)|(/\\*[^*]*(?:\\*(?!/)[^*]*)*\\*/)";
|
|
||||||
|
|
||||||
// pre-processor directive
|
|
||||||
p += "|" + "(^\\s*#.*?$)";
|
|
||||||
|
|
||||||
StringBuilder sb = new StringBuilder(in);
|
|
||||||
Pattern pattern = Pattern.compile(p, Pattern.MULTILINE | Pattern.DOTALL);
|
|
||||||
Matcher matcher = pattern.matcher(sb);
|
|
||||||
while (matcher.find()) {
|
|
||||||
String replacement = composeReplacementString(new StringBuilder(sb.subSequence(matcher.start(), matcher.end())));
|
|
||||||
sb.replace(matcher.start(), matcher.end(), replacement);
|
|
||||||
}
|
|
||||||
return sb.toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
private String composeReplacementString(StringBuilder sb) {
|
|
||||||
for (int i = 0; i < sb.length(); i++) {
|
|
||||||
if (sb.charAt(i) != '\n') {
|
|
||||||
sb.setCharAt(i, ' ');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return sb.toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Removes the contents of all top-level curly brace pairs {}.
|
|
||||||
* @param in the String to collapse
|
|
||||||
* @return the collapsed String
|
|
||||||
*/
|
|
||||||
private String collapseBraces(String in) {
|
|
||||||
StringBuffer buffer = new StringBuffer();
|
|
||||||
int nesting = 0;
|
|
||||||
int start = 0;
|
|
||||||
|
|
||||||
// XXX: need to keep newlines inside braces so we can determine the line
|
|
||||||
// number of a prototype
|
|
||||||
for (int i = 0; i < in.length(); i++) {
|
|
||||||
if (in.charAt(i) == '{') {
|
|
||||||
if (nesting == 0) {
|
|
||||||
buffer.append(in.substring(start, i + 1)); // include the '{'
|
|
||||||
}
|
|
||||||
nesting++;
|
|
||||||
}
|
|
||||||
if (in.charAt(i) == '}') {
|
|
||||||
nesting--;
|
|
||||||
if (nesting == 0) {
|
|
||||||
start = i; // include the '}'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
buffer.append(in.substring(start));
|
|
||||||
|
|
||||||
return buffer.toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
public ArrayList<String> prototypes(String in) {
|
|
||||||
in = collapseBraces(strip(in));
|
|
||||||
|
|
||||||
// XXX: doesn't handle ... varargs
|
|
||||||
// XXX: doesn't handle function pointers
|
|
||||||
Pattern prototypePattern = Pattern.compile("[\\w\\[\\]\\*]+\\s+[&\\[\\]\\*\\w\\s]+\\([&,\\[\\]\\*\\w\\s]*\\)(?=\\s*;)");
|
|
||||||
Pattern functionPattern = Pattern.compile("[\\w\\[\\]\\*]+\\s+[&\\[\\]\\*\\w\\s]+\\([&,\\[\\]\\*\\w\\s]*\\)(?=\\s*\\{)");
|
|
||||||
|
|
||||||
// Find already declared prototypes
|
|
||||||
ArrayList<String> prototypeMatches = new ArrayList<String>();
|
|
||||||
Matcher prototypeMatcher = prototypePattern.matcher(in);
|
|
||||||
while (prototypeMatcher.find())
|
|
||||||
prototypeMatches.add(prototypeMatcher.group(0) + ";");
|
|
||||||
|
|
||||||
// Find all functions and generate prototypes for them
|
|
||||||
ArrayList<String> functionMatches = new ArrayList<String>();
|
|
||||||
Matcher functionMatcher = functionPattern.matcher(in);
|
|
||||||
while (functionMatcher.find())
|
|
||||||
functionMatches.add(functionMatcher.group(0) + ";");
|
|
||||||
|
|
||||||
// Remove generated prototypes that exactly match ones found in the source file
|
|
||||||
for (int functionIndex=functionMatches.size() - 1; functionIndex >= 0; functionIndex--) {
|
|
||||||
for (int prototypeIndex=0; prototypeIndex < prototypeMatches.size(); prototypeIndex++) {
|
|
||||||
if ((functionMatches.get(functionIndex)).equals(prototypeMatches.get(prototypeIndex))) {
|
|
||||||
functionMatches.remove(functionIndex);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return functionMatches;
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean isStartOrEndOfString(char p[], int index) {
|
|
||||||
if (p[index] != '\"') {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (index == 0) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (p[index - 1] == '\\') {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (index - 2 >= 0 && p[index - 2] == '\\') {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Replace all commented portions of a given String as spaces.
|
|
||||||
* Utility function used here and in the preprocessor.
|
|
||||||
*/
|
|
||||||
public String scrubComments(String what) {
|
|
||||||
char p[] = what.toCharArray();
|
|
||||||
|
|
||||||
int index = 0;
|
|
||||||
boolean insideString = false;
|
|
||||||
while (index < p.length) {
|
|
||||||
if (isStartOrEndOfString(p, index)) {
|
|
||||||
insideString = !insideString;
|
|
||||||
}
|
|
||||||
// for any double slash comments, ignore until the end of the line
|
|
||||||
if (!insideString && (p[index] == '/') &&
|
|
||||||
(index < p.length - 1) &&
|
|
||||||
(p[index+1] == '/')) {
|
|
||||||
p[index++] = ' ';
|
|
||||||
p[index++] = ' ';
|
|
||||||
while ((index < p.length) &&
|
|
||||||
(p[index] != '\n')) {
|
|
||||||
p[index++] = ' ';
|
|
||||||
}
|
|
||||||
|
|
||||||
// check to see if this is the start of a new multiline comment.
|
|
||||||
// if it is, then make sure it's actually terminated somewhere.
|
|
||||||
} else if (!insideString && (p[index] == '/') &&
|
|
||||||
(index < p.length - 1) &&
|
|
||||||
(p[index+1] == '*')) {
|
|
||||||
p[index++] = ' ';
|
|
||||||
p[index++] = ' ';
|
|
||||||
boolean endOfRainbow = false;
|
|
||||||
while (index < p.length - 1) {
|
|
||||||
if ((p[index] == '*') && (p[index+1] == '/')) {
|
|
||||||
p[index++] = ' ';
|
|
||||||
p[index++] = ' ';
|
|
||||||
endOfRainbow = true;
|
|
||||||
break;
|
|
||||||
|
|
||||||
} else {
|
|
||||||
// continue blanking this area
|
|
||||||
if (p[index] != '\n') {
|
|
||||||
p[index] = ' ';
|
|
||||||
}
|
|
||||||
index++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!endOfRainbow) {
|
|
||||||
throw new RuntimeException(tr("Missing the */ from the end of a " +
|
|
||||||
"/* comment */"));
|
|
||||||
}
|
|
||||||
} else { // any old character, move along
|
|
||||||
index++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return new String(p);
|
|
||||||
}
|
|
||||||
}
|
|
Loading…
Reference in New Issue
Block a user