Skip to content

Commit

Permalink
Teensy 4.1 Ethernet support (MarlinFirmware#19801)
Browse files Browse the repository at this point in the history
  • Loading branch information
bilsef authored and thinkyhead committed Apr 29, 2021
1 parent 417ec13 commit 90889d1
Show file tree
Hide file tree
Showing 15 changed files with 478 additions and 11 deletions.
3 changes: 2 additions & 1 deletion Marlin/Configuration.h
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,8 @@

/**
* Select a secondary serial port on the board to use for communication with the host.
* :[-1, 0, 1, 2, 3, 4, 5, 6, 7]
* Currently Ethernet (-2) is only supported on Teensy 4.1 boards.
* :[-2, -1, 0, 1, 2, 3, 4, 5, 6, 7]
*/
//#define SERIAL_PORT_2 -1

Expand Down
7 changes: 7 additions & 0 deletions Marlin/Configuration_adv.h
Original file line number Diff line number Diff line change
Expand Up @@ -3463,6 +3463,13 @@
// Default behavior is limited to Z axis only.
#endif

/**
* Ethernet. Use M552 to enable and set the IP address.
*/
#if HAS_ETHERNET
#define MAC_ADDRESS { 0xDE, 0xAD, 0xBE, 0xEF, 0xF0, 0x0D } // A MAC address unique to your network
#endif

/**
* WiFi Support (Espressif ESP32 WiFi)
*/
Expand Down
2 changes: 2 additions & 0 deletions Marlin/src/HAL/TEENSY40_41/HAL.h
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,8 @@
#ifdef SERIAL_PORT_2
#if SERIAL_PORT_2 == -1
#define MYSERIAL1 usbSerial
#elif SERIAL_PORT_2 == -2
#define MYSERIAL1 ethernet.telnetClient
#elif WITHIN(SERIAL_PORT_2, 0, 8)
#define MYSERIAL1 MSERIAL(SERIAL_PORT_2)
#else
Expand Down
13 changes: 12 additions & 1 deletion Marlin/src/MarlinCore.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,10 @@
#include "lcd/dwin/e3v2/rotary_encoder.h"
#endif

#if HAS_ETHERNET
#include "feature/ethernet.h"
#endif

#if ENABLED(IIC_BL24CXX_EEPROM)
#include "libs/BL24CXX.h"
#endif
Expand Down Expand Up @@ -714,6 +718,9 @@ void idle(TERN_(ADVANCED_PAUSE_FEATURE, bool no_stepper_sleep/*=false*/)) {
HAL_idletask();
#endif

// Check network connection
TERN_(HAS_ETHERNET, ethernet.check());

// Handle Power-Loss Recovery
#if ENABLED(POWER_LOSS_RECOVERY) && PIN_EXISTS(POWER_LOSS)
if (printJobOngoing()) recovery.outage();
Expand Down Expand Up @@ -969,7 +976,7 @@ void setup() {
MYSERIAL0.begin(BAUDRATE);
uint32_t serial_connect_timeout = millis() + 1000UL;
while (!MYSERIAL0 && PENDING(millis(), serial_connect_timeout)) { /*nada*/ }
#if HAS_MULTI_SERIAL
#if HAS_MULTI_SERIAL && !HAS_ETHERNET
MYSERIAL1.begin(BAUDRATE);
serial_connect_timeout = millis() + 1000UL;
while (!MYSERIAL1 && PENDING(millis(), serial_connect_timeout)) { /*nada*/ }
Expand Down Expand Up @@ -1091,6 +1098,10 @@ void setup() {
SETUP_RUN(settings.first_load()); // Load data from EEPROM if available (or use defaults)
// This also updates variables in the planner, elsewhere

#if HAS_ETHERNET
SETUP_RUN(ethernet.init());
#endif

#if HAS_TOUCH_XPT2046
SETUP_RUN(touch.init());
#endif
Expand Down
9 changes: 7 additions & 2 deletions Marlin/src/core/serial.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,10 @@

#include "../inc/MarlinConfig.h"

#if HAS_ETHERNET
#include "../feature/ethernet.h"
#endif

/**
* Define debug bit-masks
*/
Expand Down Expand Up @@ -56,8 +60,9 @@ extern uint8_t marlin_debug_flags;
#define SERIAL_OUT(WHAT, V...) (void)CAT(MYSERIAL,SERIAL_CATCHALL).WHAT(V)
#else
#define SERIAL_OUT(WHAT, V...) do{ \
if (!serial_port_index || serial_port_index == SERIAL_BOTH) (void)MYSERIAL0.WHAT(V); \
if ( serial_port_index) (void)MYSERIAL1.WHAT(V); \
const bool port2_open = TERN1(HAS_ETHERNET, ethernet.have_telnet_client); \
if ( serial_port_index == 0 || serial_port_index == SERIAL_BOTH) (void)MYSERIAL0.WHAT(V); \
if ((serial_port_index == 1 || serial_port_index == SERIAL_BOTH) && port2_open) (void)MYSERIAL1.WHAT(V); \
}while(0)
#endif

Expand Down
175 changes: 175 additions & 0 deletions Marlin/src/feature/ethernet.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,175 @@
/**
* Marlin 3D Printer Firmware
* Copyright (c) 2020 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
*
* Based on Sprinter and grbl.
* Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
*
* 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 3 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, see <https://www.gnu.org/licenses/>.
*
*/

#include "../inc/MarlinConfigPre.h"

#if HAS_ETHERNET

#include "ethernet.h"
#include "../core/serial.h"

#define DEBUG_OUT ENABLED(DEBUG_ETHERNET)
#include "../core/debug_out.h"

bool MarlinEthernet::hardware_enabled, // = false
MarlinEthernet::have_telnet_client; // = false

IPAddress MarlinEthernet::ip,
MarlinEthernet::myDns,
MarlinEthernet::gateway,
MarlinEthernet::subnet;

EthernetClient MarlinEthernet::telnetClient; // connected client

MarlinEthernet ethernet;

EthernetServer server(23); // telnet server

enum linkStates { UNLINKED, LINKING, LINKED, CONNECTING, CONNECTED, NO_HARDWARE } linkState;

#ifdef __IMXRT1062__

static void teensyMAC(uint8_t * const mac) {
const uint32_t m1 = HW_OCOTP_MAC1, m2 = HW_OCOTP_MAC0;
mac[0] = m1 >> 8;
mac[1] = m1 >> 0;
mac[2] = m2 >> 24;
mac[3] = m2 >> 16;
mac[4] = m2 >> 8;
mac[5] = m2 >> 0;
}

#else

byte mac[] = MAC_ADDRESS;

#endif

void ethernet_cable_error() { SERIAL_ERROR_MSG("Ethernet cable is not connected."); }

void MarlinEthernet::init() {
if (!hardware_enabled) return;

SERIAL_ECHO_MSG("Starting network...");

// Init the Ethernet device
#ifdef __IMXRT1062__
uint8_t mac[6];
teensyMAC(mac);
#endif

if (!ip) {
Ethernet.begin(mac); // use DHCP
}
else {
if (!gateway) {
gateway = ip;
gateway[3] = 1;
myDns = gateway;
subnet = IPAddress(255,255,255,0);
}
if (!myDns) myDns = gateway;
if (!subnet) subnet = IPAddress(255,255,255,0);
Ethernet.begin(mac, ip, myDns, gateway, subnet);
}

// Check for Ethernet hardware present
if (Ethernet.hardwareStatus() == EthernetNoHardware) {
SERIAL_ERROR_MSG("No Ethernet hardware found.");
linkState = NO_HARDWARE;
return;
}

linkState = UNLINKED;

if (Ethernet.linkStatus() == LinkOFF)
ethernet_cable_error();
}

void MarlinEthernet::check() {
if (!hardware_enabled) return;

switch (linkState) {
case NO_HARDWARE:
break;

case UNLINKED:
if (Ethernet.linkStatus() == LinkOFF) break;

SERIAL_ECHOLNPGM("Ethernet cable connected");
server.begin();
linkState = LINKING;
break;

case LINKING:
if (!Ethernet.localIP()) break;

SERIAL_ECHOPGM("Successfully started telnet server with IP ");
MYSERIAL0.println(Ethernet.localIP());

linkState = LINKED;
break;

case LINKED:
if (Ethernet.linkStatus() == LinkOFF) {
ethernet_cable_error();
linkState = UNLINKED;
break;
}
telnetClient = server.accept();
if (telnetClient) linkState = CONNECTING;
break;

case CONNECTING:
telnetClient.println("Marlin " SHORT_BUILD_VERSION);
#if defined(STRING_DISTRIBUTION_DATE) && defined(STRING_CONFIG_H_AUTHOR)
telnetClient.println(
" Last Updated: " STRING_DISTRIBUTION_DATE
" | Author: " STRING_CONFIG_H_AUTHOR
);
#endif
telnetClient.println("Compiled: " __DATE__);

SERIAL_ECHOLNPGM("Client connected");
have_telnet_client = true;
linkState = CONNECTED;
break;

case CONNECTED:
if (telnetClient && !telnetClient.connected()) {
SERIAL_ECHOLNPGM("Client disconnected");
telnetClient.stop();
have_telnet_client = false;
linkState = LINKED;
}
if (Ethernet.linkStatus() == LinkOFF) {
ethernet_cable_error();
if (telnetClient) telnetClient.stop();
linkState = UNLINKED;
}
break;

default: break;
}
}

#endif // HAS_ETHERNET
39 changes: 39 additions & 0 deletions Marlin/src/feature/ethernet.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
/**
* Marlin 3D Printer Firmware
* Copyright (c) 2020 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
*
* Based on Sprinter and grbl.
* Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
*
* 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 3 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, see <https://www.gnu.org/licenses/>.
*
*/
#pragma once

#ifdef __IMXRT1062__
#include <NativeEthernet.h>
#endif

// Teensy 4.1 uses internal MAC Address

class MarlinEthernet {
public:
static bool hardware_enabled, have_telnet_client;
static IPAddress ip, myDns, gateway, subnet;
static EthernetClient telnetClient;
static void init();
static void check();
};

extern MarlinEthernet ethernet;
Loading

0 comments on commit 90889d1

Please sign in to comment.