From 28fb162779880f9df68480fe2dee01fd27cfb4be Mon Sep 17 00:00:00 2001 From: Barry de Graaff <4353213+barrydegraaff@users.noreply.github.com> Date: Wed, 31 May 2023 12:38:20 +0200 Subject: [PATCH] Add feature receive Wake-On-Lan WOL on Arduino, can be used for pushing notifications from network to Arduino --- .../receiveWOLPacket/receiveWOLPacket.ino | 47 +++++++++++++++++++ src/enc28j60.cpp | 35 +++++++++++++- src/enc28j60.h | 8 ++++ 3 files changed, 89 insertions(+), 1 deletion(-) create mode 100644 examples/receiveWOLPacket/receiveWOLPacket.ino diff --git a/examples/receiveWOLPacket/receiveWOLPacket.ino b/examples/receiveWOLPacket/receiveWOLPacket.ino new file mode 100644 index 00000000..d69274b6 --- /dev/null +++ b/examples/receiveWOLPacket/receiveWOLPacket.ino @@ -0,0 +1,47 @@ +/* + Demo receiving WOL magic packets on Arduino, it can be used to send push notifications to Arduino. + rpm based linux: ether-wake 42:41:52:52:59:33 + deb based linux: etherwake -i enp1s0 42:41:52:52:59:33 (replace enp1s0 with your network card id) + +*/ + +#include + +// ethernet interface mac address, must be unique on the LAN +static byte mymac[] = { 0x42, 0x41, 0x52, 0x52, 0x59, 0x33 }; //ASCII: BARRY1 +byte Ethernet::buffer[700]; +const char hostname[] = "device.example.com"; + +static uint32_t timer; + +void setup () { + Serial.begin(115200); + // Change 'SS' to your Slave Select pin, if you arn't using the default pin + if (ether.begin(sizeof Ethernet::buffer, mymac, SS) == 0) + Serial.println(F("Failed to access Ethernet controller")); + if (!ether.dhcpSetup(hostname, true)) + { + Serial.println(F("DHCP failed")); + } + + ether.printIp("IP: ", ether.myip); + ether.printIp("GW: ", ether.gwip); + ether.printIp("DNS: ", ether.dnsip); +} + +void loop () { + ether.packetLoop(ether.packetReceive()); + + if (ether.pollWOLInterrupt()) + { + wolReceived(); + } +} + +/* Method called when a WOL magic packet is received +*/ +void wolReceived() +{ + ether.clearWOLInterrupt(); + Serial.println(F("Magic Packet received!")); +} diff --git a/src/enc28j60.cpp b/src/enc28j60.cpp index fa465756..1450091d 100644 --- a/src/enc28j60.cpp +++ b/src/enc28j60.cpp @@ -127,6 +127,22 @@ bool ENC28J60::promiscuous_enabled = false; #define EIR_WOLIF 0x04 #define EIR_TXERIF 0x02 #define EIR_RXERIF 0x01 +// ENC28J60 EWOLIE Register Bit Definitions +#define EWOLIE_UCWOLIE 0x80 +#define EWOLIE_AWOLIE 0x40 +#define EWOLIE_PMWOLIE 0x10 +#define EWOLIE_MPWOLIE 0x08 +#define EWOLIE_HTWOLIE 0x04 +#define EWOLIE_MCWOLIE 0x02 +#define EWOLIE_BCWOLIE 0x01 +// ENC28J60 EWOLIR Register Bit Definitions +#define EWOLIR_UCWOLIF 0x80 +#define EWOLIR_AWOLIF 0x40 +#define EWOLIR_PMWOLIF 0x10 +#define EWOLIR_MPWOLIF 0x08 +#define EWOLIR_HTWOLIF 0x04 +#define EWOLIR_MCWOLIF 0x02 +#define EWOLIR_BCWOLIF 0x01 // ENC28J60 ESTAT Register Bit Definitions #define ESTAT_INT 0x80 #define ESTAT_LATECOL 0x10 @@ -405,7 +421,8 @@ byte ENC28J60::initialize (uint16_t size, const byte* macaddr, byte csPin) { writeRegByte(MAADR0, macaddr[5]); writePhy(PHCON2, PHCON2_HDLDIS); SetBank(ECON1); - writeOp(ENC28J60_BIT_FIELD_SET, EIE, EIE_INTIE|EIE_PKTIE); + writeOp(ENC28J60_BIT_FIELD_SET, EIE, EIE_INTIE|EIE_PKTIE|EIE_WOLIE); + writeRegByte(EWOLIE, EWOLIE_MPWOLIE); writeOp(ENC28J60_BIT_FIELD_SET, ECON1, ECON1_RXEN); byte rev = readRegByte(EREVID); @@ -417,6 +434,22 @@ byte ENC28J60::initialize (uint16_t size, const byte* macaddr, byte csPin) { return rev; } +void ENC28J60::clearWOLInterrupt () { + writeOp(ENC28J60_BIT_FIELD_CLR, EWOLIR, EWOLIR_MPWOLIF); + writeOp(ENC28J60_BIT_FIELD_CLR, EIR, EIR_WOLIF); +} + +bool ENC28J60::pollWOLInterrupt () { + if((readRegByte(EWOLIR) & (EWOLIR_MPWOLIF)) == EWOLIR_MPWOLIF) + { + return true; + } + else + { + return false; + } +} + bool ENC28J60::isLinkUp() { return (readPhyByte(PHSTAT2) >> 2) & 1; } diff --git a/src/enc28j60.h b/src/enc28j60.h index f8716af8..a35b7500 100644 --- a/src/enc28j60.h +++ b/src/enc28j60.h @@ -59,6 +59,14 @@ class ENC28J60 { static uint8_t initialize (const uint16_t size, const uint8_t* macaddr, uint8_t csPin = 8); + /** @brief Clear magic packet WOL interrupt flag + */ + static void clearWOLInterrupt (); + + /** @brief Read the WOL interrupt flag + */ + static bool pollWOLInterrupt (); + /** @brief Check if network link is connected * @return bool True if link is up */