From 0cebedb59e6388b90b40c15d4ff5511f0a5cb09f Mon Sep 17 00:00:00 2001 From: Roger Clark Date: Mon, 6 Jun 2016 10:20:55 +1000 Subject: [PATCH] Added Etheret_STM by Vassilis (at his request, as copy of https://github.com/Serasidis/Ethernet_STM) --- STM32F1/libraries/Ethernet_STM/README.md | 110 ++++ .../AdvancedChatServer/AdvancedChatServer.ino | 116 +++++ .../BarometricPressureWebServer.ino | 248 +++++++++ .../examples/ChatServer/ChatServer.ino | 102 ++++ .../DhcpAddressPrinter/DhcpAddressPrinter.ino | 71 +++ .../DhcpChatServer/DhcpChatServer.ino | 114 +++++ .../examples/TelnetClient/TelnetClient.ino | 116 +++++ .../Twitter_Serial_GW/Twitter_Serial_GW.ino | 133 +++++ .../Twitter_SimplePost/Twitter_SimplePost.ino | 99 ++++ .../UDPSendReceiveString.ino | 141 +++++ .../examples/UdpNtpClient/UdpNtpClient.ino | 173 +++++++ .../examples/WebClient/WebClient.ino | 116 +++++ .../WebClientRepeating/WebClientRepeating.ino | 138 +++++ .../examples/WebServer/WebServer.ino | 123 +++++ .../examples/XivelyClient/XivelyClient.ino | 195 +++++++ .../XivelyClientString/XivelyClientString.ino | 183 +++++++ STM32F1/libraries/Ethernet_STM/keywords.txt | 37 ++ .../libraries/Ethernet_STM/library.properties | 9 + .../Ethernet_STM/pictures/w5100_module1.jpg | Bin 0 -> 49453 bytes .../Ethernet_STM/pictures/w5100_module2.jpg | Bin 0 -> 137924 bytes .../Ethernet_STM/pictures/w5100_shield.jpg | Bin 0 -> 178568 bytes STM32F1/libraries/Ethernet_STM/src/Dhcp.cpp | 480 ++++++++++++++++++ STM32F1/libraries/Ethernet_STM/src/Dhcp.h | 178 +++++++ STM32F1/libraries/Ethernet_STM/src/Dns.cpp | 423 +++++++++++++++ STM32F1/libraries/Ethernet_STM/src/Dns.h | 41 ++ .../Ethernet_STM/src/EthernetClient.cpp | 168 ++++++ .../Ethernet_STM/src/EthernetClient.h | 39 ++ .../Ethernet_STM/src/EthernetServer.cpp | 91 ++++ .../Ethernet_STM/src/EthernetServer.h | 22 + .../Ethernet_STM/src/EthernetUdp.cpp | 218 ++++++++ .../libraries/Ethernet_STM/src/EthernetUdp.h | 99 ++++ .../Ethernet_STM/src/Ethernet_STM.cpp | 181 +++++++ .../libraries/Ethernet_STM/src/Ethernet_STM.h | 60 +++ .../libraries/Ethernet_STM/src/Twitter.cpp | 91 ++++ STM32F1/libraries/Ethernet_STM/src/Twitter.h | 46 ++ STM32F1/libraries/Ethernet_STM/src/util.h | 13 + .../Ethernet_STM/src/utility/socket.cpp | 406 +++++++++++++++ .../Ethernet_STM/src/utility/socket.h | 42 ++ .../libraries/Ethernet_STM/src/utility/util.h | 14 + .../Ethernet_STM/src/utility/w5100.cpp | 268 ++++++++++ .../Ethernet_STM/src/utility/w5100.h | 424 ++++++++++++++++ .../Ethernet_STM/src/utility/w5200.cpp | 303 +++++++++++ .../Ethernet_STM/src/utility/w5200.h | 400 +++++++++++++++ .../Ethernet_STM/src/utility/w5500.cpp | 241 +++++++++ .../Ethernet_STM/src/utility/w5500.h | 447 ++++++++++++++++ 45 files changed, 6919 insertions(+) create mode 100644 STM32F1/libraries/Ethernet_STM/README.md create mode 100644 STM32F1/libraries/Ethernet_STM/examples/AdvancedChatServer/AdvancedChatServer.ino create mode 100644 STM32F1/libraries/Ethernet_STM/examples/BarometricPressureWebServer/BarometricPressureWebServer.ino create mode 100644 STM32F1/libraries/Ethernet_STM/examples/ChatServer/ChatServer.ino create mode 100644 STM32F1/libraries/Ethernet_STM/examples/DhcpAddressPrinter/DhcpAddressPrinter.ino create mode 100644 STM32F1/libraries/Ethernet_STM/examples/DhcpChatServer/DhcpChatServer.ino create mode 100644 STM32F1/libraries/Ethernet_STM/examples/TelnetClient/TelnetClient.ino create mode 100644 STM32F1/libraries/Ethernet_STM/examples/Twitter_Serial_GW/Twitter_Serial_GW.ino create mode 100644 STM32F1/libraries/Ethernet_STM/examples/Twitter_SimplePost/Twitter_SimplePost.ino create mode 100644 STM32F1/libraries/Ethernet_STM/examples/UDPSendReceiveString/UDPSendReceiveString.ino create mode 100644 STM32F1/libraries/Ethernet_STM/examples/UdpNtpClient/UdpNtpClient.ino create mode 100644 STM32F1/libraries/Ethernet_STM/examples/WebClient/WebClient.ino create mode 100644 STM32F1/libraries/Ethernet_STM/examples/WebClientRepeating/WebClientRepeating.ino create mode 100644 STM32F1/libraries/Ethernet_STM/examples/WebServer/WebServer.ino create mode 100644 STM32F1/libraries/Ethernet_STM/examples/XivelyClient/XivelyClient.ino create mode 100644 STM32F1/libraries/Ethernet_STM/examples/XivelyClientString/XivelyClientString.ino create mode 100644 STM32F1/libraries/Ethernet_STM/keywords.txt create mode 100644 STM32F1/libraries/Ethernet_STM/library.properties create mode 100644 STM32F1/libraries/Ethernet_STM/pictures/w5100_module1.jpg create mode 100644 STM32F1/libraries/Ethernet_STM/pictures/w5100_module2.jpg create mode 100644 STM32F1/libraries/Ethernet_STM/pictures/w5100_shield.jpg create mode 100644 STM32F1/libraries/Ethernet_STM/src/Dhcp.cpp create mode 100644 STM32F1/libraries/Ethernet_STM/src/Dhcp.h create mode 100644 STM32F1/libraries/Ethernet_STM/src/Dns.cpp create mode 100644 STM32F1/libraries/Ethernet_STM/src/Dns.h create mode 100644 STM32F1/libraries/Ethernet_STM/src/EthernetClient.cpp create mode 100644 STM32F1/libraries/Ethernet_STM/src/EthernetClient.h create mode 100644 STM32F1/libraries/Ethernet_STM/src/EthernetServer.cpp create mode 100644 STM32F1/libraries/Ethernet_STM/src/EthernetServer.h create mode 100644 STM32F1/libraries/Ethernet_STM/src/EthernetUdp.cpp create mode 100644 STM32F1/libraries/Ethernet_STM/src/EthernetUdp.h create mode 100644 STM32F1/libraries/Ethernet_STM/src/Ethernet_STM.cpp create mode 100644 STM32F1/libraries/Ethernet_STM/src/Ethernet_STM.h create mode 100644 STM32F1/libraries/Ethernet_STM/src/Twitter.cpp create mode 100644 STM32F1/libraries/Ethernet_STM/src/Twitter.h create mode 100644 STM32F1/libraries/Ethernet_STM/src/util.h create mode 100644 STM32F1/libraries/Ethernet_STM/src/utility/socket.cpp create mode 100644 STM32F1/libraries/Ethernet_STM/src/utility/socket.h create mode 100644 STM32F1/libraries/Ethernet_STM/src/utility/util.h create mode 100644 STM32F1/libraries/Ethernet_STM/src/utility/w5100.cpp create mode 100644 STM32F1/libraries/Ethernet_STM/src/utility/w5100.h create mode 100644 STM32F1/libraries/Ethernet_STM/src/utility/w5200.cpp create mode 100644 STM32F1/libraries/Ethernet_STM/src/utility/w5200.h create mode 100644 STM32F1/libraries/Ethernet_STM/src/utility/w5500.cpp create mode 100644 STM32F1/libraries/Ethernet_STM/src/utility/w5500.h diff --git a/STM32F1/libraries/Ethernet_STM/README.md b/STM32F1/libraries/Ethernet_STM/README.md new file mode 100644 index 0000000..4071bc0 --- /dev/null +++ b/STM32F1/libraries/Ethernet_STM/README.md @@ -0,0 +1,110 @@ +W5x00 ethernet library for STM32F103 micro-controllers +---- + +That library has been ported from the **WIZnet WIZ_Ethernet_Library**, to STM32F103 microcontrollers. +The library supports **W5100** and **W5500** Ethernet controllers. The source code has been modified to support the **W5200** too, but has not been tested (yet) on a real W5200 controller. + +Ported to STM32F103 on 23 Aug 2015 by **Vassilis Serasidis** + +Library installation +---- +### *Install the library globally* ### + + +* Unzip the file **Ethernet_STM-master.zip** into your Arduino IDE directory + +> arduino\libraries + +and rename the folder **Ethernet_STM-master** to **Ethernet_STM** + +In this case the library can be used from the 8-bit and 32-bit Arduino boards (UNO, Nano, DUE etc) and from STM32F1 microcontroller series (for example STM32F103). + +#### *Install the library for using it only with STM32F1 series* ### + +* Unzip the file **Ethernet_STM-master.zip** into your Arduino IDE directory + +> ...arduino\hardware\Arduino_STM32\STM32F1\libraries + +and rename the folder **Ethernet_STM-master** to **Ethernet_STM** + + +Selecting the Ethernet type controller (W5100, W5200 or W5500) +---- +For selecting among those tree chips edit the file: +`Ethernet_STM\src\utility\w5100.h` +and comment-out only the line with the chip you want to use. + + + +By default the **W5500** ethernet controller is selected. + + +``` +//#define W5100_ETHERNET_SHIELD // Arduino Ethenret Shield and Compatibles ... +//#define W5200_ETHERNET_SHIELD // WIZ820io, W5200 Ethernet Shield +#define W5500_ETHERNET_SHIELD // WIZ550io, ioShield series of WIZnet +``` +If you edit the **w5100.h** file, save it and re-compile your sketch. + +Selecting W5500 Sockets number and RAM buffer amount +---- +For selecting the Sockets number (1-8) and the RAM buffer amount (1-16 kBytes) for each Socket, edit the file: +`Ethernet_STM\src\utility\w5500.h` +and change the values you want. + +``` +Total RAM buffer is 16 kBytes for Transmitter and 16 kBytes for receiver for 1 Socket. +The Total W5500 RAM buffer is 32 kBytes (16 + 16). +If you use more Sockets then the RAM buffer must be split. +For example: if you use 2 Sockets then all socket must use upto 16 kBytes in total RAM. +So, we have: + + #define MAX_SOCK_NUM 2 // Select two Sockets. + #define RXBUF_SIZE 8 // The Receiver buffer size will be 8 kBytes + #define TXBUF_SIZE 8 // The Transmitter buffer size will be 8 kBytes + +In total we use (2 Sockets)*(8 kBytes) for transmitter + (2 Sockets)*(8 kBytes) for receiver = 32 kBytes. + +I would prefer to use only 1 Socket with 16 kBytes RAM buffer for transmitter and 16 kByte for receiver buffer. + + #define MAX_SOCK_NUM 1 // Select only one Socket + #define RXBUF_SIZE 16 // Select 16 kBytes Receiver RAM buffer + #define TXBUF_SIZE 16 // Select 16 kBytes Transmitter RAM buffer +``` + +Default settings: + +``` +#define MAX_SOCK_NUM 8 // Select the number of Sockets (1-8) +#define RXBUF_SIZE 2 // Select the Receiver buffer size (1 - 16 kBytes) +#define TXBUF_SIZE 2 // Select the Transmitter buffer size (1 - 16 kBytes) +``` +If you edit the **w5500.h** file, save it and re-compile your sketch. + +Using the Ethernet_STM library +---- +1. Choose the desired ethernet chip you want to use (W5100, W5200 or W5500) from the w5100.h file +2. include this library in your sketch + +`#include ` + +All functions / commands have the same syntax with the stock Arduino Ethernet library. + + +PIN Connections +---- +|W5x00|STM32F103| +|:------:|:-----:| +|SS|PA4| +|SCK|PA5| +|MISO|PA6| +|MOSI|PA7| + + + +**DO NOT FORGET TO ADD A RESISTOR 4k7 BETWEEN RESET AND 3.3V (OR RESET AND 5V) PINS ON ETHERNET SHIELD** + +![alt tag](http://www.serasidis.gr/images/w5100_shield_1.jpg) +![alt tag](http://www.serasidis.gr/images/w5100_module_2.jpg) +![alt tag](http://www.serasidis.gr/images/w5100_module_1.jpg) + diff --git a/STM32F1/libraries/Ethernet_STM/examples/AdvancedChatServer/AdvancedChatServer.ino b/STM32F1/libraries/Ethernet_STM/examples/AdvancedChatServer/AdvancedChatServer.ino new file mode 100644 index 0000000..a85d06c --- /dev/null +++ b/STM32F1/libraries/Ethernet_STM/examples/AdvancedChatServer/AdvancedChatServer.ino @@ -0,0 +1,116 @@ +/* + Advanced Chat Server + + A more advanced server that distributes any incoming messages + to all connected clients but the client the message comes from. + To use telnet to your device's IP address and type. + You can see the client's input in the serial monitor as well. + Using an Arduino Wiznet Ethernet shield. + + Circuit: + * Ethernet shield attached to pins 10, 11, 12, 13 + * Analog inputs attached to pins A0 through A5 (optional) + + created 18 Dec 2009 + by David A. Mellis + modified 9 Apr 2012 + by Tom Igoe + redesigned to make use of operator== 25 Nov 2013 + by Norbert Truchsess + + */ + +#include +#include + +#define PORT 23 // telnet defaults to port 23 + +// Enter a MAC address and IP address for your controller below. +// The IP address will be dependent on your local network. +// gateway and subnet are optional: +byte mac[] = { + 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED }; +IPAddress ip(192,168,1, 177); +IPAddress gateway(192,168,1, 1); +IPAddress subnet(255, 255, 255, 0); + + +EthernetServer server(PORT); + +EthernetClient clients[4]; + +void setup() { + // initialize the ethernet device + Ethernet.begin(mac, ip, gateway, subnet); + // start listening for clients + server.begin(); + // Open serial communications and wait for port to open: + Serial.begin(9600); + while (!Serial) { + ; // wait for serial port to connect. Needed for Leonardo only + } + + + + Serial.print("Chat server address: "); + for (byte thisByte = 0; thisByte < 4; thisByte++) { + // print the value of each byte of the IP address: + Serial.print(Ethernet.localIP()[thisByte], DEC); + Serial.print("."); + } + Serial.print("\nPort: "); + Serial.print(PORT); +} + +void loop() { + // wait for a new client: + EthernetClient client = server.available(); + + // when the client sends the first byte, say hello: + if (client) { + + boolean newClient = true; + for (byte i=0;i<4;i++) { + //check whether this client refers to the same socket as one of the existing instances: + if (clients[i]==client) { + newClient = false; + break; + } + } + + if (newClient) { + //check which of the existing clients can be overridden: + for (byte i=0;i<4;i++) { + if (!clients[i] && clients[i]!=client) { + clients[i] = client; + // clead out the input buffer: + client.flush(); + Serial.println("We have a new client"); + client.print("Hello, client number: "); + client.print(i); + client.println(); + break; + } + } + } + + if (client.available() > 0) { + // read the bytes incoming from the client: + char thisChar = client.read(); + // echo the bytes back to all other connected clients: + for (byte i=0;i<4;i++) { + if (clients[i] && (clients[i]!=client)) { + clients[i].write(thisChar); + } + } + // echo the bytes to the server as well: + Serial.write(thisChar); + } + } + for (byte i=0;i<4;i++) { + if (!(clients[i].connected())) { + // client.stop() invalidates the internal socket-descriptor, so next use of == will allways return false; + clients[i].stop(); + } + } +} \ No newline at end of file diff --git a/STM32F1/libraries/Ethernet_STM/examples/BarometricPressureWebServer/BarometricPressureWebServer.ino b/STM32F1/libraries/Ethernet_STM/examples/BarometricPressureWebServer/BarometricPressureWebServer.ino new file mode 100644 index 0000000..978e22d --- /dev/null +++ b/STM32F1/libraries/Ethernet_STM/examples/BarometricPressureWebServer/BarometricPressureWebServer.ino @@ -0,0 +1,248 @@ +/* + SCP1000 Barometric Pressure Sensor Display + + Serves the output of a Barometric Pressure Sensor as a web page. + Uses the SPI library. For details on the sensor, see: + http://www.sparkfun.com/commerce/product_info.php?products_id=8161 + http://www.vti.fi/en/support/obsolete_products/pressure_sensors/ + + This sketch adapted from Nathan Seidle's SCP1000 example for PIC: + http://www.sparkfun.com/datasheets/Sensors/SCP1000-Testing.zip + + Circuit: + SCP1000 sensor attached to pins 6,7, and 11 - 13: + DRDY: pin 6 + CSB: pin 7 + MOSI: pin 11 + MISO: pin 12 + SCK: pin 13 + + created 31 July 2010 + by Tom Igoe + modified 12 Aug 2013 + by Soohwan Kim + + Modified 18 Aug 2015 + by Vassilis Serasidis + + ========================================================= + Ported to STM32F103 on 18 Aug 2015 by Vassilis Serasidis + + <---- Pinout ----> + W5x00 <--> STM32F103 + SS <--> PA4 <--> BOARD_SPI1_NSS_PIN + SCK <--> PA5 <--> BOARD_SPI1_SCK_PIN + MISO <--> PA6 <--> BOARD_SPI1_MISO_PIN + MOSI <--> PA7 <--> BOARD_SPI1_MOSI_PIN + ========================================================= + + */ + +#include +// the sensor communicates using SPI, so include the library: +#include + + +// assign a MAC address for the ethernet controller. +// fill in your address here: + +#if defined(WIZ550io_WITH_MACADDRESS) // Use assigned MAC address of WIZ550io +; +#else +byte mac[] = {0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED}; +#endif + +// assign an IP address for the controller: +IPAddress ip(192,168,1,20); +IPAddress gateway(192,168,1,1); +IPAddress subnet(255, 255, 255, 0); + + +// Initialize the Ethernet server library +// with the IP address and port you want to use +// (port 80 is default for HTTP): +EthernetServer server(80); + + +//Sensor's memory register addresses: +const int PRESSURE = 0x1F; //3 most significant bits of pressure +const int PRESSURE_LSB = 0x20; //16 least significant bits of pressure +const int TEMPERATURE = 0x21; //16 bit temperature reading + +// pins used for the connection with the sensor +// the others you need are controlled by the SPI library): +const int dataReadyPin = 6; +const int chipSelectPin = 7; + +float temperature = 0.0; +long pressure = 0; +long lastReadingTime = 0; + +void setup() { + // start the SPI library: + SPI.begin(); + + // start the Ethernet connection and the server: +#if defined(WIZ550io_WITH_MACADDRESS) // Use assigned MAC address of WIZ550io + Ethernet.begin(ip); +#else + Ethernet.begin(mac, ip); +#endif + + server.begin(); + // initalize the data ready and chip select pins: + pinMode(dataReadyPin, INPUT); + pinMode(chipSelectPin, OUTPUT); + + Serial.begin(9600); + + //Configure SCP1000 for low noise configuration: + writeRegister(0x02, 0x2D); + writeRegister(0x01, 0x03); + writeRegister(0x03, 0x02); + + // give the sensor and Ethernet shield time to set up: + delay(1000); + + //Set the sensor to high resolution mode tp start readings: + writeRegister(0x03, 0x0A); + +} + +void loop() { + // check for a reading no more than once a second. + if (millis() - lastReadingTime > 1000){ + // if there's a reading ready, read it: + // don't do anything until the data ready pin is high: + if (digitalRead(dataReadyPin) == HIGH) { + getData(); + // timestamp the last time you got a reading: + lastReadingTime = millis(); + } + } + + // listen for incoming Ethernet connections: + listenForEthernetClients(); +} + + +void getData() { + Serial.println("Getting reading"); + //Read the temperature data + int tempData = readRegister(0x21, 2); + + // convert the temperature to celsius and display it: + temperature = (float)tempData / 20.0; + + //Read the pressure data highest 3 bits: + byte pressureDataHigh = readRegister(0x1F, 1); + pressureDataHigh &= 0b00000111; //you only needs bits 2 to 0 + + //Read the pressure data lower 16 bits: + unsigned int pressureDataLow = readRegister(0x20, 2); + //combine the two parts into one 19-bit number: + pressure = ((pressureDataHigh << 16) | pressureDataLow)/4; + + Serial.print("Temperature: "); + Serial.print(temperature); + Serial.println(" degrees C"); + Serial.print("Pressure: " + String(pressure)); + Serial.println(" Pa"); +} + +void listenForEthernetClients() { + // listen for incoming clients + EthernetClient client = server.available(); + if (client) { + Serial.println("Got a client"); + // an http request ends with a blank line + boolean currentLineIsBlank = true; + while (client.connected()) { + if (client.available()) { + char c = client.read(); + // if you've gotten to the end of the line (received a newline + // character) and the line is blank, the http request has ended, + // so you can send a reply + if (c == '\n' && currentLineIsBlank) { + // send a standard http response header + client.println("HTTP/1.1 200 OK"); + client.println("Content-Type: text/html"); + client.println(); + // print the current readings, in HTML format: + client.print("Temperature: "); + client.print(temperature); + client.print(" degrees C"); + client.println("
"); + client.print("Pressure: " + String(pressure)); + client.print(" Pa"); + client.println("
"); + break; + } + if (c == '\n') { + // you're starting a new line + currentLineIsBlank = true; + } + else if (c != '\r') { + // you've gotten a character on the current line + currentLineIsBlank = false; + } + } + } + // give the web browser time to receive the data + delay(1); + // close the connection: + client.stop(); + } +} + + +//Send a write command to SCP1000 +void writeRegister(byte registerName, byte registerValue) { + // SCP1000 expects the register name in the upper 6 bits + // of the byte: + registerName <<= 2; + // command (read or write) goes in the lower two bits: + registerName |= 0b00000010; //Write command + + // take the chip select low to select the device: + digitalWrite(chipSelectPin, LOW); + + SPI.transfer(registerName); //Send register location + SPI.transfer(registerValue); //Send value to record into register + + // take the chip select high to de-select: + digitalWrite(chipSelectPin, HIGH); +} + + +//Read register from the SCP1000: +unsigned int readRegister(byte registerName, int numBytes) { + byte inByte = 0; // incoming from the SPI read + unsigned int result = 0; // result to return + + // SCP1000 expects the register name in the upper 6 bits + // of the byte: + registerName <<= 2; + // command (read or write) goes in the lower two bits: + registerName &= 0b11111100; //Read command + + // take the chip select low to select the device: + digitalWrite(chipSelectPin, LOW); + // send the device the register you want to read: + int command = SPI.transfer(registerName); + // send a value of 0 to read the first byte returned: + inByte = SPI.transfer(0x00); + + result = inByte; + // if there's more than one byte returned, + // shift the first byte then get the second byte: + if (numBytes > 1){ + result = inByte << 8; + inByte = SPI.transfer(0x00); + result = result |inByte; + } + // take the chip select high to de-select: + digitalWrite(chipSelectPin, HIGH); + // return the result: + return(result); +} diff --git a/STM32F1/libraries/Ethernet_STM/examples/ChatServer/ChatServer.ino b/STM32F1/libraries/Ethernet_STM/examples/ChatServer/ChatServer.ino new file mode 100644 index 0000000..dc04d88 --- /dev/null +++ b/STM32F1/libraries/Ethernet_STM/examples/ChatServer/ChatServer.ino @@ -0,0 +1,102 @@ +/* + Chat Server + + A simple server that distributes any incoming messages to all + connected clients. To use telnet to your device's IP address and type. + You can see the client's input in the serial monitor as well. + Using an Arduino Wiznet Ethernet shield. + + Circuit: + * Ethernet shield attached to pins 10, 11, 12, 13 + * Analog inputs attached to pins A0 through A5 (optional) + + created 18 Dec 2009 + by David A. Mellis + modified 9 Apr 2012 + by Tom Igoe + modified 12 Aug 2013 + by Soohwan Kim + Modified 18 Aug 2015 + by Vassilis Serasidis + + ========================================================= + Ported to STM32F103 on 18 Aug 2015 by Vassilis Serasidis + + <---- Pinout ----> + W5x00 <--> STM32F103 + SS <--> PA4 <--> BOARD_SPI1_NSS_PIN + SCK <--> PA5 <--> BOARD_SPI1_SCK_PIN + MISO <--> PA6 <--> BOARD_SPI1_MISO_PIN + MOSI <--> PA7 <--> BOARD_SPI1_MOSI_PIN + ========================================================= + + */ + +#include +#include + +// Enter a MAC address and IP address for your controller below. +// The IP address will be dependent on your local network. +// gateway and subnet are optional: +#if defined(WIZ550io_WITH_MACADDRESS) // Use assigned MAC address of WIZ550io +; +#else +byte mac[] = {0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED}; +#endif + +IPAddress ip(192,168,1, 177); +IPAddress gateway(192,168,1, 1); +IPAddress subnet(255, 255, 255, 0); + + +// telnet defaults to port 23 +EthernetServer server(23); +boolean alreadyConnected = false; // whether or not the client was connected previously + +void setup() { + // initialize the ethernet device +#if defined(WIZ550io_WITH_MACADDRESS) + Ethernet.begin(ip, gateway, subnet); +#else + Ethernet.begin(mac, ip, gateway, subnet); +#endif + // start listening for clients + server.begin(); + // Open serial communications and wait for port to open: + Serial.begin(9600); + while (!Serial) { + ; // wait for serial port to connect. Needed for Leonardo only + } + + + Serial.print("Chat server address:"); + Serial.println(Ethernet.localIP()); +} + +void loop() { + // wait for a new client: + EthernetClient client = server.available(); + + // when the client sends the first byte, say hello: + if (client) { + if (!alreadyConnected) { + // clead out the input buffer: + client.flush(); + Serial.println("We have a new client"); + client.println("Hello, client!"); + alreadyConnected = true; + } + + if (client.available() > 0) { + // read the bytes incoming from the client: + char thisChar = client.read(); + // echo the bytes back to the client: + server.write(thisChar); + // echo the bytes to the server as well: + Serial.write(thisChar); + } + } +} + + + diff --git a/STM32F1/libraries/Ethernet_STM/examples/DhcpAddressPrinter/DhcpAddressPrinter.ino b/STM32F1/libraries/Ethernet_STM/examples/DhcpAddressPrinter/DhcpAddressPrinter.ino new file mode 100644 index 0000000..5ffab7d --- /dev/null +++ b/STM32F1/libraries/Ethernet_STM/examples/DhcpAddressPrinter/DhcpAddressPrinter.ino @@ -0,0 +1,71 @@ +/* + DHCP-based IP printer + + This sketch uses the DHCP extensions to the Ethernet library + to get an IP address via DHCP and print the address obtained. + using an Arduino Wiznet Ethernet shield. + + Circuit: + * Ethernet shield attached to pins 10, 11, 12, 13 + + created 12 April 2011 + modified 9 Apr 2012 + by Tom Igoe + modified 12 Aug 2013 + by Soohwan Kim + Modified 18 Aug 2015 + by Vassilis Serasidis + + ========================================================= + Ported to STM32F103 on 18 Aug 2015 by Vassilis Serasidis + + <---- Pinout ----> + W5x00 <--> STM32F103 + SS <--> PA4 <--> BOARD_SPI1_NSS_PIN + SCK <--> PA5 <--> BOARD_SPI1_SCK_PIN + MISO <--> PA6 <--> BOARD_SPI1_MISO_PIN + MOSI <--> PA7 <--> BOARD_SPI1_MOSI_PIN + ========================================================= + + */ + +#include +#include + +// Enter a MAC address for your controller below. +// Newer Ethernet shields have a MAC address printed on a sticker on the shield +#if defined(WIZ550io_WITH_MACADDRESS) // Use assigned MAC address of WIZ550io +; +#else +byte mac[] = {0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED}; +#endif + +IPAddress ip(192,168,1,177); + +// Initialize the Ethernet client library +// with the IP address and port of the server +// that you want to connect to (port 80 is default for HTTP): +EthernetClient client; + +void setup() { + // Open serial communications and wait for port to open: + Serial.begin(9600); + + // start the Ethernet connection: + //Ethernet.begin(mac, ip); //Static IP + Ethernet.begin(mac); //It Gets the IP from the DHCP Server + + // print your local IP address: + Serial.print("My IP address: "); + for (byte thisByte = 0; thisByte < 4; thisByte++) { + // print the value of each byte of the IP address: + Serial.print(Ethernet.localIP()[thisByte], DEC); + Serial.print("."); + } + Serial.println(); +} + +void loop() { + +} + diff --git a/STM32F1/libraries/Ethernet_STM/examples/DhcpChatServer/DhcpChatServer.ino b/STM32F1/libraries/Ethernet_STM/examples/DhcpChatServer/DhcpChatServer.ino new file mode 100644 index 0000000..64efb4f --- /dev/null +++ b/STM32F1/libraries/Ethernet_STM/examples/DhcpChatServer/DhcpChatServer.ino @@ -0,0 +1,114 @@ +/* + DHCP Chat Server + + A simple server that distributes any incoming messages to all + connected clients. To use telnet to your device's IP address and type. + You can see the client's input in the serial monitor as well. + Using an Arduino Wiznet Ethernet shield. + + THis version attempts to get an IP address using DHCP + + Circuit: + * Ethernet shield attached to pins 10, 11, 12, 13 + + Based on ChatServer example by David A. Mellis + created 21 May 2011 + modified 9 Apr 2012 + by Tom Igoe + modified 12 Aug 2013 + by Soohwan Kim + Modified 18 Aug 2015 + by Vassilis Serasidis + + ========================================================= + Ported to STM32F103 on 18 Aug 2015 by Vassilis Serasidis + + <---- Pinout ----> + W5x00 <--> STM32F103 + SS <--> PA4 <--> BOARD_SPI1_NSS_PIN + SCK <--> PA5 <--> BOARD_SPI1_SCK_PIN + MISO <--> PA6 <--> BOARD_SPI1_MISO_PIN + MOSI <--> PA7 <--> BOARD_SPI1_MOSI_PIN + ========================================================= + + */ + +#include +#include + +// Enter a MAC address and IP address for your controller below. +// The IP address will be dependent on your local network. +// gateway and subnet are optional: +#if defined(WIZ550io_WITH_MACADDRESS) // Use assigned MAC address of WIZ550io +; +#else +byte mac[] = {0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED}; +#endif +IPAddress ip(192,168,1, 177); +IPAddress gateway(192,168,1, 1); +IPAddress subnet(255, 255, 0, 0); + +// telnet defaults to port 23 +EthernetServer server(23); +boolean gotAMessage = false; // whether or not you got a message from the client yet + +void setup() { + + // Open serial communications and wait for port to open: + Serial.begin(9600); + // this check is only needed on the Leonardo: + while (!Serial) { + ; // wait for serial port to connect. Needed for Leonardo only + } + + + // start the Ethernet connection: + Serial.println("Trying to get an IP address using DHCP"); +#if defined(WIZ550io_WITH_MACADDRESS) + if (Ethernet.begin() == 0) { +#else + if (Ethernet.begin(mac) == 0) { +#endif + Serial.println("Failed to configure Ethernet using DHCP"); + // initialize the ethernet device not using DHCP: +#if defined(WIZ550io_WITH_MACADDRESS) + Ethernet.begin(ip, gateway, subnet); +#else + Ethernet.begin(mac, ip, gateway, subnet); +#endif + } + // print your local IP address: + Serial.print("My IP address: "); + ip = Ethernet.localIP(); + for (byte thisByte = 0; thisByte < 4; thisByte++) { + // print the value of each byte of the IP address: + Serial.print(ip[thisByte], DEC); + Serial.print("."); + } + Serial.println(); + // start listening for clients + server.begin(); + +} + +void loop() { + // wait for a new client: + EthernetClient client = server.available(); + + // when the client sends the first byte, say hello: + if (client) { + if (!gotAMessage) { + Serial.println("We have a new client"); + client.println("Hello, client!"); + gotAMessage = true; + } + + // read the bytes incoming from the client: + char thisChar = client.read(); + // echo the bytes back to the client: + server.write(thisChar); + // echo the bytes to the server as well: + Serial.print(thisChar); + } +} + diff --git a/STM32F1/libraries/Ethernet_STM/examples/TelnetClient/TelnetClient.ino b/STM32F1/libraries/Ethernet_STM/examples/TelnetClient/TelnetClient.ino new file mode 100644 index 0000000..b01fd45 --- /dev/null +++ b/STM32F1/libraries/Ethernet_STM/examples/TelnetClient/TelnetClient.ino @@ -0,0 +1,116 @@ +/* + Telnet client + + This sketch connects to a a telnet server (http://www.google.com) + using an Arduino Wiznet Ethernet shield. You'll need a telnet server + to test this with. + Processing's ChatServer example (part of the network library) works well, + running on port 10002. It can be found as part of the examples + in the Processing application, available at + http://processing.org/ + + Circuit: + * Ethernet shield attached to pins 10, 11, 12, 13 + + created 14 Sep 2010 + modified 9 Apr 2012 + by Tom Igoe + modified 12 Aug 2013 + by Soohwan Kim + Modified 18 Aug 2015 + by Vassilis Serasidis + + ========================================================= + Ported to STM32F103 on 18 Aug 2015 by Vassilis Serasidis + + <---- Pinout ----> + W5x00 <--> STM32F103 + SS <--> PA4 <--> BOARD_SPI1_NSS_PIN + SCK <--> PA5 <--> BOARD_SPI1_SCK_PIN + MISO <--> PA6 <--> BOARD_SPI1_MISO_PIN + MOSI <--> PA7 <--> BOARD_SPI1_MOSI_PIN + ========================================================= + + */ + +#include +#include + +// Enter a MAC address and IP address for your controller below. +// The IP address will be dependent on your local network: +#if defined(WIZ550io_WITH_MACADDRESS) // Use assigned MAC address of WIZ550io +; +#else +byte mac[] = {0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED}; +#endif + +IPAddress ip(192,168,1,177); + +// Enter the IP address of the server you're connecting to: +IPAddress server(1,1,1,1); + +// Initialize the Ethernet client library +// with the IP address and port of the server +// that you want to connect to (port 23 is default for telnet; +// if you're using Processing's ChatServer, use port 10002): +EthernetClient client; + +void setup() { + // start the Ethernet connection: +#if defined(WIZ550io_WITH_MACADDRESS) + Ethernet.begin(ip); +#else + Ethernet.begin(mac, ip); +#endif + // Open serial communications and wait for port to open: + Serial.begin(9600); + while (!Serial) { + ; // wait for serial port to connect. Needed for Leonardo only + } + + + // give the Ethernet shield a second to initialize: + delay(1000); + Serial.println("connecting..."); + + // if you get a connection, report back via serial: + if (client.connect(server, 10002)) { + Serial.println("connected"); + } + else { + // if you didn't get a connection to the server: + Serial.println("connection failed"); + } +} + +void loop() +{ + // if there are incoming bytes available + // from the server, read them and print them: + if (client.available()) { + char c = client.read(); + Serial.print(c); + } + + // as long as there are bytes in the serial queue, + // read them and send them out the socket if it's open: + while (Serial.available() > 0) { + char inChar = Serial.read(); + if (client.connected()) { + client.print(inChar); + } + } + + // if the server's disconnected, stop the client: + if (!client.connected()) { + Serial.println(); + Serial.println("disconnecting."); + client.stop(); + // do nothing: + while(true); + } +} + + + + diff --git a/STM32F1/libraries/Ethernet_STM/examples/Twitter_Serial_GW/Twitter_Serial_GW.ino b/STM32F1/libraries/Ethernet_STM/examples/Twitter_Serial_GW/Twitter_Serial_GW.ino new file mode 100644 index 0000000..32c103f --- /dev/null +++ b/STM32F1/libraries/Ethernet_STM/examples/Twitter_Serial_GW/Twitter_Serial_GW.ino @@ -0,0 +1,133 @@ +/* + Twitter Serial GW + + Sample : Serial port => Twitter gateway + Run this program on Arduino and connect via some Serial port terminal software. + Type a message and hit enter key, and it will be posted to Twitter. + Arduino IDE Serial Monitor is not usable because it doesn't seem able to send Enter key code. + + Notice + -The library uses this site as a proxy server for OAuth stuff. Your tweet may not be applied during maintenance of this site. + -Please avoid sending more than 1 request per minute not to overload the server. + -Twitter seems to reject repeated tweets with the same contenet (returns error 403). + + Reference & Lincense + URL : http://arduino-tweet.appspot.com/ + + Circuit: + * Ethernet shield attached to pins 10, 11, 12, 13 + + created 2011 + by NeoCat - (ver1.3 - Support IDE 1.0) + tested & + modified 13 Aug 2013 + by Soohwan Kim - (ver1.3 - Support IDE 1.0.5) + Modified 18 Aug 2015 + by Vassilis Serasidis + + ========================================================= + Ported to STM32F103 on 18 Aug 2015 by Vassilis Serasidis + + <---- Pinout ----> + W5x00 <--> STM32F103 + SS <--> PA4 <--> BOARD_SPI1_NSS_PIN + SCK <--> PA5 <--> BOARD_SPI1_SCK_PIN + MISO <--> PA6 <--> BOARD_SPI1_MISO_PIN + MOSI <--> PA7 <--> BOARD_SPI1_MOSI_PIN + ========================================================= + + */ + +#include // needed in Arduino 0019 or later +#include +#include "./Twitter.h" // Twitter.h in library/Ethernet folder. @diffinsight 2013-08-19 + +// The includion of EthernetDNS is not needed in Arduino IDE 1.0 or later. +// Please uncomment below in Arduino IDE 0022 or earlier. +//#include + +// Ethernet Shield Settings +#if defined(WIZ550io_WITH_MACADDRESS) // Use assigned MAC address of WIZ550io +; +#else +byte mac[] = {0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED}; +#endif + +// If you don't specify the IP address, DHCP is used(only in Arduino 1.0 or later). +// fill in an available IP address on your network here, +IPAddress ip(1,1,1,1); +IPAddress gw(1,1,1,1); +IPAddress snip(0,0,0,0); +IPAddress dnsip(0,0,0,0); + +// Your Token to Tweet (get it from http://arduino-tweet.appspot.com/) +//Twitter twitter("YOUR-TOKEN-HERE"); + + +char msg[141] = ""; +int len = 0; + +void setup() +{ + delay(1000); + // start the Ethernet connection: +#if defined(WIZ550io_WITH_MACADDRESS) + Ethernet.begin(ip, dnsip, gw,snip); +#else + Ethernet.begin(mac, ip, dnsip, gw,snip); +#endif +// or you can use DHCP for autoomatic IP address configuration. +// start the Ethernet connection: +//#if defined(WIZ550io_WITH_MACADDRESS) +// Ethernet.begin(); +//#else +// Ethernet.begin(mac); +//#endif + + + Serial.begin(9600); + Serial.print("> "); +} + +void loop() +{ + if (Serial.available() > 0) { + char recv = msg[len++] = Serial.read(); + if (recv == '\b' || recv == 127) { // Backspace + if (len > 1) { + len -= 2; + Serial.print("\b \b"); + } + } + else if (recv == '\r' || recv == '\n') { // send CR/LF to post + Serial.print("\r\n"); + len--; + msg[len] = 0; + if (len > 0) + post(); + len = 0; + Serial.print("\r\n> "); + } + else if (len > 140) + len = 140; + else + Serial.print(recv); + } +} + +void post() +{ + Serial.println("connecting ..."); + if (twitter.post(msg)) { + int status = twitter.wait(); + if (status == 200) { + Serial.println("OK."); + } else { + Serial.print("failed : code "); + Serial.println(status); + } + } else { + Serial.println("connection failed."); + } + delay(1000); +} diff --git a/STM32F1/libraries/Ethernet_STM/examples/Twitter_SimplePost/Twitter_SimplePost.ino b/STM32F1/libraries/Ethernet_STM/examples/Twitter_SimplePost/Twitter_SimplePost.ino new file mode 100644 index 0000000..6e38697 --- /dev/null +++ b/STM32F1/libraries/Ethernet_STM/examples/Twitter_SimplePost/Twitter_SimplePost.ino @@ -0,0 +1,99 @@ +/* + Twitter SimplePost + + SimplePost messages to Twitter (tweet) from Aruduino with Ethernet Shield! + + Notice + -The library uses this site as a proxy server for OAuth stuff. Your tweet may not be applied during maintenance of this site. + -Please avoid sending more than 1 request per minute not to overload the server. + -Twitter seems to reject repeated tweets with the same contenet (returns error 403). + + Reference & Lincense + URL : http://arduino-tweet.appspot.com/ + + Circuit: + * Ethernet shield attached to pins 10, 11, 12, 13 + + created 2011 + by NeoCat - (ver1.3 - Support IDE 1.0) + tested & + modified 13 Aug 2013 + by Soohwan Kim - (ver1.3 - Support IDE 1.0.5) + Modified 18 Aug 2015 + by Vassilis Serasidis + + ========================================================= + Ported to STM32F103 on 18 Aug 2015 by Vassilis Serasidis + + <---- Pinout ----> + W5x00 <--> STM32F103 + SS <--> PA4 <--> BOARD_SPI1_NSS_PIN + SCK <--> PA5 <--> BOARD_SPI1_SCK_PIN + MISO <--> PA6 <--> BOARD_SPI1_MISO_PIN + MOSI <--> PA7 <--> BOARD_SPI1_MOSI_PIN + ========================================================= + + */ + +#include // needed in Arduino 0019 or later +#include +#include "./Twitter.h" // Twitter.h in library/Ethernet folder. @diffinsight 2013-08-19 + +// The includion of EthernetDNS is not needed in Arduino IDE 1.0 or later. +// Please uncomment below in Arduino IDE 0022 or earlier. +//#include + + +// Ethernet Shield Settings +#if defined(WIZ550io_WITH_MACADDRESS) // Use assigned MAC address of WIZ550io +; +#else +byte mac[] = {0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED}; +#endif + +// If you don't specify the IP address, DHCP is used(only in Arduino 1.0 or later). +// fill in an available IP address on your network here, +IPAddress ip(1,1,1,1); +IPAddress gw(1,1,1,1); +IPAddress snip(1,1,1,1); +IPAddress dnsip(1,1,1,1); + +// Your Token to Tweet (get it from http://arduino-tweet.appspot.com/) +Twitter twitter("YOUR-TOKEN-HERE"); + +// Message to post +char msg[] = "Hello! Tweet! Tweet! Tweet! This message is written from Arduino Pro Mini!"; + +void setup() +{ + delay(1000); + // start the Ethernet connection: +#if defined(WIZ550io_WITH_MACADDRESS) + Ethernet.begin(ip, dnsip, gw,snip); +#else + Ethernet.begin(mac, ip, dnsip, gw,snip); +#endif + // or you can use DHCP for autoomatic IP address configuration. + // Ethernet.begin(mac); + Serial.begin(9600); + + Serial.println("connecting ..."); + if (twitter.post(msg)) { + // Specify &Serial to output received response to Serial. + // If no output is required, you can just omit the argument, e.g. + // int status = twitter.wait(); + int status = twitter.wait(&Serial); + if (status == 200) { + Serial.println("OK."); + } else { + Serial.print("failed : code "); + Serial.println(status); + } + } else { + Serial.println("connection failed."); + } +} + +void loop() +{ +} diff --git a/STM32F1/libraries/Ethernet_STM/examples/UDPSendReceiveString/UDPSendReceiveString.ino b/STM32F1/libraries/Ethernet_STM/examples/UDPSendReceiveString/UDPSendReceiveString.ino new file mode 100644 index 0000000..6acdb97 --- /dev/null +++ b/STM32F1/libraries/Ethernet_STM/examples/UDPSendReceiveString/UDPSendReceiveString.ino @@ -0,0 +1,141 @@ +/* + UDPSendReceive.pde: + This sketch receives UDP message strings, prints them to the serial port + and sends an "acknowledge" string back to the sender + + A Processing sketch is included at the end of file that can be used to send + and received messages for testing with a computer. + + created 21 Aug 2010 + by Michael Margolis + modified 12 Aug 2013 + by Soohwan Kim + Modified 18 Aug 2015 + by Vassilis Serasidis + + ========================================================= + Ported to STM32F103 on 18 Aug 2015 by Vassilis Serasidis + + <---- Pinout ----> + W5x00 <--> STM32F103 + SS <--> PA4 <--> BOARD_SPI1_NSS_PIN + SCK <--> PA5 <--> BOARD_SPI1_SCK_PIN + MISO <--> PA6 <--> BOARD_SPI1_MISO_PIN + MOSI <--> PA7 <--> BOARD_SPI1_MOSI_PIN + ========================================================= + + + This code is in the public domain. + */ + + +#include // needed for Arduino versions later than 0018 +#include +#include // UDP library from: bjoern@cs.stanford.edu 12/30/2008 + + +// Enter a MAC address and IP address for your controller below. +// The IP address will be dependent on your local network: +#if defined(WIZ550io_WITH_MACADDRESS) // Use assigned MAC address of WIZ550io +; +#else +byte mac[] = {0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED}; +#endif +IPAddress ip(192, 168, 1, 177); + +unsigned int localPort = 8888; // local port to listen on + +// buffers for receiving and sending data +char packetBuffer[UDP_TX_PACKET_MAX_SIZE]; //buffer to hold incoming packet, +char ReplyBuffer[] = "acknowledged"; // a string to send back + +// An EthernetUDP instance to let us send and receive packets over UDP +EthernetUDP Udp; + +void setup() { + // start the Ethernet and UDP: +#if defined(WIZ550io_WITH_MACADDRESS) + Ethernet.begin(ip); +#else + Ethernet.begin(mac,ip); +#endif + Udp.begin(localPort); + + Serial.begin(9600); +} + +void loop() { + // if there's data available, read a packet + int packetSize = Udp.parsePacket(); + if(packetSize) + { + Serial.print("Received packet of size "); + Serial.println(packetSize); + Serial.print("From "); + IPAddress remote = Udp.remoteIP(); + for (int i =0; i < 4; i++) + { + Serial.print(remote[i], DEC); + if (i < 3) + { + Serial.print("."); + } + } + Serial.print(", port "); + Serial.println(Udp.remotePort()); + + // read the packet into packetBufffer + Udp.read(packetBuffer,UDP_TX_PACKET_MAX_SIZE); + Serial.println("Contents:"); + Serial.println(packetBuffer); + + // send a reply, to the IP address and port that sent us the packet we received + Udp.beginPacket(Udp.remoteIP(), Udp.remotePort()); + Udp.write(ReplyBuffer); + Udp.endPacket(); + } + delay(10); +} + + +/* + Processing sketch to run with this example + ===================================================== + + // Processing UDP example to send and receive string data from Arduino + // press any key to send the "Hello Arduino" message + + + import hypermedia.net.*; + + UDP udp; // define the UDP object + + + void setup() { + udp = new UDP( this, 6000 ); // create a new datagram connection on port 6000 + //udp.log( true ); // <-- printout the connection activity + udp.listen( true ); // and wait for incoming message + } + + void draw() + { + } + + void keyPressed() { + String ip = "192.168.1.177"; // the remote IP address + int port = 8888; // the destination port + + udp.send("Hello World", ip, port ); // the message to send + + } + + void receive( byte[] data ) { // <-- default handler + //void receive( byte[] data, String ip, int port ) { // <-- extended handler + + for(int i=0; i < data.length; i++) + print(char(data[i])); + println(); + } + */ + + diff --git a/STM32F1/libraries/Ethernet_STM/examples/UdpNtpClient/UdpNtpClient.ino b/STM32F1/libraries/Ethernet_STM/examples/UdpNtpClient/UdpNtpClient.ino new file mode 100644 index 0000000..7e8b9e0 --- /dev/null +++ b/STM32F1/libraries/Ethernet_STM/examples/UdpNtpClient/UdpNtpClient.ino @@ -0,0 +1,173 @@ +/* + + Udp NTP Client + + Get the time from a Network Time Protocol (NTP) time server + Demonstrates use of UDP sendPacket and ReceivePacket + For more on NTP time servers and the messages needed to communicate with them, + see http://en.wikipedia.org/wiki/Network_Time_Protocol + + Warning: NTP Servers are subject to temporary failure or IP address change. + Plese check + + http://tf.nist.gov/tf-cgi/servers.cgi + + if the time server used in the example didn't work. + + created 4 Sep 2010 + by Michael Margolis + modified 9 Apr 2012 + by Tom Igoe + modified 12 Aug 2013 + by Soohwan Kim + Modified 18 Aug 2015 + by Vassilis Serasidis + + ========================================================= + Ported to STM32F103 on 18 Aug 2015 by Vassilis Serasidis + + <---- Pinout ----> + W5x00 <--> STM32F103 + SS <--> PA4 <--> BOARD_SPI1_NSS_PIN + SCK <--> PA5 <--> BOARD_SPI1_SCK_PIN + MISO <--> PA6 <--> BOARD_SPI1_MISO_PIN + MOSI <--> PA7 <--> BOARD_SPI1_MOSI_PIN + ========================================================= + + + This code is in the public domain. + + */ + +#include +#include +#include + +// Enter a MAC address for your controller below. +// Newer Ethernet shields have a MAC address printed on a sticker on the shield +#if defined(WIZ550io_WITH_MACADDRESS) // Use assigned MAC address of WIZ550io +; +#else +byte mac[] = {0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED}; +#endif + +unsigned int localPort = 8888; // local port to listen for UDP packets + +IPAddress timeServer(132, 163, 4, 101); // time-a.timefreq.bldrdoc.gov NTP server +// IPAddress timeServer(132, 163, 4, 102); // time-b.timefreq.bldrdoc.gov NTP server +// IPAddress timeServer(132, 163, 4, 103); // time-c.timefreq.bldrdoc.gov NTP server + +const int NTP_PACKET_SIZE= 48; // NTP time stamp is in the first 48 bytes of the message + +byte packetBuffer[ NTP_PACKET_SIZE]; //buffer to hold incoming and outgoing packets + +// A UDP instance to let us send and receive packets over UDP +EthernetUDP Udp; + +void setup() +{ + // Open serial communications and wait for port to open: + Serial.begin(9600); + while (!Serial) { + ; // wait for serial port to connect. Needed for Leonardo only + } + + + // start Ethernet and UDP +#if defined(WIZ550io_WITH_MACADDRESS) + if (Ethernet.begin() == 0) { +#else + if (Ethernet.begin(mac) == 0) { +#endif + Serial.println("Failed to configure Ethernet using DHCP"); + // no point in carrying on, so do nothing forevermore: + for(;;) + ; + } + Udp.begin(localPort); +} + +void loop() +{ + sendNTPpacket(timeServer); // send an NTP packet to a time server + + // wait to see if a reply is available + delay(1000); + if ( Udp.parsePacket() ) { + // We've received a packet, read the data from it + Udp.read(packetBuffer,NTP_PACKET_SIZE); // read the packet into the buffer + + //the timestamp starts at byte 40 of the received packet and is four bytes, + // or two words, long. First, esxtract the two words: + + unsigned long highWord = word(packetBuffer[40], packetBuffer[41]); + unsigned long lowWord = word(packetBuffer[42], packetBuffer[43]); + // combine the four bytes (two words) into a long integer + // this is NTP time (seconds since Jan 1 1900): + unsigned long secsSince1900 = highWord << 16 | lowWord; + Serial.print("Seconds since Jan 1 1900 = " ); + Serial.println(secsSince1900); + + // now convert NTP time into everyday time: + Serial.print("Unix time = "); + // Unix time starts on Jan 1 1970. In seconds, that's 2208988800: + const unsigned long seventyYears = 2208988800UL; + // subtract seventy years: + unsigned long epoch = secsSince1900 - seventyYears; + // print Unix time: + Serial.println(epoch); + + + // print the hour, minute and second: + Serial.print("The UTC time is "); // UTC is the time at Greenwich Meridian (GMT) + Serial.print((epoch % 86400L) / 3600); // print the hour (86400 equals secs per day) + Serial.print(':'); + if ( ((epoch % 3600) / 60) < 10 ) { + // In the first 10 minutes of each hour, we'll want a leading '0' + Serial.print('0'); + } + Serial.print((epoch % 3600) / 60); // print the minute (3600 equals secs per minute) + Serial.print(':'); + if ( (epoch % 60) < 10 ) { + // In the first 10 seconds of each minute, we'll want a leading '0' + Serial.print('0'); + } + Serial.println(epoch %60); // print the second + } + // wait ten seconds before asking for the time again + delay(10000); +} + +// send an NTP request to the time server at the given address +unsigned long sendNTPpacket(IPAddress& address) +{ + // set all bytes in the buffer to 0 + memset(packetBuffer, 0, NTP_PACKET_SIZE); + // Initialize values needed to form NTP request + // (see URL above for details on the packets) + packetBuffer[0] = 0b11100011; // LI, Version, Mode + packetBuffer[1] = 0; // Stratum, or type of clock + packetBuffer[2] = 6; // Polling Interval + packetBuffer[3] = 0xEC; // Peer Clock Precision + // 8 bytes of zero for Root Delay & Root Dispersion + packetBuffer[12] = 49; + packetBuffer[13] = 0x4E; + packetBuffer[14] = 49; + packetBuffer[15] = 52; + + // all NTP fields have been given values, now + // you can send a packet requesting a timestamp: + Udp.beginPacket(address, 123); //NTP requests are to port 123 + Udp.write(packetBuffer,NTP_PACKET_SIZE); + Udp.endPacket(); +} + + + + + + + + + + diff --git a/STM32F1/libraries/Ethernet_STM/examples/WebClient/WebClient.ino b/STM32F1/libraries/Ethernet_STM/examples/WebClient/WebClient.ino new file mode 100644 index 0000000..c5a77fe --- /dev/null +++ b/STM32F1/libraries/Ethernet_STM/examples/WebClient/WebClient.ino @@ -0,0 +1,116 @@ +/* + Web client + + This sketch connects to a website (http://www.google.com) + using an Arduino Wiznet Ethernet shield. + + Circuit: + * Ethernet shield attached to pins 10, 11, 12, 13 + + created 18 Dec 2009 + by David A. Mellis + modified 9 Apr 2012 + by Tom Igoe, based on work by Adrian McEwen + modified 12 Aug 2013 + by Soohwan Kim + Modified 18 Aug 2015 + by Vassilis Serasidis + + ========================================================= + Ported to STM32F103 on 18 Aug 2015 by Vassilis Serasidis + + <---- Pinout ----> + W5x00 <--> STM32F103 + SS <--> PA4 <--> BOARD_SPI1_NSS_PIN + SCK <--> PA5 <--> BOARD_SPI1_SCK_PIN + MISO <--> PA6 <--> BOARD_SPI1_MISO_PIN + MOSI <--> PA7 <--> BOARD_SPI1_MOSI_PIN + ========================================================= + + + */ + +#include +#include + +// Enter a MAC address for your controller below. +// Newer Ethernet shields have a MAC address printed on a sticker on the shield +#if defined(WIZ550io_WITH_MACADDRESS) // Use assigned MAC address of WIZ550io +; +#else +byte mac[] = {0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED}; +#endif +// if you don't want to use DNS (and reduce your sketch size) +// use the numeric IP instead of the name for the server: +//IPAddress server(185,25,21,130); // numeric IP for Serasidis.gr (no DNS) +char server[] = "www.serasidis.gr"; // name address for Serasidis.gr (using DNS) + +// Set the static IP address to use if the DHCP fails to assign +IPAddress ip(192,168,1,177); + +// Initialize the Ethernet client library +// with the IP address and port of the server +// that you want to connect to (port 80 is default for HTTP): +EthernetClient client; + +void setup() { + // Open serial communications and wait for port to open: + Serial.begin(9600); + while (!Serial) { + ; // wait for serial port to connect. Needed for Leonardo only + } + + // start the Ethernet connection: +#if defined(WIZ550io_WITH_MACADDRESS) + if (Ethernet.begin() == 0) { +#else + if (Ethernet.begin(mac) == 0) { +#endif + Serial.println("Failed to configure Ethernet using DHCP"); + // no point in carrying on, so do nothing forevermore: + // try to congifure using IP address instead of DHCP: +#if defined(WIZ550io_WITH_MACADDRESS) + Ethernet.begin(ip); +#else + Ethernet.begin(mac, ip); +#endif + } + // give the Ethernet shield a second to initialize: + delay(1000); + Serial.println("connecting..."); + + // if you get a connection, report back via serial: + if (client.connect(server, 80)) { + Serial.println("connected"); + // Make an HTTP request: + client.println("GET /util/time.php HTTP/1.1"); + client.println("Host: www.serasidis.gr"); + client.println("Connection: close"); + client.println(); + } + else { + // if you didn't get a connection to the server: + Serial.println("connection failed"); + } +} + +void loop() +{ + // if there are incoming bytes available + // from the server, read them and print them: + if (client.available()) { + char c = client.read(); + Serial.print(c); + } + + // if the server's disconnected, stop the client: + if (!client.connected()) { + Serial.println(); + Serial.println("disconnecting."); + client.stop(); + + // do nothing forevermore: + while(true); + } +} + diff --git a/STM32F1/libraries/Ethernet_STM/examples/WebClientRepeating/WebClientRepeating.ino b/STM32F1/libraries/Ethernet_STM/examples/WebClientRepeating/WebClientRepeating.ino new file mode 100644 index 0000000..9ee668e --- /dev/null +++ b/STM32F1/libraries/Ethernet_STM/examples/WebClientRepeating/WebClientRepeating.ino @@ -0,0 +1,138 @@ +/* + Repeating Web client + + This sketch connects to a a web server and makes a request + using a Wiznet Ethernet shield. You can use the Arduino Ethernet shield, or + the Adafruit Ethernet shield, either one will work, as long as it's got + a Wiznet Ethernet module on board. + + This example uses DNS, by assigning the Ethernet client with a MAC address, + IP address, and DNS address. + + Circuit: + * Ethernet shield attached to pins 10, 11, 12, 13 + + created 19 Apr 2012 + by Tom Igoe + modified 12 Aug 2013 + by Soohwan Kim + Modified 18 Aug 2015 + by Vassilis Serasidis + + ========================================================= + Ported to STM32F103 on 18 Aug 2015 by Vassilis Serasidis + + <---- Pinout ----> + W5x00 <--> STM32F103 + SS <--> PA4 <--> BOARD_SPI1_NSS_PIN + SCK <--> PA5 <--> BOARD_SPI1_SCK_PIN + MISO <--> PA6 <--> BOARD_SPI1_MISO_PIN + MOSI <--> PA7 <--> BOARD_SPI1_MOSI_PIN + ========================================================= + + + http://arduino.cc/en/Tutorial/WebClientRepeating + This code is in the public domain. + + */ + +#include +#include + +// assign a MAC address for the ethernet controller. +// fill in your address here: +#if defined(WIZ550io_WITH_MACADDRESS) // Use assigned MAC address of WIZ550io +; +#else +byte mac[] = {0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED}; +#endif +// fill in an available IP address on your network here, +// for manual configuration: +// If you don't specify the IP address, DHCP is used(only in Arduino 1.0 or later). +// fill in an available IP address on your network here, +IPAddress ip(1,1,1,1); +IPAddress gwip(1,1,1,1); +IPAddress snip(1,1,1,1); +IPAddress myDns(1,1,1,1); + + +// initialize the library instance: +EthernetClient client; + +char server[] = "www.arduino.cc"; + +unsigned long lastConnectionTime = 0; // last time you connected to the server, in milliseconds +boolean lastConnected = false; // state of the connection last time through the main loop +const unsigned long postingInterval = 60*1000; // delay between updates, in milliseconds + + +void setup() { + // start serial port: + Serial.begin(9600); + // give the ethernet module time to boot up: + delay(1000); + // start the Ethernet connection using a fixed IP address and DNS server: +#if defined(WIZ550io_WITH_MACADDRESS) + Ethernet.begin(ip, myDns, gwip, snip); +#else + Ethernet.begin(mac, ip, myDns, gwip, snip); +#endif + + // print the Ethernet board/shield's IP address: + Serial.print("My IP address: "); + Serial.println(Ethernet.localIP()); +} + +void loop() { + // if there's incoming data from the net connection. + // send it out the serial port. This is for debugging + // purposes only: + if (client.available()) { + char c = client.read(); + Serial.print(c); + } + + // if there's no net connection, but there was one last time + // through the loop, then stop the client: + if (!client.connected() && lastConnected) { + Serial.println(); + Serial.println("disconnecting."); + client.stop(); + } + + // if you're not connected, and ten seconds have passed since + // your last connection, then connect again and send data: + if(!client.connected() && (millis() - lastConnectionTime > postingInterval)) { + httpRequest(); + } + // store the state of the connection for next time through + // the loop: + lastConnected = client.connected(); +} + +// this method makes a HTTP connection to the server: +void httpRequest() { + // if there's a successful connection: + if (client.connect(server, 80)) { + Serial.println("connecting..."); + // send the HTTP PUT request: + client.println("GET /latest.txt HTTP/1.1"); + client.println("Host: www.arduino.cc"); + client.println("User-Agent: arduino-ethernet"); + client.println("Connection: close"); + client.println(); + + // note the time that the connection was made: + lastConnectionTime = millis(); + } + else { + // if you couldn't make a connection: + Serial.println("connection failed"); + Serial.println("disconnecting."); + client.stop(); + } +} + + + + diff --git a/STM32F1/libraries/Ethernet_STM/examples/WebServer/WebServer.ino b/STM32F1/libraries/Ethernet_STM/examples/WebServer/WebServer.ino new file mode 100644 index 0000000..42afdbc --- /dev/null +++ b/STM32F1/libraries/Ethernet_STM/examples/WebServer/WebServer.ino @@ -0,0 +1,123 @@ +/* + Web Server + + A simple web server that shows the value of the analog input pins. + using an Arduino Wiznet Ethernet shield. + + Circuit: + * Ethernet shield attached to pins 10, 11, 12, 13 + * Analog inputs attached to pins A0 through A5 (optional) + + created 18 Dec 2009 + by David A. Mellis + modified 9 Apr 2012 + by Tom Igoe + modified 12 Aug 2013 + by Soohwan Kim + Modified 18 Aug 2015 + by Vassilis Serasidis + + ========================================================= + Ported to STM32F103 on 18 Aug 2015 by Vassilis Serasidis + + <---- Pinout ----> + W5x00 <--> STM32F103 + SS <--> PA4 <--> BOARD_SPI1_NSS_PIN + SCK <--> PA5 <--> BOARD_SPI1_SCK_PIN + MISO <--> PA6 <--> BOARD_SPI1_MISO_PIN + MOSI <--> PA7 <--> BOARD_SPI1_MOSI_PIN + ========================================================= + + + */ + +#include +#include + +// Enter a MAC address and IP address for your controller below. +// The IP address will be dependent on your local network: +#if defined(WIZ550io_WITH_MACADDRESS) // Use assigned MAC address of WIZ550io +; +#else +byte mac[] = {0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED}; +#endif +IPAddress ip(192,168,1,177); + +// Initialize the Ethernet server library +// with the IP address and port you want to use +// (port 80 is default for HTTP): +EthernetServer server(80); + +void setup() { + // Open serial communications and wait for port to open: + Serial.begin(9600); + while (!Serial) { + ; // wait for serial port to connect. Needed for Leonardo only + } + + + // start the Ethernet connection and the server: +#if defined(WIZ550io_WITH_MACADDRESS) + Ethernet.begin(ip); +#else + Ethernet.begin(mac, ip); +#endif + server.begin(); + Serial.print("server is at "); + Serial.println(Ethernet.localIP()); +} + + +void loop() { + // listen for incoming clients + EthernetClient client = server.available(); + if (client) { + Serial.println("new client"); + // an http request ends with a blank line + boolean currentLineIsBlank = true; + while (client.connected()) { + if (client.available()) { + char c = client.read(); + Serial.write(c); + // if you've gotten to the end of the line (received a newline + // character) and the line is blank, the http request has ended, + // so you can send a reply + if (c == '\n' && currentLineIsBlank) { + // send a standard http response header + client.println("HTTP/1.1 200 OK"); + client.println("Content-Type: text/html"); + client.println("Connection: close"); // the connection will be closed after completion of the response + client.println("Refresh: 5"); // refresh the page automatically every 5 sec + client.println(); + client.println(""); + client.println(""); + // output the value of each analog input pin + for (int analogChannel = 0; analogChannel < 6; analogChannel++) { + int sensorReading = analogRead(analogChannel); + client.print("analog input "); + client.print(analogChannel); + client.print(" is "); + client.print(sensorReading); + client.println("
"); + } + client.println(""); + break; + } + if (c == '\n') { + // you're starting a new line + currentLineIsBlank = true; + } + else if (c != '\r') { + // you've gotten a character on the current line + currentLineIsBlank = false; + } + } + } + // give the web browser time to receive the data + delay(1); + // close the connection: + client.stop(); + Serial.println("client disonnected"); + } +} + diff --git a/STM32F1/libraries/Ethernet_STM/examples/XivelyClient/XivelyClient.ino b/STM32F1/libraries/Ethernet_STM/examples/XivelyClient/XivelyClient.ino new file mode 100644 index 0000000..d846b9b --- /dev/null +++ b/STM32F1/libraries/Ethernet_STM/examples/XivelyClient/XivelyClient.ino @@ -0,0 +1,195 @@ +/* + + Cosm sensor client + + This sketch connects an analog sensor to Cosm (http://xively.com) + using a Wiznet Ethernet shield. You can use the Arduino Ethernet shield, or + the Adafruit Ethernet shield, either one will work, as long as it's got + a Wiznet Ethernet module on board. + + This example has been updated to use version 2.0 of the cosm.com API. + To make it work, create a feed with a datastream, and give it the ID + sensor1. Or change the code below to match your feed. + + + Circuit: + * Analog sensor attached to analog in 0 + * Ethernet shield attached to pins 10, 11, 12, 13 + + created 27 July 2013 + updated 14 May 2012 + modified 12 Aug 2013 + by Soohwan Kim + Modified 18 Aug 2015 + by Vassilis Serasidis + + ========================================================= + Ported to STM32F103 on 18 Aug 2015 by Vassilis Serasidis + + <---- Pinout ----> + W5x00 <--> STM32F103 + SS <--> PA4 <--> BOARD_SPI1_NSS_PIN + SCK <--> PA5 <--> BOARD_SPI1_SCK_PIN + MISO <--> PA6 <--> BOARD_SPI1_MISO_PIN + MOSI <--> PA7 <--> BOARD_SPI1_MOSI_PIN + ========================================================= + + + thank to Tom Igoe with input from Usman Haque and Joe Saavedra + +http://arduino.cc/en/Tutorial/CosmClient + This code is in the public domain. + + */ + +#include +#include + +#define APIKEY "YOUR API KEY GOES HERE" // replace your pachube api key here +#define FEEDID 00000 // replace your feed ID +#define USERAGENT "My Project" // user agent is the project name + +// assign a MAC address for the ethernet controller. +// Newer Ethernet shields have a MAC address printed on a sticker on the shield +// fill in your address here: +#if defined(WIZ550io_WITH_MACADDRESS) // Use assigned MAC address of WIZ550io +; +#else +byte mac[] = {0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED}; +#endif + +// fill in an available IP address on your network here, +// for manual configuration: +IPAddress ip(192,168,1,177); +IPAddress gw(0,0,0,0); +IPAddress snip(0,0,0,0); +IPAddress dnsip(0,0,0,0); +// initialize the library instance: +EthernetClient client; + +// if you don't want to use DNS (and reduce your sketch size) +// use the numeric IP instead of the name for the server: +//IPAddress server(173,203,98,29); // In cases where it is not possible to use DNS, you can use the following bare-IP address alternative +char server[] = "api.xively.com"; // name address for cosm API + + +unsigned long lastConnectionTime = 0; // last time you connected to the server, in milliseconds +boolean lastConnected = false; // state of the connection last time through the main loop +const unsigned long postingInterval = 10*1000; //delay between updates to cosm.com + +void setup() { + // start serial port: + Serial.begin(9600); + + // start the Ethernet connection: +#if defined(WIZ550io_WITH_MACADDRESS) + if (Ethernet.begin() == 0) { +#else + if (Ethernet.begin(mac) == 0) { +#endif + Serial.println("Failed to configure Ethernet using DHCP"); + // DHCP failed, so use a fixed IP address: +#if defined(WIZ550io_WITH_MACADDRESS) + Ethernet.begin(ip, dnsip, gw,snip); +#else + Ethernet.begin(mac, ip, dnsip, gw,snip); +#endif + } +} + +void loop() { + // read the analog sensor: + int sensorReading = analogRead(A0); + + // if there's incoming data from the net connection. + // send it out the serial port. This is for debugging + // purposes only: + if (client.available()) { + char c = client.read(); + Serial.print(c); + } + + // if there's no net connection, but there was one last time + // through the loop, then stop the client: + if (!client.connected() && lastConnected) { + Serial.println(); + Serial.println("disconnecting."); + client.stop(); + } + + // if you're not connected, and ten seconds have passed since + // your last connection, then connect again and send data: + if(!client.connected() && (millis() - lastConnectionTime > postingInterval)) { + sendData(sensorReading); + } + // store the state of the connection for next time through + // the loop: + lastConnected = client.connected(); +} + +// this method makes a HTTP connection to the server: +void sendData(int thisData) { + // if there's a successful connection: + if (client.connect(server, 80)) { + Serial.println("connecting..."); + // send the HTTP PUT request: + client.print("PUT /v2/feeds/"); + client.print(FEEDID); + client.println(".csv HTTP/1.1"); + client.println("Host: api.cosm.com"); + client.print("X-ApiKey: "); + client.println(APIKEY); + client.print("User-Agent: "); + client.println(USERAGENT); + client.print("Content-Length: "); + + // calculate the length of the sensor reading in bytes: + // 8 bytes for "sensor1," + number of digits of the data: + int thisLength = 8 + getLength(thisData); + client.println(thisLength); + + // last pieces of the HTTP PUT request: + client.println("Content-Type: text/csv"); + client.println("Connection: close"); + client.println(); + + // here's the actual content of the PUT request: + client.print("sensor1,"); + client.println(thisData); + + } + else { + // if you couldn't make a connection: + Serial.println("connection failed"); + Serial.println(); + Serial.println("disconnecting."); + client.stop(); + } + // note the time that the connection was made or attempted: + lastConnectionTime = millis(); +} + + +// This method calculates the number of digits in the +// sensor reading. Since each digit of the ASCII decimal +// representation is a byte, the number of digits equals +// the number of bytes: + +int getLength(int someValue) { + // there's at least one byte: + int digits = 1; + // continually divide the value by ten, + // adding one to the digit count for each + // time you divide, until you're at 0: + int dividend = someValue /10; + while (dividend > 0) { + dividend = dividend /10; + digits++; + } + // return the number of digits: + return digits; +} + + + + diff --git a/STM32F1/libraries/Ethernet_STM/examples/XivelyClientString/XivelyClientString.ino b/STM32F1/libraries/Ethernet_STM/examples/XivelyClientString/XivelyClientString.ino new file mode 100644 index 0000000..d85b5e0 --- /dev/null +++ b/STM32F1/libraries/Ethernet_STM/examples/XivelyClientString/XivelyClientString.ino @@ -0,0 +1,183 @@ +/* + Xively(Cosm, Pachube) sensor client + + This sketch connects an analog sensor to Xively (http://xively.com) + using a Wiznet Ethernet shield. You can use the Arduino Ethernet shield, or + the Adafruit Ethernet shield, either one will work, as long as it's got + a Wiznet Ethernet module on board. + + This example has been updated to use the Xively.com API. + To make it work, create a feed with two datastreams, and give them the IDs + sensor1 and sensor2. Or change the code below to match your feed. + + This example uses the String library, which is part of the Arduino core from + version 0019. + + Circuit: + * Analog sensor attached to analog in 0 + * Ethernet shield attached to pins 10, 11, 12, 13 + + created 15 March 2010 + modified 9 Apr 2012 + by Tom Igoe with input from Usman Haque and Joe Saavedra + modified 8 September 2012 + by Scott Fitzgerald + modified 12 Aug 2013 + by Soohwan Kim + Modified 18 Aug 2015 + by Vassilis Serasidis + + ========================================================= + Ported to STM32F103 on 18 Aug 2015 by Vassilis Serasidis + + <---- Pinout ----> + W5x00 <--> STM32F103 + SS <--> PA4 <--> BOARD_SPI1_NSS_PIN + SCK <--> PA5 <--> BOARD_SPI1_SCK_PIN + MISO <--> PA6 <--> BOARD_SPI1_MISO_PIN + MOSI <--> PA7 <--> BOARD_SPI1_MOSI_PIN + ========================================================= + + + http://arduino.cc/en/Tutorial/PachubeClientString + This code is in the public domain. + + */ + +#include +#include + + +#define APIKEY "YOUR API KEY GOES HERE" // replace your pachube api key here +#define FEEDID 00000 // replace your feed ID +#define USERAGENT "My Project" // user agent is the project name + + +// assign a MAC address for the ethernet controller. +// fill in your address here: +#if defined(WIZ550io_WITH_MACADDRESS) // Use assigned MAC address of WIZ550io +; +#else +byte mac[] = {0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED}; +#endif + +// fill in an available IP address on your network here, +// for manual configuration: +IPAddress ip(192,168,1,177); +IPAddress gw(0,0,0,0); +IPAddress snip(0,0,0,0); +IPAddress dnsip(0,0,0,0); +// initialize the library instance: +EthernetClient client; + +// if you don't want to use DNS (and reduce your sketch size) +// use the numeric IP instead of the name for the server: +//IPAddress server(173,203,98,29); // In cases where it is not possible to use DNS, you can use the following bare-IP address alternative +char server[] = "api.xively.com"; // name address for cosm API + +unsigned long lastConnectionTime = 0; // last time you connected to the server, in milliseconds +boolean lastConnected = false; // state of the connection last time through the main loop +const unsigned long postingInterval = 10*1000; //delay between updates to xively.com + +void setup() { + // Open serial communications and wait for port to open: + Serial.begin(9600); + while (!Serial) { + ; // wait for serial port to connect. Needed for Leonardo only + } + + + // give the ethernet module time to boot up: + delay(1000); + // start the Ethernet connection: +#if defined(WIZ550io_WITH_MACADDRESS) + if (Ethernet.begin() == 0) { +#else + if (Ethernet.begin(mac) == 0) { +#endif + Serial.println("Failed to configure Ethernet using DHCP"); + // DHCP failed, so use a fixed IP address: +#if defined(WIZ550io_WITH_MACADDRESS) + Ethernet.begin(ip, dnsip, gw,snip); +#else + Ethernet.begin(mac, ip, dnsip, gw,snip); +#endif + } +} + +void loop() { + // read the analog sensor: + int sensorReading = analogRead(A0); + // convert the data to a String to send it: + + String dataString = "sensor1,"; + dataString += sensorReading; + + // you can append multiple readings to this String if your + // pachube feed is set up to handle multiple values: + int otherSensorReading = analogRead(A1); + dataString += "\nsensor2,"; + dataString += otherSensorReading; + + // if there's incoming data from the net connection. + // send it out the serial port. This is for debugging + // purposes only: + if (client.available()) { + char c = client.read(); + Serial.print(c); + } + + // if there's no net connection, but there was one last time + // through the loop, then stop the client: + if (!client.connected() && lastConnected) { + Serial.println(); + Serial.println("disconnecting."); + client.stop(); + } + + // if you're not connected, and ten seconds have passed since + // your last connection, then connect again and send data: + if(!client.connected() && (millis() - lastConnectionTime > postingInterval)) { + sendData(dataString); + } + // store the state of the connection for next time through + // the loop: + lastConnected = client.connected(); +} + +// this method makes a HTTP connection to the server: +void sendData(String thisData) { + // if there's a successful connection: + if (client.connect(server, 80)) { + Serial.println("connecting..."); + // send the HTTP PUT request: + client.print("PUT /v2/feeds/"); + client.print(FEEDID); + client.println(".csv HTTP/1.1"); + client.println("Host: api.xively.com"); + client.print("X-ApiKey: "); + client.println(APIKEY); + client.print("User-Agent: "); + client.println(USERAGENT); + client.print("Content-Length: "); + client.println(thisData.length()); + + // last pieces of the HTTP PUT request: + client.println("Content-Type: text/csv"); + client.println("Connection: close"); + client.println(); + + // here's the actual content of the PUT request: + client.println(thisData); + } + else { + // if you couldn't make a connection: + Serial.println("connection failed"); + Serial.println(); + Serial.println("disconnecting."); + client.stop(); + } + // note the time that the connection was made or attempted: + lastConnectionTime = millis(); +} + diff --git a/STM32F1/libraries/Ethernet_STM/keywords.txt b/STM32F1/libraries/Ethernet_STM/keywords.txt new file mode 100644 index 0000000..7b162a5 --- /dev/null +++ b/STM32F1/libraries/Ethernet_STM/keywords.txt @@ -0,0 +1,37 @@ +####################################### +# Syntax Coloring Map For Ethernet +####################################### + +####################################### +# Datatypes (KEYWORD1) +####################################### + +Ethernet KEYWORD1 Ethernet +EthernetClient KEYWORD1 EthernetClient +EthernetServer KEYWORD1 EthernetServer +IPAddress KEYWORD1 EthernetIPAddress + +####################################### +# Methods and Functions (KEYWORD2) +####################################### + +status KEYWORD2 +connect KEYWORD2 +write KEYWORD2 +available KEYWORD2 +read KEYWORD2 +peek KEYWORD2 +flush KEYWORD2 +stop KEYWORD2 +connected KEYWORD2 +begin KEYWORD2 +beginPacket KEYWORD2 +endPacket KEYWORD2 +parsePacket KEYWORD2 +remoteIP KEYWORD2 +remotePort KEYWORD2 + +####################################### +# Constants (LITERAL1) +####################################### + diff --git a/STM32F1/libraries/Ethernet_STM/library.properties b/STM32F1/libraries/Ethernet_STM/library.properties new file mode 100644 index 0000000..a3bd5b8 --- /dev/null +++ b/STM32F1/libraries/Ethernet_STM/library.properties @@ -0,0 +1,9 @@ +name=Ethernet_STM +version=1.0.3 +author=WIZnet :: Ported to STM32 by Vassilis Serasidis. +maintainer=WIZnet and Vassilis Serasidis (for porting to STM32) +sentence=Enables network connection (local and Internet) using the Arduino Ethernet board or shield. For all Arduino boards. +paragraph=With this library you can use the Arduino Ethernet (shield or board) to connect to Internet. The library provides both Client and server functionalities. The library permits you to connect to a local network also with DHCP and to resolve DNS. +category=Communication +url=http://arduino.cc/en/Reference/Ethernet +architectures=* \ No newline at end of file diff --git a/STM32F1/libraries/Ethernet_STM/pictures/w5100_module1.jpg b/STM32F1/libraries/Ethernet_STM/pictures/w5100_module1.jpg new file mode 100644 index 0000000000000000000000000000000000000000..70b315d19c328a372ee09d58a725769b74e0280d GIT binary patch literal 49453 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

Kxkt#xfLWHR3fN2S& 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 literal 0 HcmV?d00001 diff --git a/STM32F1/libraries/Ethernet_STM/pictures/w5100_module2.jpg b/STM32F1/libraries/Ethernet_STM/pictures/w5100_module2.jpg new file mode 100644 index 0000000000000000000000000000000000000000..1b8283e917262e05d6bd5cfc6f10814185acc797 GIT binary patch literal 137924 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 z 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 C4uJXq literal 0 HcmV?d00001 diff --git a/STM32F1/libraries/Ethernet_STM/pictures/w5100_shield.jpg b/STM32F1/libraries/Ethernet_STM/pictures/w5100_shield.jpg new file mode 100644 index 0000000000000000000000000000000000000000..46fc0061932f6548bf1ce84f5888baa35f80c9eb GIT binary patch literal 178568 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�#w zqER{1BI@i|;-|L!rlBf*X?nDS-QtT6F{8c}<JC7*%QC7t<4o=ThXpL+f&G zh&s?E7-BWvPI%2<-5+`2r|=i*B`VTIVU+VvXB<7aC-p4EYv}qo`!vP)=c_CWFFOY3 z{-Lrm3tgL6BSEzwOVzZE%^#CHukRXa7pYAShx(?BMDoG zzNRH+G_%yPt^rlS!%Nb`>g$58TIzdIh_Qf+Y?%q=u8^1$?MXZl8p3nKMueQ~yd|o- zZSSuh{9hZ<2(B3p`|BzZ+r&k49xTpj{k@v0c@+BbRwxmn@gDII_aikScn&2H>X&a6epB5&4(SK9|Zf>WVwwdDp(5NlBwIMUUnVjLoj?;Mo>-keAhK!7g>t*xx zEk%W=a^?!vRQ9ZDkpp;wXkDtvCwgT@OA+-s896T9yX8P>gY9ULxZK&jHn)Xv64K9* zUFE5``R9r%o=zX{V~qL-3p|>aNnt%T<22hAtrYY9A7iBjtrttSxbY>;RjNC4aBiOO z*}n{wN7c@k@?>t)PiLYo=s=XuWx@;uyGrO6Volyf^H4C@tPY=LHhpyt57KsXzDCc?|&$;*J&p86#lLAxJsfbhO z?9N=SfBwQ15rl)dx|NnA3Fbk0%d$NM9xf9ireiuRb@mUh#^t_iEAE1JV0iKND7SJo zMgsL1*qhpPxVJlp@kC$PG`?pw7c?(_{5s)L>+>gmDjqcO%D6vg`jv4AMo)tfFXP42J04_C6(CWm5Trq^GP(AZZcqQehvlLee({xqd_kB}0` zro84iU|qyvSFN%lT@jxE35?(O7162`ssWr+wO8sleOxsom}KYmotbpUuU_qUyXouf zj2fK4cAh%qwXFYi@HftMZ-gc;45r;So#%YgEl5MHVI=HmIX!X9FQo=e&(TU(4_pw%~QcD(lADm?G<=51i^UfB-n1|8zTOB*VhdUNi(*@Y3%i-0Q?UTSV z2#DvWvuKPYb!F3MkMVYmfnzE)TfO;J7k+`7{FI%6m;3vzm;#Q1vauX)OVXGQ&t4|| z-ZW(&=K!DWbDN0WqWy?`s5bF5W4#h}^B9lrX4UVhTpd`{K%&T_1Wokr3#82tr5=>W zliX)kWVwh`0raZZi8X{caYapE<`XAlxW(9i<#toy6mBx-8L!g4%PPW_nRe%S;8zP^q}N>;b-D#B8P7eG&eYljB}!N1EAwEac6!O5ij{k|K!cm< z9IS4f9y+2+UtY5bR}|r8{XtcBJ&K_Ct1#hKTmcv%a(B@FQwdwzby%?c&v(dmmW-~= zsxXBo{gFut1uFx$)E-4I2QkaSd~{hfp!!D}NV65zr_bHZ zS{H?87*lzex5IeDCw(zv(bg@660!@GX4hu5%Y6U-I6HawJXi!@;QgVD2+$N?aj53b z5z{G%`dAMkJWruISSKK}17}dg@d>W3@O(cKC!df0 zM%dS9(wu-;x9OO*JGgxAwLAS#+K>EAa?@&FgZumfzr|mSe%F2fB5?uDFmD)#SC=T; zcUt?fj%XF^Yj$0n`rWKupT-=_G~#5mmBlx1afLH&8_+Jn(v+ zZmF3X)~(%Bc@KbVV3REIyt(aR?UkQITXe=BmM&>1G^Cr|cb#iBD=jT%FIHP^7$22#zr5ivdnJFf8E8RL~}VPrjHfa($A>q$n8 z6Iz209_R|)=6nr~=T|?P^d_N-wO?x@cB+)R&%?at2Vmi%wvN(a_0#j3$uw2k?~Z>a zCxy5x&CG-_5-&25*vYL~rd!yS=ad}x3JjFhD~iS;Tg0WpKVESBs64eg=_pkrx@=!x z_wNI|5&00Z{4|?4sJQTR{bvUxqmrSx_;E&gq9{t?z1Sm?X5do z|9>PYpV`qBLd!_EyL+6VeV0k}NPv9oyhjg8ICO|Zob z9@tu+r&450cM7xZ6F#=ws=IPKQi(CZ>#dQl>VNPfE|tX{>}%pAib)3Vh5G&3gj2nAM2bnB! zHaFLrTx|&M6sn8qW+!@zxRgV%58W<6eo9Cuvs3!421$PWT>_MeCjyx67`Naq zaP*hUJ#5NRULn*A_^-?|KRF$N_l`Zaxdbt2ZIyou)`svG16N7y`pt(s zi=5?EDoeW=g$Fao+5`eDQN@4dklsltC8N~EhGG=sIBPLIJYi6i;HFKw6|LG4sqk1w zda3Hf8^?PXW0x|rN&uj;jv~pEiOOS_;l`KHO@A_p#sfT;#bx^$QT6!x+K)(7v?A)K zNG>`*IX4EsYGd3d0NtYVsCklD0*@xE>@h>+2VAqnRsJV8xc^NpR{boT*ejT{#fRWH z@9%9>NiPlZiHuz;bG77=hJF{G?KGr_`c=B>Vw`Dx>bX9Lnoer1Sw2u{vG-_jSsJe4 z_x^~fNI9r!Tuf<9h%{o{v!d$m2YeUGuUERJ13{L{Ju>_m4{VFqnCT+Y9yESG9b&rWjq zf#fVxD>D&!}fg$&BX}8ilYYbtaqJ3&4{@_HM zONABW0;HKYY^Zy7DMP)A;Bm<(W`BCrMrkRy1o1mrvWV+U*Q}BWTV7?15VpYhBhFjA|PVsA|(c0rRE}U8b*S2~>-rjVkv#WOMdZt;_X?tlh<|!UmKrq}?&Kk+xr@ z{3*uELG+k5LENEArS7J@e5xmgUHuTFamD|m&7T;plE96ZOW74fdpL?b=`i3?lS1) z04A1Mx+Xl1EE*UoSj4oSLi)ics-WHw=JMQ08ID)GYdvHk`*RpJcgi$if|d{Z4%PcF zhvpBv*J$Zb_!#4NO>-ahsjalmB z)iUCp%!txMAiawz8=4mw^>|CKslgj{K9O&hke`%`tjD58-bXc1+x!17VWzgfS4>w8zI^nj& zhhZVBGy5}Ko$8T^_&gijX1E)ex=Sg!yCNqSEQYg;(Oj z2L?!VILfxAV%NeQFhN*nz2ORK!?t(CS@s0;)HY#7%K@pWJgHUwc42zA66fqfoQhk)wUS60O{(1Hq3i%7{yW{)%~u}*~^a?j_kpY3@3 z4ZC2>i+(U*;u<-~`>}x8&6{8ENk~>mNJwZ%*4lnux3tmvIj&L(~1b zok*AC^}1)2l^+aVRQ8M#upT|an}G5Eq3pch+5W%(ualxw)gIAWwQFzbLQz$F1Zizj z)LxOaReKdhYo)E)BegfRS5do75Q$YgF@wnK`+Q&Dzu@yje#>HbOg!n2(7WI12Uy7biP>gs0S{;7|* zww=S#LE|8`&AbaUwQXQ+m%7#@gRK_|uNVueY8`o(UnCq}w#Y#;C<4PKyoUI*L^XGI zH%ebZCHMTpaV!o zsMq?J`a+1py}x1lOh>up)4NDNG_<>9M>kqr7wXaMzuPfSMo9$o7)(iRN&5#hrnHs> z>3K(VGu=u#RM}i;DbczKw-}Ess4T&sKg61~VEiFLNs1w{Kh<9&n{^kq?U>^=>kc~#OKOSx3rqa1 z2&91g(v$Jv-c37wn1Lt9b1g}$*w)xUu9ppVl@+;vehO;vlFS^=QE>Mqy4^zW>+>F2 z01IWN&`8Q=<`uhx?}-p&o+fOZd26Y3qgogLl_cN&x}YVyX!?5=>6Npv?f}?tm7Py( zRb?~DqiuHUB%t*B{ve5?J4@fKxGKa_ZZ1|a=rZMZWI{w9%|88Mh2yg<X7-7$}a{@FrZxJw)E$nQK^OOd>Y z^mIe8kO1gnK>9DW(T{l!L%-;R?PBJhXpDn8ub}iATU!AONAGV_LKqEjbKsQJ$zPlgF|3D> z@b~4tLE{8x(Xe@Sw@S=kT>igf%}UU>Dsr;3i5=_sao{X+U+Yf95iNQCYJ-GKH!_~t zV~8^bAM5PGrz+}oH7x1e!;blghP;-)!7+P-B15mDH4nOdW72eXfN?cOcNc3Hd+D8 z1VI0~E-806DL|Pv?72w&QQ0OL2JsRGf0VG$T7BD-r%dy}1RrZ2xiWNhmcSb9vFFX^ zVQKnj#KU6FC@_sZVe!C1h|#f96+ICKW`&ZyWMVAW`Etj{siJNZRuJ2HU3Yh{iFHf5 z9(8z%gxBQ*THZs&Wgs7FXQjN1K609E)vg3Ag}^bblAaieSOuQzT7q7GX$M(_3|60n zv&1`bpD|`?1=yNDF-ctEQNnm_g9EHLUC=?3euSD|pPzqRFEOmmov2H-wArX_{+C<; zUY!40vnZ38<~84(TYq8u3;;dSpWi}{0`uMjsM<|G!*lcJ|``EEn>T%yVdu>Lw}+KR#M^mkVE`uk<_Qlb>8@ zdy|kw0iOKbH@NWmS4C!wAoZqEbVyzVVlMF zDp_4O=@IJrqv@7i43bLER&Y%a&<~K6V-dN-_>!wjTaJFGvl_m(w)Sb!)T{5T;=)mL zh~8N6>A_UG6G&_xnp_X6*QMOjdzoZJHanh`IM&&|s4cn~ff}s`#2qgHs;gZpXh>9Z zPrv$vTL_!IC%UIt>-*HtvK4gR9=VNQI|fzU)Oylip;LMZ_3`4|e>A6?dw~G1lw*4g zfA(*C7wodx66*qzo~H*+J924CRw<5X1;sMokKP8z2Q?POzx$pz_=i6*OPRWPXEAQn z7M$!wDLK^#uPWMWA^pIR>^!cjbN8?5!Yd(OR}B$&$;nhE7`X(W_$MqdGU2d zT6O79lR<{6Q$;> z12#Hd>1g~PjhN}2BdS17CF2TxTjMtcb6W5D?QPvp=G0xjq_9(yRU1F%-yhOy;;u3* zm2BR3Ohz2A)`retZ>qNm-m}rBAiF+@@=x23*L}ONn1Wg{beU6GA{Nl+Z|YxVogJ-2Qema#QC%3>t5QW-kZM3A5aU}&-{BtQ6(b}KozM2%rvW_!UIH?We~cv187rL$rCWJbbyl+Uy3 zg?rwW?WbGW9RoyiYG&>5iTdCX)#_LS0zlB0)H|Zv+0Q>aMJZsxU7q(08Q&DU+|-xf zY^k$9|J<=yk_CJS^WUX@euikhy2Msn3z(<2w?>Uq=S8+|P|MpqRZ*;>E|or(xZexC z8GyRDVN(<@34d848tKqHY2WwTM%%B5%UPV%-#OnXD<~R~b)wu==Cvopap7}N%z(te z7)^L6QPU7X`rxc0IeR;iSEq8%Yqt3qYuCY6Sxj-2@3Z{5y36uV$y?jMu30Z1@LvX0 zOiK!DA>t?hHL@LAFI+Ufw(#A?o)x8ufXoWvHXNFh-8W6PodDjaiCnBgUPHQiLV8Ck z>^+Ptt6&!&vSU?KCl=&|TQg$Ru3DIs-8M`eIgF?o=k$lA>>R?{5yM7qNJ zOI+|@gj=p%gxK+A7P93G3dj>2cFCr=Dpt4~5gk`q;oo9s=N~vBt$>zVNy)h&{#598 z{u-CKDsA5Mp3+;SbQNCamhIT8o=-!wj|RA^!aKJ5&jQ`3N_nFO1OC@U z(*|`}YUD8*uwkFX(Q6}!R5*b7eb*Mu(Qkj-(|}+Z->UwlEnnfc?VNS3e5aT3gZSgH zVI7dD)H}TcbU)x6@Wiw~G#`$W_)0sq&BoCk&v|IXKyI|Xn}V!9JI9~(XmIZ}?svmw zSQZ6i%52P52A^qd1E{31+&SUCKM8p?-KIrceS4uegEHu|ncwFtzAuRNo2_i?b_m<;C`^Iqs{R zp_8>~6SIb*-XUdJSW!UJQPWx++rO}qffWLxMbNGDOOiOES}(Zc(QZ6MK;K+X0Q!f>lX-6Dt`EJ@47}S)SmcMz?OL%@$Ia&Wow)aBFh^B41b!=nBQN zV4eR;gMkY6*>A5(p{6&rVMmmL3u2tl{pRuxkCV5e&**}c7b}xtrS{g32r{=M^;kVJ z<5znkeNff;jN;3VBLeD+^$)A#PQ{)LQSxu@#UWe1>VDQ)*Bh)jz?wG{eLV|gQqA>{ z4IYY<(H%kfs z_OW0$?<*TrsVT*=2!!TYP)u#C!gpoX?htliutvfK+k0JkYWsPz&{Bpw>6^Nr0Pf@g z>_y3Me>S1XjTMQC`WgfKW{|GNb$2s!&9ccM@G`;yfm0I&oIP~`mvO&uKsLOVEa|PG z%GhrMZhFVl^6t(Pr{}y*cgovz`Q7;s_cH-wf|p>7V~^TL_U8U5it{%Nq|bcEn(e6Q z;aB6NBh~e>CiI-2oJ-o6(XQo$Gp`SC4eg<%BDaNQP-<%>1$)k%Gom6A^)mK!=1%R- zR(Y2G@X9eN2Y}8W8YQrIT%lb59?Xn)?SbXO@Y$V;h56{N%WK&IXT=Ca4ZI<70sU){IJnQyfz!qr>bL;l3EAr8=jy;>MtQ|01Ex^xPgTocS3h}gXA@-Cxncf%b%+Q^n znVCPo5CpqxXgG(>&(A}FaYS$QBTPv|-$eA8RA6p;n*J!(6TN}(pd>)N1$-=x;`VZ(Op*;O(GuN;*>t04*_B;O=U*r)W=Xc7iBKMwp2 z+(g_`#5_GYii1Gyb4 zZLnw$Fuq55*xu0iBZAvI?Ym;<^pvdn*skT!<)zAvpN-@Yd@>v5>4ZOuBekIt?POHr!imN35>fkW^PNrf(8{rnLIMeOlGw@h?-jV{UNymWdUm;)c0^Gk~8#NAY6j%^p2(lAF;^ofbN zW1SCp`Psv8*A!>c39>A6T&c3d^17V!ujyWJsAA*h#^J_9%SCK`6>$L>GZCCB;YCfLj>(g1&RJ*rv!NWT3ud>a=xYqJy?Tx>?CGurmW64jsKUc2h>~&I^ zuj}~LLo9&*Po?C5Td=4PqYD40O|oT)y_*FRq;R5mU5T>-ZcOjhR2xs<@CC_zaB|)< zJL^PI+EYt2-%$Hls_5#JuKp@F1B1=lnSYg>HcE~^bI1{V##&S$r5PrK` zje=#@jqLdBGOtICIl#v2{@2vj%dL~pFssJ@)%yZZjpP--Q$+f&ewr)s(i5#On9{ci z_v%|qHj-oWM0`T$*1QxFI(}L0Pvyi_o=VTpGwtecNyC-pBwzh*AAZ{`f(dNgjrhHU zZ41g{KTo9I4(@*#VLVBZ30JJ>ad?vZndQ5Q&xeAB7i$q4Fz#Ug>D3AQFm4mHMd$-1 zN(%lckGXNiE0rhMDT@%u(#z{%{oTRm%~fBcLW$XSRk$z_+J%dtYWJa*MkEN%6*=0T zS&)E<)EAw0C^z|=&vulh=>)6LKRO%$+sk$wJ}H-A=x73XkHKXKW7pROO=c9^Oyo7u z?>txTs2qv2uG&A*yHx9_qJA2T+fF;9SMG*J)PvbtWk|Y@$W{Nt{&`;AJMF@RS-jbioDFSHWu0xrm3;1!+h!Z zf<*tRg1a37jSI3+_rjC*l_JwogkW%yIq}(NVC7{gm62{E#K>Rm1WO zkNBo`3xUtEa}Z5KewA?z&>|A!(|RYK1bIUCEBn(OKxjPFs{l6~O1yW;hKCr_UlJ8y z`Ji_;XNI^37$w%>q81q3GEVomWSPu8wj##O#H~`&0rt-NQ%JQ`sTl1gCQDIZBDbmuoZ8qoQ5ZA?aM?DLi<*<-1)(9V^xX9ApNjqossbGH#t; z*6PqF5Fp@d9wpxJF?6s4!CS6x(v_Xue>yFM)q<50yaGg+Q{FGE3omcDA1f0GR>b= zQKu0p!Rk**YtaGVh>n}Bmlies`ZJV}j6B_C0pH7kh}*?OEL`Z#AW!p}o514XSiSBl z?wvxoV`mw?HD)e2zS|PnTGJE-k|m7FwP{)K(N&&3KCgo75q%G9JD3)N%YGi2l(N@V zH#bJHyiHu@5Ea_bS-k1<_AQj72d*6dYl$riKBPPYu`W|tcV%y}-VECb`^z4<*ZK%; zpPgE5zmu(wv*SD64*M5gaQ5n72Umv&^e@_mxP`jhE@ntDG+z3Io5NsF1Wtz5SiVO_ z(-a&390@{JH^d?o;mTwlj!4KNFh!g8%}wm`v8j6}IzW}hLNRW>btJ##MezV{g9q8K z2h@<nxYtxez2^-tL+6TysBO%E#NH-af(GrqNb1bgaWTMw=!qZdV z!E8kpq)eN$+Ab0uMQ)mWz4lIjhq^zrt~Ec_1a$7_>YF=4{tO+}R|tDj#wO-@7Ng@d zjDQ;(lH8|tNsVu%QoON^X#sZ=LSrXgaf_7p}b*2F5)0csb>64}J)Zg}!S(9DsA*C?xx~YuH zj0Q_(0FsbAlKOl(Cnx7r*~_e> zG;IIyWKpi@if3h6h*7t@k#9KQm@a=uu#Axk-?ao-c>nw*Wa#1P=2B(rtq*; z`2A#=8xESl0L=HEGb4r#G2#r*a4vFrj~(y^P6FTmKhKkoOhLAenL35iKM_mAqwzL; zn`{5kB;$z2pa@V+aspZ*nVX_V#6=&fJG6U#oZx7@Z)_xfYpIyBnaQP7pbxJlEbr7C zQguGAaJCE520VSI#HoZw*5VyMB09@nKz^j{|RCdxT5>patLt;&>Mi@ z*cnV$CQ6YM3lQYqKavt()drIn*_OfoYu8wl`8zSD-B>s7Nr9F=S&S5XdP8>%o-wv! z|I{}Jp5>D-L%D+fjjk{@@(=5e^4@NhU;3=^ZwDOS=%NDgV+s>fJwO+<-`Y$hfS68F z`$H~=-G?e#s~le5hsM`~i9SG?9>q*XZKniV_F!^u$C_nmCrF3OQ_AX%$m)(=8P1Lk zWb<-Err-2D(}Slzww}^Lb>9H>8J3OpzYQhERIn0p7;#6PrCBH-2Se!`s8plAha?mweOHkuwE1%YEk|cy5I> zH=g=?FTNiz!d5`!J9!nFfIZYKUR{T)b=&00P;vit&%53OF75F10x%5C1#sPz&jO41 z`u`dy|E-9!dodT%2aGuDp9WFsU__3-W*p_#Bm6>vH~!o~osWIT;0)XCwxC^m=i03r zdBzL-G@90LcvGM+bs0>VGlvxI$209J^P)5Lnh3WhHjqyqF1FHRpUDsOdsyvoCHX{p z^%`0v`FZnCiVuo%jSW4}B&{3C?`H1yM{)|~0Ut{l#%P}A?TV>CWz*YepPQ0@I=-M= ze{rDuv;4$2$O*qY+t+!J_T5KbVEd^CuVFdng~$(k7o(tk(LySnMGjM`vh<~mV-Iz- z^;Wld(F-bsvQ{0dMjn08M-=H+#_YrA!}}NCCw_lHt+Sudo6ECfxZ4kUO4@uZFIm>V zv~8@r&wlc`<;7C+(C50(->v?m2@RAY9qp}MhUQp#zm~0{A4v)B&8LX(lmI94$<`O z+KTkBkd_Vlj*dXYAuo4j1Bcu-$1F}`N1lww;lqdPrX~$?yf0n;ryyO~m@jqjsPXry z9UlP9Bx}tqS#pOAln`yS{L_1&Z4P`(ax7590D4zLy)SN3RmUsZ1#xyiCIdLj)1`$l zdB%YPJAb+P)m+&Qb%7B~+f2wzhs&P@H&?56*?$HxX#gC`irlH``(O#vE_z;82f9wi z5tRF7=r(XHg5miHiu*+#z-~}a;CKFvVAtNx$}2@ zIT-$U>NSkwUEjVH_7B)X4e9-HifBGE$gr8XP(?h35R;?x0h`OHe0ZjbhmyNID#L1& z;i_b#&>AP2E>qV#HbdSc)K-EyMhfz)W0EDXX8Ua7G0pa%1eOc^2+*>M;7}qi7Ttb* zoytt|AXmYe7s<7-HXDWDR_v!02k7dW4-Z6B6)i)|j9De;2}~(u7axrAyQ5n1^@Tr5 zFDx~D?x!#m6(AqJp7NL+S~rKK5iDygj#0hHunfrjCi`v`dGys+NvHIax(-8s2*d#0 zv=x3CM>NOr!X?RAf>BH!Es>(!TonHbSreeC=$N0o?)y}u=|(E3V<)@ z-Q`1k8?an&)Ol}ecBlc>8D|_8dK5*zL|VezcM!0NFoFvzD1UBK%{!9+a95~34(1ZY zo-xm~@`6|G>vAM*0m3uasgXW-(Bw3I&ZKSwZu6=YCS9iD%=$$$i>465SL9 z6Pc@<`F`+f$j5%8_R!fKUeUMRzlZIB#vW0zhn}ip_Ioz-o;BmB4?aqA1+VPZ6t&C< zSr)sS$krAT!meF$ibps?j!7M{4KrOdiaG?bueVFqO>BA9F+@!a?s+b{+jWHIegv)9 zVFp@V*&mC&;E#h$tqT=9v(VOFyJOc2)2 zzp=03&{DsAo_M0n3goLGTpUM5BA+o=xO`o zmqFzrCsA9cDSa00>ZIcyaCA*@;dU(;C^&V=2Y82Qc}Xv48LXQ%_4ql*c^kjM8i&xv zEmLXX`qLT=B#xhX0z{4&xZM&s#sZVx{uLZ;`P2;`n83wIN3f8uX?}mnVVQM3V%mt5 zW|L_Z-;Izahkg0Gf%!O__Vl#in?X3!iL)?UbN@;`Dd}s3KROm~>zE|&?>>pDG4_=4 z*k%h{ZgPfI%uj4Chl4qsI<`{EY)V(tYR)mwAh3Xnv5tp&Q5h{ z%>bXQ2{gP(mpCVA!uFYuf;s?$U(KF8)|zZ{(#3_+zu59SE&|Ef^uDqQv+KKCvP;k# z?#K(ZEh8rKt`+V`Rw?J{jGg(H23D2+e=EKL#*pUOG%WT=Zl{lOzm&u)xp&Nk(pu{w zwfV5`yDi?;RdCU42R}x89_9r1zVs>o1_Qg6oy^S7r>u@7q+X`}jdceln6bDJ3tN}= zt>hbmACyp%>HV)vT}ZS?*^v42*}K(uIrr~f4G{(H>~HrXLa6=7I@KvHnau^J8R>ke z2w3E%l~+otu7$VhhvL`Zwq2-qa9D5ssZzSD&|8ZUud7F(&dy6xb42Dw^jdkBVpEfc z`nLC@Qy$u9{3C`^0cwWI_N`N10x+vX2IJR@)pn1~;q{A+1DEe@(Sj6T4VP;e*N6{Q zKUA?)5%Nhzpk|spxmG6pmw3~{zoHBIU;P+zhVQDT<-ECPb|ELZP<%E0N?%-!u6lp) z1b9d=eB^c?S2oyRrY*!4ov-XqICKqQ>#BmH&Ru`yYnDF#pfdK#!Ygn8B$E4t^aSfdBt{JN^2n;UOnBxFp&F$59@Tt4F5;|l5m~%Rp4BKCDU(R){j*9j zUNVTc)BaXx4i$=7cp+Eb-%yXU*)vMOOa^xtRZTTuisCiccgz0mJez5IYsQ0BRacOQ zc$*ZJ(9J)$EG0K=wS#_RjF)RY81$cvF3xvgL_v{o0}|xu%R~Su2_XO=2pbxsyD=IV z#6RlRY!Ip`Nx*NPg(GY2w?Jh%NTXl}X%ChER_k606u<0UeMpW5Nz7c7`$WDR3uTOQ zd~L3-#bkauVtQp`CZ+t}pHU8f1A(8*DWjpxKyT+_JnAAvf&@DHKpqTP0@M9N2#x#4 zTTxKkQflhG^?7;>G%1ZPbH>ngzN)F&Z^7WD`Gy1}>^i@Hl5;h2HacL$;YeWfMgTkW zMW+M1UAfZzsl$q0vH&&B`(-iQwe{?=iQ>v=+G|n*D{Rm1-TQYB)^paf&bjl#6NXhF z9HxxhCR1DU|Iy@)xuCjQ01w!cdU>htS%TWl;>t{|ETlM0CvPM-nZhoJ*Ntok4wz0& zErDdf%902~!9r<9u(J`c!MkzH^v(xWYnBJ1ZyI^uoYSbHJI@l?gV**}^w@PewPkbC z!2kp_xdQp1gJ{F2gEIj(wk6!Gxn^(KqQ07bs7?1My;y^atbmhcr17O3>;m@=3=kU0uw>9Kt%~b zJT7MBM3W-7BKl`y`|ctib7vBFX2!$MKo5R~=YGg}^8~HA84~IXMj9d<>{0y&m9n1b9 zi+}U#5>$iw7sp*^s7$4YgfAJ&_hw=irzAbm2VtAJ+=h1y4DX|S`2&LorhZH=h33VB}BOB&)2=HCjoSp&&)SXBFk&n zQZ2o9PLEo4z8!#l;LauMq2BLy?o7ayzi)Cpx~eG+6~~B0++)rVAEL8xOyE6OQY2p? zsvlXAgGgT9EVjYjOWu)Gu6g&8r!FdV` z>6tZHeUYvQ;S1Tdh7yfXfSVks0Z9?zXfBFt^(orO()w;WIH7UxG{>8j{r2)lzS7=^ zH_@qAL&iWK$c{anWYazaP|UL4qlNdiRGa^G8H1}iix?q81EN8KL!8{!;^Bh zY}&MUKF~UwprnIv(8JWb{(tcellVwRS!^l5AMlXY3EclcJJA7zj*G?3{1HTTz4IKz z4R;wrY$4erE3&7dc_!)9Z@yq`O^kQ4J*uM+#p z5d;TXTgnDVtl-|o*H*OAh~@dfxs1v~R+E3}yJ3)$6XfL=>l!X%&$JHA+1$38UX}-} zdd+woultdLj}h%){w%@(~#!+jEk|75-U-c1Os0O zuN7`ooEaj1Yl)o~cPyqKwM({6P#6|**8yA5oA^oA`^1IFa}?h%+{+*i8PQKViy)WZ z`GQ;;4h_h~FUUHM9`s*RD*YtM<_w=$EAOFJ|M|P{Pc^v>$s1NbgG~}FS1+X;l%p`m zOS-*iOa%3s4=ABsWYcn{qL8B9Fi}wp-MZ`lPZ(PDgs^r;@k4c{Gp9P@=z)sh0VOZL zB6^5)c(+sEzHi?o$UBo7{O`yu%x?a*S@@lfW7 ziHM9ol=)MGe-#=XeW08HX2J}}yYrN>C-D78b8mDFpFN+9-?Q9iDTKg9fD>p5E=!Wz z;Lu{5q-f*+4Mt7spE>QV_PcPM+=ki*A1?ui_u4(;<3Kp*K5ygjJI75_H`qX zogTGFHgqSHH#o~X5kOuL^Qtu4+EDMLTbaXMi{{eqAn<7C3yKp4%PqY}%Xe6JQ*&WQ+pBsrvbQx!|=+AnYW!J5= zWKmsZnyf)ezzX&7j}Jj;BF40C6StFc@nBJ_#%j5FtH)nO_bZlT=N%ZGw66&|GODU@ zIWQLo&n}|hz9j1{dGnIlm%7xDJ%$h?x4Pkut@!oYvb&$1AW=1uU-_R-zPlhvU$`oG zDJz@G;8WO-o=1!oC_>uq5Xp1#67f%-rj=KC1y5nRr*aE}_a9fW zCaIoc!b2;+n#v0TCXpFy(y({k-O6P<=ulaAWuAR&bl{E>A`n}#1&obQc*aRg-WSM@ z1f8sAyOo&)Oe>3I${6PvZ%lQKS1RaIX`)V{~9C*F)kfNa~Zj`1&VJlV;hTH_+f4f9U-#&~ndB>rP``-7K10&q1%N z`3Z;AUdh;n=#hlLGQh>#4h9fz5GaCF=)Ud5;#5VY!=yLo+@laV{Q?KswcNP`rs?Ii zzcVk$y?u#KO1*rb468K&ZMLrM@DDW=52Y!JC${;R^z^4cFEj2eI^sQOt3XRHxNa%~ z457p@5`^#_A%eUJYrk4m*Pi*aSpk!TI)W;Rfq$FQ1wE{|f$6PE$T>v!qcIjpR(r%G zioKBZD#IlB^Nh|EVo=E2i?iJIm5bc-V!JP%8jftI-e4w zRIWT8?4qv9p)KdhBKLOup5GhUnbv)LQPj#z>+LV|x@fEQ*X#d!w}n4XKq&P}J#0@L zR7anjuCa|{DeBbTde4VIUF1}{RU&?batHrXv`ctAxo+LozV-aV|K$bcrT)QH>vkn$z(-$e>PW}kWkwu!bL(Yt zcIWL7%eQwCui>sH@xoE%d8EZV41FE<+|fxK~`_|k=O>rq-m@c~+KEqGlfw6=pN z;x4W*Nw%Cr1Z{$dUf`dbfpYFt?rP80;>M&RfY>MQ{hF!LVtF$T(_+rGs{2`n zP41Fj=j9{L-f(4x#r)X5>CmRTU1B!JtGQc;7SmGR%kX4Y2Vwn0m37!)hty37H$og4hzUP3YyR?aNk?#SC0 zcXrm%L%5jM-ZUenyd6};W0*T}%vD-Jy}OK<;k-*&`$63KN2>W*1A~Kb^zh4vxmJJu z+{H~j!$vpt6!V)8z@j5!I)&n=>%wsHnpc&88fOb4Oc)(Jw*Q_2HTlmkgi0pf8lDBtv6%t0i z6$!gzMXT!@lyvVQfKmMjr$7HHgY-frgD+8e<`(_|!UKw-Un#l31EU~6fUzgjg#5M9 zadFx6sk45h@IDVBxQ`Gh(6=tIH*$5V+~yJ{*6oT`wA|fDA8Q{7FPd5}8kr4|*d70m z24!dTlsvmQmN>h>Ff9$&^YJYH7uevd7k-`|!tp_5pU&4|AoV`o%Da>V%M6PAM5PAw z`=*+9mbS>(;M>8D?iXv{a@Kf`arJwhOH9=zMN;&iP|_>#4~l1@hy6{G zr1W!G#>?+FwJyGItarG2Rkn#f1w~l2tf7dKjYyputOOMeQ4**N^yg-N*E zG}d2}@6OkT@MLB{Kj336mM$r-*^8y=PDx5_!;Qmf<7(lO7WU$k6&RkfXIfjul;)&H zgb^{t&b1Tzm$pkwVO+z`Tc*$8)9o5!UqNN(dE}+xqk%=)lBz5bjAKZ{TH^3tL>g4J zk2B6>$aR}L!T;Em>)AD2u)3J;s2ujh1UG@Vk#b>Kp4Bb4NvQCytw)p|@BSVkdMCD; zFY$oiQQ3*!-MKP&bfN+z_jc_VyY0{Vk`g-uFT#Xt_K>xbo$_wHM(V}qAH}~_f-b;q zll5j5)N>(t|4by7qY5x98kzsjp&V2uaqXRd^_pr@it|x z{Cjr!w>~VUj3rT!t_^7X=+BLrY&U&+b zJRonN-`jaYO|p*6r|QJ~xI$hgh$Rm_k_+E!qW8&hY2S}4cz5I#g} zbR6}5=eS;V(`wqrZ=>MJoaW}9#^zg+LfMd9bZvs&$4pdVhs>|@@8BT@)F0>?(~4AloNkAY+ zdu4N+IqhfYC3w@=QRJ|=4?uVo9U*0@2FJEORbv;q;fvhu2z4j7c>1Jc2^P*O4#r4w zsqx||ER^{_nu{sPM|Gf+(+(o*k#)x+o|)4ys7`|oKYHr}&aG)cvtuO_lqon_;TzgP z;qW6kQ_>Uy^KK@S1MAwlw|LLT8_=41=s_^qYDRwrj=Jf!nOHKYc{)`^-Z#q7@vbJv zD9KOACR0M21-le7DUD}X`HTQVPs{&kgn`>I{G2pQr4J&hFY)?5C=SM#zjRA_Ia%I5 zJj)ZEEtuNMR9e^y`PotX$Qn|R*lNk)Bh_avfD>wvZ@F?3+M3$*bIzyl)(b|r*qKYmz7)-HnrKH~( zD}5KfIo(AZ(FM8E=`f6ZZ}+Sj>2v)PEbS_){8#4pDVTun!-D=U;rScz+rFm;&^UgL zj0I1h+aKhE{S2d-y^C%(VI@-$N5)wCHtkRpg@yL07MN`Fb0vMn=Z$Xcom40qdj~M? z>1nWp4D1x%d-%rrz5ywNuLdelme(hbgqPYrYiA&vhYK%#{+{+cO}A0HzsxJk#DIUb z&9z&(gQFIG)gw!I?H!fXy*{+|L)%JUVpzdn+c|9>*R3t$v!WrFPQj^5nD%%rysegK zwD>YHC#2N3e%i);{celUAu!O~zTn!ua?(@cn(}M2&rqUFMXyX@_F3~h>Nx_3tnVuz z{YOK+_LjuWXWD&=h<7aEF)(m#U>)T9d-jU4P*o{JKS)HW>GEtW^*5Ag>isrPu$B1H zlPKSXVnr*Ut^tUcnT9e0#e$z%oJy@1F78z|T&S5_O0ZNV)tHk@NH{#-@!NxQj-OO+ z;^TM1Mx{L0R$kV}L zKmRION94$JQ&6qG3E|a-qMQ|k-N_SF?)Y$Dj$v}&Z1RyOhw#uxRE^iR(orf5?TAAz z0;G-FtH3ldcD5I@kXyKpV5=rsB!^vzO22H$@!Z@#ie(A|jyD`^}{6ss6RJ7ez z1_O)@#obR=-+F)hvrYv~iJU#JYyLRQoPNhE#T*>aa$Zd{Cd4nX&x{B4w1KJD`pa;* zZl!brI5sOP)29ey>)wC}?}&W-vu|H0CU96a;RokXF=Dj|cN4MDEU!>jpl&@2jE>D=HKgqSOR|Wjk#E7Nr_84zsY z-Z$Wcupm7H+;bA>9TQU?de)dCO%9Eyh^LA_kk(Ph{MeKSmFTO!O?SIYAaA}*QAgpR$ z!PO;uEWM)MB03z-Gv6Xq=P5|o^HTfe8sDw2@gs@ItJO_e{60 ze6Ls-o3VDYhxlHcMS5DG_s}U{CWXzBV5_WzqEV1A1obE4kxc*gJ(^u(TJ044Hu&#E z?OBOP+Karf5Z2}d-@8d;M#BK0e$jx2oaB$=Cc7Hc5w+3)CHERl^p@%TXU_$E0Zp=$ z)!q}qoP?vLtLDQX~nT0Bn9JJNy-CezmUHYJFzJN5R(yi|wrEQ&V|kwe+4{-P~M<+4i`6 zf0t>)wehJG-Sf;H&C>McZ)jCJC^T+pThwj49mkbMDr6N$+t=Uu=22R>qudiTJ+>x^d|Igy^Y~v=9@3xYJWO;^`8z6-u|N&c+zrI z2L6APy>(nu{~te!q97Dx&#E26cLaZqejD!l$P!o zBcwNC3>Kfe@9%N%{rlcO_Sj#0oX0sk=Y3x9XJXCtjBE*`L2YaW%_7#`-)+wTkFOHAe4)n_hC#_>fa^KR1;GZfH^<%OyDL$rVwEW2 zA@e5GqPP(pd8N_RjoZ*p=b8$8O>l-YAsVq?Gh6^%X0u~U_GEeRbksxz51saWt3tZgq< z;dN3`?8bPTRNpOlY*e`gws@|P2J9#4OnWTv%**T^M!*_+P`^j#=+RdzGo~AkmR#kh zrRIV5Vuo~y@=7-k6h3ymA82$};O9W_lWVDLQGqFp4z^lMRfV>iRJzV&rK6%q!a*Lt zEaokAor6o@L{>r7u45qb(iLv*OL;&U{y7MY}e-eVI%K|$t`V$NcVT;?bDx1jpGG&SpiS<(|F66nRGcyKnUOe>!-L49dCanI_dyH^u`ofz7 z_XFCL?>Cst5?k=pllT|~F~Y;iQPkxZ#RL_`(b`UmLFK^CYign0Ojpb1x3|3;8v}qk zql)i3JQ5U!hV<`7q!Vw1FDYmK1`vct-=CnE7v_ik=clIQVuRidbI(XV`T7Hu)e>WY z5oQd>R_gYkuvFIgZuop27oi_*qpN$*tjpl8>vd;WvHe@>tXJ-*ESn^7MfoDC74O$1 ztloy|z91LL8E_FKyLg$gPT6P_13>}3(LLdMQFO7Nx_M-3IO7Y95^@*0R7LasU30DH zr972K874+I(SwGp_wcdvs)?4qV{S`Lh6Z8Ng@X_jQ*>Y7lXOo=qYgu(m94`e$L^R- ze|;No{69&8SoHoIj2^QoIe&dhR%i@r^n(yXNS)?NRIH%ye;v)dshD@1rUfY@vurd4$TP*y}aml+oA|WDyFI!y!($&MO zJV{bm8)bvO!s?@_^Ss`AR%BvZf|qY^Fb~fW;&yqoOPaS6g*W|Qvm}YFwhweu_OV^| zQ|!j%^8GqUL38cc{p!>|>PCU@Otx}XFU$&3v9GGWv8qzfDbcMV4_>NRe~{`MuP0b} zW-}_RuvVs+fP3d?YP>B_7Z;eG(NLGBPjnfTB4`l>ATRpzsI-su?!Ds7GTl(|ssRl_ zRA!Alz4*i2?mIhAD!_m9DGUuib}pcn@J;xdSDowG^z?Kh_=f3NpP%fQz{~!&Kh{sY zpOY56uT`4iUlW$ls1NFDQ}qT@H}RX}nl9fe)t}u3wrs@7zSRegXap-BF!dOZ zW~j4-D7JgJ*I8N)w=YQ?;)=7Fo}G{w3W+k@0=|Kaz6#;=$9z5QLajKj?qohU z%gBx8g0Qf6<9dDpqI$A@*Dg7|GtZ+p0y#ruDA$#6@rF%}&BzJ=VVxb{=_5^lE0>=+ zPZn)8jjtd$@8@v)fgX@v6C!^>L4;x4_3n_IjGCQ$>G5q{mcO~B*k)Z@%->kzL&ucaNQQf4Y ztGm4`DZ7*Y>eqf0<=nB{G@o4+u$EmaR#&!+sTaEhVxDL zcuuL#{_&%wz|@U--7waC8+|Xhex&(Y)zn>)&P6!rAZS@~IDagt3lKXm*^|#Ozk82o z-K<_go5zBKr-}1-$VGqbt7 z>r_WMwW5gmH=uzp*5goaSl5s$!pE>=CrU5#3k+5zFSFAJ%6yo3FXHfTKgL62JD`&C zjJUKdijuMFT*1CxiBz5%3ev+QGk3|_Sw!rlyyW0J^!upR1|E~mUvNeXeYeygB(C~2 z`Ta-p07A>>)dtEBLSfzcI*BpgqPrzIHJ5;C2FQTEzxL-dcc^G7L4lrHKjL3n$-X8W zFC=oE)rN6#Jp@+CZ6@FyY@AyV3nS3VmKxp8Y%{ez1>1pep! zaJZQ`iYjb~&NP(n!Wc09>2Rif6Q5r)42t`oY5wCQsMu5hxLip!4D+ivI-w7}5d4%k zKE8m8VnoXRwd#rt0a1Rl^P|LXQgp0E5^Ug2gR=a$kgD4lHu z>!F$EBM|=+3Y#iOG0uT?O8IbrY&Av!IwhghqYo1L?NUzilSAt_KBV>@@kRi;MC}{k z4oA@IGrRFyY)R?1b=2h9HrOg(CEN0oiH+Nu&FR_B!k5uc`r4&Ce^Qn|Zcbc(;DXty zr5V1z6Zkpg1hLtIKPJbiONMt`P?F@lc-%tzqEDw%PT*b|(+7^V%`W)Zhv)TmzQvmB zc8hB*l7xr(eTOkwUZlG!9m@Xgs<^ACNl3B!pp2QBQ9q`khs&CC$bLp&)MM@h({Xh6 zn{>B;FR6O}8fs1-<~fv@7=3Y{Bi{hIjV+5%jwl>+)eQr-t!HI;({T+Iy^Tf6e>5(O zATi(p&Gv`n|7c9C#vK+m)5=;wbl8u>7luaDfrp7>;) z2g}xJRrAPJf1VgF1{dzL-?q_?IMn%m^~@-T`LD5M;5D+ z-Rnf-`uvepaHJzzN$mTboDT$_tp3)v#VhZY=M_Esu8V1%QDL)WmZVlhh*g%R@@yvM zc5KA~YxtD+e>76Sf=FZOv=LhFn}uq6F0L0d_}sjy$OBCDrqN@T{zktYzZtj#*n467 zudEYSuo>sPo!67gid{K3!f4-t{b>nzdrbz$t>Dh z$RkoJn?R6x#%t}JFayPY?xf%{oEst}RSj`qDpqQ-K}MhOC)_!;*OB@s#|q|oHnrg1 zZq>5yWENYzu%5ICodcvhfhnS3c~dat75G+Qs>1A80#;^6lVL=Z|LOEYuzZ|>^z>OQ zbX3a1ibuh&@xsCQta(V`{`FsPBP(aCE+sZ=(;H2G>`OYCG#NVA!Sn_O{X;ot?;Bb> za;f~B?Owm7{o6j_(*AVCu&SA|vE~|AqUO=mN4?F++3faDA;&ZMy)_;rU2b1Ju|WL( z!~Lf{rgEpj9AXe_YbJ zd;=%^o9{O1Z8eqJAa*pXM;8((ddjW=`*%lqHg-O?hZI}A+uw4f+9WPoDA%R?6=JDo zziXIuUKN9ctVhP$10uIZnD6JL?c4-!ppx@$A_>$UQ4C)cHOreKg)2@6i%*LoZ zw1f>+wI}vWjQ@IaCHSABr@mt88`C#AlHw03oIS#aay6dwr|K_aANQa!MrGN$W(^{N z6GKNJf+#glAb^>wG?ylncQ3Q!O!5lQs5+O4e_5bekGIIEZbtjw=7yUl7E02r#zpZ1#!EM)~SjRvIC&M5i zAm@nhwQUgJ&SN|npP<5wRz0Od6)H*?Qie(lUSh&hfhEGu2is-KqoKv&!g<^AzDdL9 zD@7CSsHnbwTb+^wev{t#5<=i^7p%^KD&RMZZDkKw<06QiJY2DBFt-a9{|QsrWZL{L z@FDRNx^Xm>GQfw`K;3mi@sgg5L!GdQ$eA}yPhOP$OKQlh(#GYM-+d}%5ifF!!-F|5 zeHLOyVZ6@Xg^11s-LCW6o0GE&V{N6AG2gEFL?3AXn`UMRRtwu- z!Wevju|wI{u2x4~NYX9!1y<>pXl(W_)tJ6k{@mo%775ZJ?PRaL(y%-g){)Mb@yCSz zJh2pA(6#+XW=wQ1rV7pFg6-SBprTeHwGG+d>-LD`G+P@N}L*WA+8c<%B~k#)@G zNQj^99B!1txV45#%&(m~i#SOi7qiFJ7YU9Oyd9_+b{h>myZRGvE+7*#>!aaU|>%v-HWE`ZUKGq|80qbx3tp zt3c5nS4xy*l3jHrJ%?>A8{j0W;+QW*PxV=eO9KG=*%i*y8&RSCcG7=4TL0%S+twTD z{3SZXc@W`&^}KWUf*LbbSJbO#q(3F+aZ~RdxIBQ!P>Xa*eC0kcF0(bH|Kt+AFe?_6 zEUv1Dll(nXV+#rAxp^@~I)4z=wfC&h_}*+k(t;3Ya6dN4sG*^_Qe9a1O@^M~)32L&BGdjZ_%3u-rjj;?MoRyJ*S116S41 zy0m1`76XJF{HVDJiRGhQyMsZnLYe|!7?uQ;w%?uSGIqs^tLFtdI@>5*{2Hlc0JB`llD=Y zD(lNbt=6pEYv-hTlYl=73cAe};!gE3KpDIA**i01U-&xPT6*)55=h)A{(2k13yhcJ zeK09FE$3R9z1Q!mV*T@+lk-bj3u7A{Lw^S!Ys#ke8(sFRwk#ig6C5TVc$$)TTjcAG zZ7mD;YX3O+bq+}9ZVb$~uJnM*MR&;e%`4`>t@Uqdh>pZ@j{u3E$^sm@w zlzY08mp;9huKx1gFJX)GP^5ZBgdN)}2@~bK+LgW+*;P+bcWrDs}yu7ltxDRv2puLa1Oea<*Cu6?FA?2ykKt5Vc zH3@E$Bz@)@Otno@vBZ;ZmWa!al+oVnELlpWaJ|@$KW8;UZm@ zYm>hxl2whH1SYlz*@=Jp)wc!eL-}Y$W#>7G6oKozXELJfG1p3WdgUSe?bbnf+lt{YOO6bFUXth!11*= z8{0URqgu(Tb=nDd2z?w0D7aYyE_2JsIC7g|sR-eXzn5RTT@9m^#-CoFJe9MY(RONT zp4dB3*k$Jo^Rvu3NcyevgU_}*$>162g>5{XIKLF)uUpv;a(<2jbx=b19FY2HqUzcGGRmsALQiFq8`Lh*RmVzB~ghuNoMT2 zAIBbhB{L);qEthG**Y(xDD>Nyzfzr`QtEq=+0H*PulrL- zQ90$I9}XFvK)av zWO-%DW3cu!OTCDZb7LZ6RAB7AbeD*{=vB^MP0>;u^ZV9k-(Bzu^O@aLzn^~ZMUUL| zU{#G0>)+&pD?iVTo_^oJK;^judV)D}ByJ``{sx3?d*D<^RI$YPLf$l=Y_I8e+^yv1 zh7i$^Wvx*>s221g?@^W>7v^Q6un|u}sJ`<4IWu4!{(|@fBCkD{*@fcbcuX5KYnEU6 zkW@aSTF#1Ggt>&)r}&!6Rkv-a1)u#gTpO9=^6FdCu19y&wycK*nZ5EwhH+8lNz@1X zC@s%oO4rJuosX2VnUP;h|H(ex8e)dAFIRd!>d>ZqgN5CCOKxf#P+RgrtiG=OHet5K zm|L*I&7gENy<7PZA-H;M8zQ=7bn8L$T(&H~H~_N^9yzBR z$I%Vb&86rq1MLyraaPzlaLaT^SPqWDK7t)Ng(Y|7UoM`C_?^$);P6 zjc97_G3_F^)+%$dp-+ocA145G%9?si@CFRy7P_Txha^gDl^`ybk#b+!S&f?7)gT4I z=O6#gi08GD(D{}Jo85v%7F39kdb~HAEqcpuk||f2DcU;~Fz1zPwtvdKunU;eF756$ z0nKG)e>QTJpXqnP)zyD!XX+hchTGBZH$Rh~dfj)BK+fkB@Rk-`L9He#sI&1kG&>CfxdRcgBZL;t%y)S_nm;iv4Wc8D{p8apzvu1h zlbK5fAYRM~U7^AHQt9hoJUBt=!p-T;yR)RBOuP+tB;{_ZHI#*1P+x43r#!8~EBWAKL3bm)KDEIDAUuqxxL0pjJu4eaT zhWao-7XTXv-;AhuY4@!tYb`uG=5>)m!5{A2%_b>pP-01Rku7wkRSywfRugAnws+cg z;)dIq*V5#RdNR>%T)@ufLyboFsGp~VvE{lS7FC9uE|4U~{Qcw$sLq-909H@Ac-G^0 z9)@Uy`@VszK%$-XF9DXu{Sle@*39menzLR5Zo)^5;UtN9Z8v`S*ab97wERiZ_IFEwjfbu9jq*gAr%{&a#umz5`gs#@v! zrBB_Kn=SJv1gOA$5`s4C>rn3}piJWqGwOoodPNHuGObqn$0fHT{FTRo5Ba+Lu2z3o z{9l%8*2*RIJ0#E~G;}S|*_x1s6V)XI{eZbHy0APG%wEnAQ#>k>2G%`LG07C>TuLk% zCq2OO;T^~gFzN$;iD2~tOW$ok8)JBMaWQD9;G?y6tuR3`ruA6nVX09X8^dju&)!<5 z&b{e&ad~%GI3GQ;^^H_2PDgl!mCH9Hiw;^Ut(ocHlxlKh8R{DbesWZ-TN+0-XSu59 z%rA_L9xJTDx`(aS5OEHZ0goGiRT@`Bk9xqj6U1EFSfA3+D6UnR=^YI;Jg8E>M}{_% zV*pP1NfbV8W_%qgvR#qjVZO1rJ(Du*MQ+2#8UiF6OS1$f`Kgq?!F=bM0Noz32@q^(LzvS3& z;)430TqZvSHi%5vHt(*KhZn-p%N{XXm1Pr|RLgUTL69EY*>T~;Q9Ryb;uLjbIC#w; zCsd1OW|~VDIU*V~h6W#IUyZD@(-zy}UA+w4V`83{!58Dq_GwEsn~O_J^@?0qU)Yrl z2MOTjzyJBOsBgWV+Lxyn-U2DX3lg5;nAZ;SvFf|4$+5Cz6$;DCwmKXcfZ@=kK|L?0^i->cC0@F|Uwx9DlcwqC z8;6#-jaJM0coS+|Z+WO7VYxof$4Ti-9eKdVjCyNu57LDOMUukA0_)qa<1|YpGFjJ# z1R8<%BQS4uCy5s#SNol;-#Xm6kRd)Ku@M}x(OP7LItOr76m-{$@Ni>vUh+)OugrCn zAw%??Nf6@mU@mU8`t2g?m3M?7^#2MVs?YZN*7C3a3+anG$z@-YYib5oN(jUo#mFSr zb1bYg%T{Ye(Q>ceR^<8GuAaN3DyYB?A&vu!i|7Sw$J)eE`S!{59k@?nmC`>_H`06( zC-kYzRk>Un{z&~6E;E{1F?4GQ!s_{}IY1(Jvd{1~RZ?TC`U98hgLH=|%Cv+;oZ2NJHU}}izyh;&HQncXdF(J z7F8olk}Bo?_>-;7T5H;f&r$ONNx>Lh$l#OnOR;o|R4(F@pRI?wbdmC1^3P!YPy<`1 z?1+5jTIhH>+|}bpjS4P@&$P%blW2xvQNArD?~LJ)=R$q@l0X>vRiSfN+AO<}>YMZ550rxx!F)Y#gHIH~AW=m5TbWPGp9 z`BsxDT!BQ7ElN&Mmmmb`O|ljtQImEb9fUbGQ;aG0NlTE;wh^wOs^IC{#UfvfSyhUQ z^ni89m29)3nrAUpCspoBSiE3?N@DO>qRTK2jP`X6C5_f3 zzG*EMh-l$8mH90C{ETY5zlAKfy4ytP$2PC=$kKwjn=2CT)6%%}8t~9bZG#XQ`B=@B zx#DHPIV?h#<7)4d z%TfGd%OBedqictFr4!2jLd$N))h5{8o%aA94Omat)`WnpWHuVJ1-m!K6GUV;WcMa~ zLoDRVOxsSuRsmFcMU*6iZ6gIfsZeI@%&7WiZz0qcwot`I?{t$vG-4qy-3o6{&LH^_ zJ)s84z`y$ka@YH~Ha`DHQ&u124HQ2rOTY-z3fycp6UEs{2(*mVt*AWO^7G3b&bbT& zji9K$oYhoNt!5@sExd1;r|IK}Vn8z6(`GnnLG#S4KT>AKB_SgDP=)tY6_^LJe>?p! z%MfnTZZ;>rKuPKUO#+Z>pn0cKc%sOv&r3>;Uz z{~t|jU_Qxz<`ZQChSfIU2p@V4Um}^#XQauTOWDp>XDlsZ+-h0rk!7(fef%)f?+Zhzt;CFXHsZ0E^i=A6PtH)G+i!Zl)eM>P-D&~K%@rf4L+zjQ zWX2<%Ia3*_PSYT_*R=<5QK`u{8c-kN{WltSY5u={%+%lu70q3+I}W$i6j|H5Hs#KV zRL=T3xgO<;_^`r(sDnlF(VwjFy4r(Z1b~^Q_IBhYUY4^DB<8I0`oxVC-z*kVA4o^E z!v)W33Str;+nSy81#mG-s}&wlHTqN!Lvr&&W+pvkkRx!b7<{zS1H-;aCOnp}7^(+c zIu)0tO+SM2_!CYxViC6pgG49lYfDR2ucV)@3C+y5J)O!eT@q=#|xobaW-DTfid(=SY_RX6{s+9(>?2-N%?GI|J z#{}|Rzkhi9A@3>Q##3eL|NJe?s2f%vSe8OA@8uP;{R2Q2SToylCHEHbvXK$Ua?_8P zHTu{g1(4|Ti~nd2^2w_e&q&}AsEk4zBzFbW>hb3wbcMuLj{o+TWV33c&>46Uy&zeL z6YMRs>$l_fxRre0|7r~Pg*bGVx>ChV6(&;{MX{BpuJ4l6%nxRL`@iOJhX+(+ODNa= zqrt(bhyvB!0EyRVXl;6%=<{nu2OXwlK8x7~6|7(lU<8Ho*W|A#mt-c$SvRjTb~NTK zcDHS1)}J8glmQY?r`s}SEcCHY8KF5$IYF>Q{6-6Eny~Jjw8QIyzdV^LvM>f$Zv8t= zsN(9$xVG7F!$&Mt>piB@pcH?1TO7?2Ebb4li!#bzW*x;QwO%-%o9ru(m>=08kMBYw z{Ep}=Wje}2da@0C2l1v2DL%-l*3mDg0J1wHY3PD1`Td`m{kSYXgJ;=}OUJ|Ek#e$4 zU;aQ92$=TFK2YFT-07|Asg_Y{C_R_rI`_piaynjczq~V3>Kr2Ckcuu`S)sA#i*m~` zHIf~(0tQHZu=a>Ek0`~T%dF)5Em}%64k%e{xdzv(~I-KXP~axoI?sTUk@^q2Dwg^b4Q_M#*DG-TK2EOOga z$62%(9j*0p#`k{EWn75GO*B|5;`thbV)hX4vLZb2^M}>TO%taQH_N}$` zR>|@K7E|Bf_Q36v^IBqiA>0kBrp3~;gmTJtxq!_@wKPx+P zD)IC{5k!3p3(^ZhG_J6-9(DUEjZh9{!4w#%n$8JdfIQR4I5aB*D>T{W7IVY^*m+Ou6^r%GqW z(sEg+s=~WQNO`qZspCL&3Ed`htzRuHyM7u~mqZ$vR@aIx9FAx>TRNkd?}K@Rh+&Wk zjj2{W?Deh?gGAX;KDXr?*z9e~kx~y)X`tVh_QJP?+-|>*z+O?zlF7ZDqcumyu@ZhT zbh&E=pr11{N7ak*Fw~_HRdXHmGigz#?yyPWEAN@|c__K{^tJZePr0PU{`^~xGtztH`D(dr+)#X^{xDDa4cWTL}`^NiZNeL(_z8_FT z4gfp_to{UGb&?}tHKTjJsJp5x<&a*?YYU45S-0(E6Hnul|}O3Cv3Fb#WH%Ojs^xAoy2qO zIdm4+LeX3%<|YZ0<7zx0UP{D|;w|GjR;0DcS9Jq_ zLJG~J4O>!;--y?L&y2&dikS^P*LpMX@!Bx8QwL3@guOcX*a*kJZJDBb+C`dY0uFD& zymo?aQvs^_0nO*#AB=0+KHp$F*YbrRMxzK}YhH0|Ss^?1rW79R;y6P|V}eLkLQ>hM z^=jK3`zAy|I{@}un*{X3{TMYS=Q~UrS&qBU4-#LPL3H2++G&4y?mm(_SOf}Y)6$qJ z+%_F4)W2KfS|k}Z+__jbAfh^I+`Jt)a==-X{@9o@Vb+o?64c(%2KN#-aQ;7~g4$yN zqdcxz_ek2);&luC8mwf4W4BrlhTYWnT3j#KqPS0;n1H>I? z<j@^j{H*#fMZTf#S=_j>Bz*KVglQV<# zGa2W_6^@htXx7g6lVGc&R?}5|em^YCm$d(GGd5U8o|s~8uSf&mGhEoyFIRcJknCx> zWe#0&-1_VO#xks-RaQaT3qGC2O2qW3AxiWylANDnT`|0TEy!ju^^S)TVix!RNa;9JQ-!XooOPfLT5@faD5oT{=}OF z*a5bV&i1t8b?0q1jbNoBZXRfuSl6tkVNn3XfG7J&oF0%`Jxt;944D<{VtK(}bamg_ z-f-m28$;rPYxybg08ei%4FuhEsi;oG+jmkGa^Fj#kwg&$pm_U&qXeo#Amgll{c`0v^QoAEgh_{@&v-rzXRtOJYx`&&$J`YP z6Z}M_*y|eRwS32Vxlj{XW8`1$B2XRjFWJ!>T{xLu-aC`Bd`zA8HPzT%iL(*9X~rh8 zrycea^p{&(yPgd1Zu$#9uXsETJQh??zc@OglH#e&^=Dd6Y!+%_R~=&#ip=!QJVEK_ zx$T?5@5vDX{MRxmYzm!%Op~zAR~(3$bxPeonB8ELIH{MAj?KH@cgf0Dur`m7a9Tmu z)gr*qc%&7aZ9jZghVSC#_YXM^NmBpO%)mL^DLf01Wa8si`4#t7j>NrHhlGfnnZK=0 zYNBPsrbnZu)(Y?+Q<+3n((}0?vL_uZXx#5q*QqK z)4qIyW&X7>WAe&=Q!L>8@;7J6t}qSH48H5QcNIrzp-LS*p~oh-iRj6BT!cB- zHOa{TXSU*}!6nm2nH2w5*)lHYFq$OwWbn`_s|*<%ihHWZq0z z2~>6xsV$*8$GyoO`32fXD|U$rVNbJCvn$wI)*O3LH?zr2L0$n*Z1SvbqZD3I0?sL} zaU)W}k?!*Ma+P!9R7bqy(vb7b*7F)Gm3bwzt2>V7?pL`@ADY;WYz%x~(3v(sW}Bi? zwSGZg;ez(R;r!6;NOZ1!A1_Zf5O?)Ub6~+$)F;W?K)ZBC?GKSrnkF%S_&F0BzlW%_OSuN^X|G%|&u6EC-7wB@Rnn_zRmZhqHxK)6_4|!PJ#rVs-b^#) z<0lT|+G}@3elZqu(6S<^La(b|2$iyceL9?JDYu^lzs9%poaASD6l9+(0Ba0Nw!Ha` zj6^{7aVDKh2Oa>Oq;39GN8u=^>z@ltN)h(gU&Of%&UeZ_5cG$0$*&&@R5Z6a*6fTh zU=+h^yvZjSnJr_!v7}c z8GsK%r7NXrp&jp^sy#*M5K6JS_&UM@W`&WEY)eRl3BgyJY%!X7gTL?Pme!=|{df^m zVPf^b_}1JN#v|BG>Qz zKX@$XVVc-tF?TV0F~T)?G}I~G_14kknFVtAQIC3_*@S^^elCoiLK{BK$J6=@-KN`( zx+53gl6-BYxTGi^cG)chyI}KRK;J&8pEWo5_gn4#R!GzW#att;FZE$#bt2U90r?{KR8&)fNTjmnMk z2YgKp{3}i@-IKfe2=+u14P5cD1$N~VMFe6|NhQCC)JV^K&uPcc?|_2yC7X7UCLP8! z%pp6cpePs;5Km#7CFrBWAGxZt{xXlbPbk4ZWp+DfJ6~ z8!>O#ue!-1K!tHod(O0J;Dmu*NP7c-gXD*XEhyk4$K}-cdgl##Tva)Gp!@uLf(}#o z+)nvN^nWajbGw;)n^vd_EhZQ>LBRGd5_?dDhQ-99m((GS6DLIt=4%Z{QtMakB95+d zh|O|TV(^o=t$lhTFJ)3WDs7E9K3ueM?2vC?orkSC=dVzaTZqhed*tUR%`5re{LZw6 zJHu~MWqfp1iU5mEviC9J`QQUHE<)-G8k|ge)75d z3mukYKayMIvJzBZ6FAidcbp}iaavtxJo>E5P79H;{+2?he3FyX~yu)AM}M>Qa!}?)HZb*t{mLlwUhW%TFUjdd;Do z-n^=}p3>8^CNpmZfJMGqGA7s!3Sq8|i2tLo{%E;z_#lb(1-p$&TC1UNjzdOys3>`e z68+9&th9u!2Reh(r8c*%E(z-*QPi3Q=;O7Rgm9lI$y@W5G6@c}n^pV`^gKu4j#hT+ zS}1@sZNMD=avLM)>NebFmIe@X#e}rcf5cKs^6tv3+jOUm_<*8%i?q0kejGQTn}|E5 zdgPyBM%15P)(tblOA+AC59@kbAOF%G(VO!G9pu!oT#H!KSMbkPD*wkH$5h3!;J+j&k=$+<|IMN=W?3xF)-F z$E>+tzU*ftG4c2jhsx6h((XwTE&OZORa=PeW984&K;%zHWZhwC{x_e!Cni$HY!8p( z66)fChkT}FmZnPTdMXyK0&YG?_VL0FcHhk4A5{0synfR!|69jazAfZrbT4y{6%&ms z*(*USRu+KOKwb4Kv-gT};_Ja&E9m_!Nr6z12`v*bjqm`DPGShs_8n+Q{LyQW=U@K?v|8w|$B0VQZwLi4AAe2oX8&3obCfDt-HB=4??(#M~ z=4TpwaQgOzzvol_#nBq*ifm`EiCVV*gwLDJ%`a9{<^T3(^bF`D{SpvjJ&Mm|;&Q*_ zRE&c?Qo)Er62+mBL0 z@RG}@qgb(7*64dlv34$kS#Ks=$fp~LR4Cd(zijODi?H;kV&=a9tsVs-Nl*EY<{>&0 zze+VFv+xc1_NPOd;K)MYbj}pq?+?Ho6q^N0M1g;8)}}ZodEI`-?Zri>r3=A)_{uWL zu6h6B9{Fj)#?^3k(%ozuLM*O9yD?jH>)+gO?knQgCM+qh-^~k&A*Deqz zygJi$7z@L`Jd8CAA6{WszYkdh+}MF*9wGH~Epm}y-FTM*qF!P60jIq|&Ci7DFB>b~ zODQ14TasAhs}_kN(KY957{P1Dp$y8#=Q}$2ZD!xJzWE+2&Z)@!F3pv*gg^SNpr_#J zIJB2GF5iYkj!rRB)1L6F-$2l4gCX^+Rt+Txz~0J3OJZ9@h*ydcz` zNG+T7A;KWx4tmvn1f>GLn-b%kaPYS$_U};yIZJh&3TyZY*zQ6fFVt#gU{eef} zp|iZ?a{ZYud0YP6hmCbwR=$^{xy1@=l3J%w*IXD_Kf&d4#;o=GZVz!5I_^DHqD_7+ z`g~_BfXiHbX7JmOK~Hm^sywN>8|hne$Kx5zVO!-K+hA@h=#9Una*M7PqZ^w76HAtE%oKIvy{h&{ zUy-zP!tSTxCHuN4L4oD*tdqBm`6+!~p?b-Mar1;_Df3)knJPw?oZZUq8PA<1#?L5PKao#>k^$&!5 zYeJ4b#;ah$3yw*%OJf}526pgQZn))pyg67|HWM>@!LLD}FSZ!mvg%_k*Y1&;;JKjD z@XyFFxcVifVytA2Vw%BQbE#JvWlP@SVLSKqU#qrsPkH8T(pm97lv?BKmy`?E;drN~ zw#n9FM)$Nrdx|9WHaIgyMvVO z5A^wxxqKLxJL~>gax9CsT3rupNa}(1DKT94{Jd59_k}&&ylKYDY%DqRK9czO&kb|I z{sUU(=CEw!o1{ac8k>^QkeRPS3#R}lY5 zM)cDw2ltcaC|@h$_eFT#Expzd+?Xm>7;tdD0bG@`PfPG;E&M(|jD`yVC4LayZ@zvM zAQh8cf|Ig_>A3AE-x1et)hO%dZQ+@!)c~u%(%Wb>NlS445UuLZaS`W){ME5TzL0*LQ?`6VfDb-islGNkmOn?cdNm=P!bZ94c0Sz-5=V~KwE zdgJKkfr|g>FceLEu7S>vrU((*Fp?}gc~VJh$7^|rVt9LW>ABRyu8ltV{ zs3LNs7CqgbWjS)raGgS80CP{55_m&r{;XgPndJDo@|3d< zG(SGWg?5iwYicic3n+ONAJK);iT-PJlCY?71*Pk-1+HK~>rmKTmAApm_1RQ?6k1D) z7*3M^tNOT{bO$FHed@)!GmW~XDkoHIWILI-KHY5~pcB(~@VIa36p`-bA^3M4a_}%? zeog4npF!joV%$YGes02_fO165CG~=Hk8L5mMy#_+MAgC2N1}W1lsC;f$4eg?%3I#dWcYr_1|za5Ja`7z+H5mUE)q4d4e=0#GF zVgaXFI-Ip|*TZn4bhA8E#wxLfbt`TA&9A^rKNTgeIWcbDY|fHgG<%?U6H6@$qxYmF@Eo9Ktz$TX!zDOs2&obp3#u9 z=H!njji*f7u9gWw^?r2<(#R3hjeLGLp(pL#GqZfP3VSL(I4iVM8%B4Z_spz1Z`ovG zlUf#3H$MF+s72|I3G_%8_nrn3Pmx>_?@cc26vxCo^J8rNll^i(BCktP)rUe?!awrJ zes_>c=MOsUiyL}Q!~7^IgWnt!6WY_2rvw9xJY@f!v=a|(GrK8Q<@f0_R}XJ3EZB&- zD$AkMi`-LxazmTcXm%sak(J#&uIZIAA<6JdMfqsKA47Hhwqe)?I?>U{wV1c zXH?4A|Hf3;aQjsnhS)dc$n%vYp{j#$vHak-iBA--r9wrS!o&z5*?u3e#(ONN^p1Ui zA)w)y@0)@;%Vedx}Dk2%<$Ic0;2qvk!2A$_;=HF4hQ;JG<&^~Ez%X(@`LcCDs%QG3OVnypzBHPhDKHDjlCQPfO{9eXB5ghXDS z`~3%eACK>kesPC9pVxg|=bY;tOvSa&ib<}u<5JeD13eaD-&z5dym&jn?Dmk`{JFZr z+{DRN)N+0}ZU(8-;1Nf@?!hDQohwMh8+4Z>IxSPx+h*t*53ZLa^)m6sN;*yDkx);- z31s$~?uro^*~zsSkEl*o>ov{VP9C;V1 z_vb6rzd&BsR+fC|EdFFURB+|TJB2h|*CIk3(YUoWZq(V`4fMw{%kKEP3q}8i)lcph zYo@QJq)OlB80u5))Gervc?o>u`+D$+e!v##Gi3V9ss9c_014z53lkI$F~=;sZN zgcL01^~a|ZKln2h^k>(sc&_&FYz!X!3v>O9(~MUE>0%j7e|`|zpTVq{^^S1swpxk( z-uK&DtL6RhAB8BVZ>&m(R~HncB+t59h*Ki#~We zLG%7I&r1pUZldOW1*-mOR80qAJ#blqS zw>$k1?7d-E={6TjJb%ge8wR(h~OCylT-~^WM{nfE3V3S z=dcX|&eiq{rPYCoTFXofd@Kwkf&A+Tn1Hgly3XCtinCcoM}==CQUlyci9TkiIyL3a zj@94DhU#i&1^>?n{&kxXgmoiyS@oFCPgIQ!M11)yYH0L(N=afS(AswhXx{8NH^94Q z>*x#&n3u@psHGLJoZL-ms(8YuvtpKDY&k8p_3Hjh%{s>1G~!5HjM2& z6!a9kGlE6Few~e~nvd#h5*$v8L?!svq*XQ?GT*wn6s>Y2dClq|QRNkQzbK^Ba_>Ki z#@cM!nUi(1Bq2foS5)5DhFGB>T0RIsx0$j2Jt)SRRAw zWs>x6l@We~0P!eQ<5zG)B}v6UkQ~yVLqJrU=Yk^hT`#0+HpcKK@KFF@i6&854*GYo z#-Dt8a;93h)UUardg&8KP7}r<@9?=0oEGV}5q%ziFVng?43ciP7tH7!DLIj;IdMx? zmtX&*u!Vi%QNjMLCof|A6CW&mYKc9<`x5!2Xn2X+iPDaVn^C9sCGy)i6sq@4P| zaYiB1xB)ON%!>R5`}!^8jb6RH4!E*b$uqg`-1I!z(W#c|*28+D)%faW zlJU<8m%sYK4-Q@Cc8fE9!n%yX%hm9^U`NQ@nDO5*R_8g5vSoNwt43Bu$TQdYXHp+( z#4w4X)5pZRaowA@HYIDpzGhP}>?=6op#x$sjmWtTXKWWNK@-|uZJRFA zr+3(Sop>YH&$Y+GpS`~^--ciq6Q897HVulv?n~idPV#-ILm2Hp0tEkkswNSO^L7y} zFKRFxyK{Bnn-K@U$S9v^+r~$xTNGwl(Bs~@!+k+OJ@5=GlT-QbqPnIu><^NOZ=7UT z@|1J`m9xZvLS?M;P^GKTv(Fk!51XDEx}Jy=V%p^`88eqfwc1&Ne7%%X&x&`9bcv8y zNM*NgdJ%S1XnTJh_TCml-57efs6NDMAq=iZ{&TT(&$=igGMI;rPeM0#h^wgHnyAjl zf9)r;oF>}E?FYRIc5YyVI^V5es0ECWss5ObP&LSB*iV&cY(+l|Ypzf2`X5D|DZJb~ z}xx*<9F!5>%D&@P3DjgVJwWr+b?rtD*cPK_N$!O z+9V$1gS8eR!-T>D#RsBjF97O;>!#W&S5eMPxR6G*_RG_>cT38hHozpVXJNi@W)jO$ zLyl#})XjP>RFylArAhMMgR4kvgngLeDpCcxoCo6oYK{W~+Esm~F$1=TR&3IVHCbqS z#FCPy=}&X-J%fJGB|t?+Cbd5)B}9|y1|7I`Z@}@WIsPZ*QtITcdYZhE)Jm0CUP(c5 zq!tvJXZPyd;_Ahyo|!~*9``SR#H{7pa-Cjj@0J)Wi0(CX&&51!Q7;20>8e;R0O?p3 zr^-TMx7XU$J|@{^;>4I4zFN!M)N1?kv2x!pur568tg;jAXwAGq#(_GMxx;kM@{Sj?dJnTU6W8$XqAnI zX)aHWPAw%_6A0~lT~^sy}~ z=ZWN-lnz5&Rf`m`&VI@DY3c3jY!_Ui(Mj>&mu9y`my!EETtbMTs3YBm7aIC%h)JH4 zY;Jrwz&|*vaGXC@V{VZAa~$0)^rCz13|~|F?J`OUTxvDon4rSP$H{ualNqo~ZCMlUxkJlfya8g^ zz6qQ!!KIk9BGk$jXO)_iB)O&=D76loI?oukszppVwnCzDJ%QIh*#3l8bB-?j-5cE) z_*r9c8AELZSqni{I{ZmpvTTBfGW;BA7hj!^<%}`!=P{PYP=8MIwECNEXc(W+Sm*EjW^{W_yI&pN zk7QIMnubl01zKZ+yA4$H(e%&SW|WfQ(~3RdOEI- zb$d6}czk=8!8Ghs0V(ZuC{7=Ipz+j{f_p$3%SKClm}o-v5b+Q&$Q?*2J?b#*K%;a9 zED+>r|QSQnVB$YLM%oj7AFLwC+v3pM{zdPwhX``}yy2X)$jj(Zu4Vhj$Rw?M)H`Kkan9> z%I%goLBBCRN`BNRtT7rnFv7Q@-$PV(QlBOXx-NI{Lj&I|ZdC%#J!?jf=+)#Gl3(&3 zS`(D+I6XA@0(kq+eEC7{Ysrq(+I7|OKTVZ)b)1Yycj8FG1@&ozUBm_lWqA;m{_|&G zv@kxc6?xg>H+GAlW^A+Ewh%VA`|346eRldETPZ%z!N-+9RBv;))ji#Y)X9Kw7=}M= z@7egiuOhSDTnEzBxpOSqKfAo@W^x|ybZ{?mJ{=9@Ry5o7ATbw^sewhqU$CEoF-8Dk zP$`w?)BVOV>iy{UVfAY4&4r0uJul1#p_74}0UGlOTyDL_TbB@q*dF3&wu`PPI{17m z1rXQY3gscp!5Q=uYvlr^6Dw{_d}kXn3C&5!E?rH>uq)rM@`p>O0zlF?W3vs9zC(hX zz-C|T5}vXP64P4p(N8BsVs3t?wmn%GR_o-h(;1ZTyJR|4{tEE{c@BL0>TC-YM{crX?t1 z3%deVw@+aovvZ-2tV!=HW$9OMC1Fkixj@=P!CxRcB}HsW&-k_q+h1Q8gR@sC+FD^$ z@%6LQxo}$Isg#e+3bsUW^M?YsNlAQVL2~bb)l4hVZ>g>z3|9gQ(;+sh9QOgeRxT@u zt6GKDMKT16cumsvD(e`D&k}84s#6eP#30W3=2ox@E8)D15LE+p?@_CXjmG4D9}=2q zBvJ8I=yAb5_xU5ujNFg{&NgvjxE%Q(xB)V77y)72bL(U$T|p4KRxB?iXfsowO=!)Q zTBPIEX?+pGZfhz~IN#!7zwhAZo`BEf1-I39ivEK00ctJt7J^*D_rxnDX`b_^Ha}(BXf4CR9%&`Ehlm+EuP9_oRxfcA)g1x)Nowy09WES zsQZzyDHUz%u4nYv_a0iGF|}VcO#li1mq!Q(?&+XDvm&_S`cbB>jY+}Ddmglw*3Ro+ zogQnWuH;MJy7!TtXL?;J`A%K~aeTXn$b`qcI|{ZH3qtcQ_vL@su*t`%f2}?q>By6 zLG@Cu=CaNM!(h87exSsVKH^(I3ala;!h{PN_)Y*DPVU=Nj}KyWINijyyR6dIE29J7 zf7p9sZah@$yijzOH8o&Z+){jU0)8$C*UzV7TKZI=pJklNb#|CMRNXz|eeX5K^pn-i zCAP~^O?P=|!nhYuINAuC-wSGM33eV*-dsq0-cL$pxnpV!dZJZ77KAmw1P^dL=q9X_ zq<;`TJXqYz7km6qPuWn8fj`Ke2U`7ZosjjuX6xWT3N^WnX0sXzB5UB=wC_=Fq8!I9 z;k*nlVG5W|UQJgU=HENRz9nmKY1;@}l6or5Eazr{z|*6!+|gZdGLtwZ8M~~p$UC)m z>+2R6>RpJJ9w7i(k4xA^Jed^;q5b3dr1?Xci?_#iLR#C^h8VN>j(HH^<#N4wUiK)#pzY#BX^)O0>*+=*bq1)A;9hhO(h~b?XFeiFB3KlQn~?ZpaJI4*)@xl_1}Y=LDN{Q2qapQuAho(P3lqz-L>6@SPKT zwBgL<&$7_6)t+@>Sv}$;;(}^ojpw`fug;2L{&Clh_I4f$!IV+gXW}PqqIY%T<4Yae zKZo<_w+|>&xrf6#AQ^LJB$kTh>STd|v}f&! z#Tf6SYu`@)v8UhkVcwrGWB4VZVrOG_++-;ORH$8=VRVo&$?7b?u~2IHL0)0=l-1TwSb203r^qNX2jMM(T72?_D zXEAB%Rz&kuY%iVenwEem`Wm{gAvfQCVJe6VRU2Xtl;MW$H*{E*YT&n8V9h=pN|$9d z?i(@(2bRW5t<60bQxkDCWfS?9OJ5*;+*w6*eRrWBnH=S&^k4-5sV#VlDhI1|+bTsTOhJygk}t6c7*ptH7VgFQ+r$D%yG zV1F&lBug*5a#O4Ehvghzr}Yvbxhx2mm>PyfE9WzvmA1eYUInpurv$&>ZeMv%*-k6l zYUcQQvl9$@%GAFvn3sQfm!^YA_D-2ie|G(1+FE#zqcK52uhG+j>UN&EDdg)f*yfik zGV>(7&1w|!V;<^bkUENE=Qm0$Tz?H(HJT6NS?!FciS5xnDtFeIgh`{O-I1)ztHNdm z$S1C2z`CW_rq{cfGllCe6P$@Rm*MwclFzhq|D&L}22Yd2H1`WhGpt1Ta(iXCiM`jk zUW#r9I)veOV}8ngZ{LycA+Y2eP@0Qq$|ua`H>T!IW-4vFdQV=1`oJgMukryg6D3K$AI-PNW;aEW7zv z+7OdVrrEvATE#mCS}k@~q@ovOP>C?X%+0BYq=ys8eK6r?lJ=TTDl^j%(nr-CpNLe7 za_7gdWgp8402htvUD*BTgOflNs9@9qG}if^U<8AwZZK>w8f&y7xX*x-CrK^x6HtCW zc$xf}fu2QB(#64YiKGn+`n`+d@+p~zlvTKGP>7ShU&U?Jk&|n2craTdhj86-%UpK) zSh2U&VTsNj0mC=#vXT0qGNRv3o(h+qz=W7fe<3QkypfzoIh`J*+`DS{3IbICHf<#{ z%6_`tx?uML(Mw~35;?J!$U0~c1xM6bOIVk+$-R=)qMYdbj62%{?9%}gf1nR@&sqV` zMXEO^tHzrrz`B)C*^Mh=TmMnCNZy)Ixk7L5iB4nhstG^o@G)#^nBv&ciT||kZXdC7 zfO4A@F;8S6hQ}d2J?ULnymED^<7lo(WzU$#3Ww&QVL>xs8bO;(*M*YP4GF~EkSZ%>Sv1ZSo{!}~jzScBjOK*&ges(_x*o(Mfg*&<6 zc~@jnKJd*S z7icOzeLTXlo119-Wp$UNS|dd&!}CO913<^WWhsKlez0fQz3lzOZYoi;z3<*fo&AGy zzxeIG{dg^+#IldbIT6pd9{UOSpb4&WcQ&C$l|cO7uB|G~TT&xMdU@`j`K`oMReD3N zvU4hGUsd<1hjp2$@C`2$6Gcx&>G>6aJr(@BlePKXip8qwKh3iZkL^uBJq^C2uSt!o zq4z-y9qkhCQC6B89~TYonapeKB>~=|Gxe$daq2+h^YlLo8T!?MT#kE@J%a)T=NHr_ z59W!6$Nw`Xz7Js=tU!?XMES{llS)s4nb=UCWAu-u2;cfx23l>IduYDwm7Z6~|8$i) zgggvG^aRweQI~^Lag1g+jHAWIhGS5~qNsb!N5CJ)cWe3z1ug9*!0`x7a#E3WGs0yYJ*8*lYU=uiWYJ3SD%|$}d6|DSC$Cg;D-pS& zO8zEBCxoh0s%z3^T%Bvb>_i2m{`;flzPXtnrH?avyX-zQxk`JdzOEc&k zdAB$K#FNHUQ%gVKkhDq~=`gFFBR|{*R0n}k$1VzueU)V1ES-Ka&h>hJ8*fFsNiJ$n ztV*4)bEPBBKl#B(-%#rU-P0UsX7f^VCU~OEnaupx%&gO>;*D0Riz#vQ6JYd^?3?zv ztNu7tuB2xfL_1(VC$wvpYHp=h*S>n^IEGSP_aFEZ%a*o_N7nGU8xdij=|1RB)Ex17 zIC$K)Gy<}LbqSnMiAqBfZqK{k%}j-Lm(Q#+X-fDxiBcXu8{mDYgz8&VoXY9BTj9ep zJud~M{rH?t+DN&t#ie7QvAU9cxD9%iWxg)Q z-{f9IK6#zfvv|LDB7Y@B-NUOC-G|Teo&M4=6q%MU@wtTGB$0m@<8kW`c8760fR#x+ zN4a-H&X%u?@_GW%tdyjFS=cUGO=1IT2t!XkxyRQsZORQ_Qynj@9-YsI{sz?D^as*ldNdjc(+a*@&-B9GsUvN; zRmtXdd8*~*GG&KW89_s*!+T~W#Gn}6d!pl7?b#O-=!M5Y38 zs2gfn{r%A8DzMIUqnm6GlDX1tLK&jg`q?t))6*VZ=jPSdxrx6XiF^pR`HNVd&MS$U z>*V{0|_hLV*B{hwhn|-&f45rC@Yhljk(6p^n@s z?eP(Rd*hE^4(~^E(_9M=GmERsMY6}l4~$GEyq`LE8(Lo@^Y7P9cbJZVE0^0b62EL0 zMCiaS#px@HXvNDMKM!3$@VD>)+Bo5(8VJBZI9c{7n84>crGc7PdTrkTs;L<3sfm6D zwu<`+fFAFwv&wXVgA?+$HRE8KLKA`g70v!()La+sv~{ay5LsI%EO5+o28iPI{d~!~ z{$P9a85pqqxJ0UAI073zbeM1Et(( zENP6oT3%CAv(XQdQ1{Wo0N+XuN~DmB_hdHr=tLh6}Og za+GBh(Yr7EC2tW8OuQDt&g=g!o{*_%umw*ifE58zHFdbjPh2(J>${6CpN`|A7T5_a zHu!9i8)k9Aj0Y5J5i%jnm)`;Yn&Aet$E+1dcSn5kZD?)IUov`O$}Tyy!cy?|rg3sk zfZl>IpmAGHS-jIe2?nJ8Rhp};F(h+7sE2`itbWXTv8^q!caWOyn-fz0YWtHeaAOj3 z8Fuwu*qtd4CB7PGGUue3R#Re#Zh-Aw3BKPtB5z~(kwAtyY3Y+nNBn>()ZC}d$h&Sy z>wR|en?XLj2OSjocqNFjCZf-{=Z%r;?9>-nT9~={R#SjVHvtgI-Q3z%_>}4qi)1cL z{Q1(<;(@pUx2XAuU;%ULD65{ zFX;`8VSTW=RBl&locne?0ob$l{F3@*K}Rh!T~^F-p~`0s<$dt_azkFAW2^_+#2Tj} zI7_hW>QunV08!Jo(!YG7Tkrc4f3v9c8QW!FCE{h+Ym??hZ(|8Te~KF5hC~N=@+QF= zUyr!|`JsXM^5XC2H1y(lpu-p51nOEM*o@72Pxf4lbfDteSsyeO7r2!b>bgi*nA>PN z-xK;HQ<<>k*}JZQdR{kIT_`9g=BjPbQFBly$~$sB{6?bI2g9$2PhHcDFXs9YYe zmZpgx3&@qu5uMKCJFP6y~tGQn+C$?o;t>HhGu-agP08b9lGlagGP=pig50Q4Ta1@NjPgh!GZgf?v;Zl1|slsI}amcRg z+?(bty_R4{00aTB6$&0`#Byv@80)rY*Qz*^PH9i+U^!ZKyy#DOYoUS09me!DT2BQE zNv#^b-K_MGuH_1(*Wf_LaJt5Y_ROrPN5M{5;>tllSG)A5@A;eZFq8?)7+bKO&XlFk zne|6! zn}6U)SSb`lrgFnlcB#lK$por_3%9Rj`%VI#BF!OmUpU0XHL)nA&4ym}+2&#W$ z-b*DHCmdtI&PU+OLV>&f=ZB#lVDv}mVX(p{J!SZL1-MsR=HK~d4w4dL$B`4Tn*lDxn*NRo>>;2QsO3RkW>f}W<<&XmD@Ay{i?IBchBg?>RQ0j z{;6W?Zv$x`KjU_d!9n(hu}cHq4cSZKN~{&y=YKMTL>tCV=YQ*k#ngTIIRT?d9szd` zl0}?+llY$w4cbSSP9E^Dy+zZ{?~JW#~0qY0qO&yW>- zx(7n;ZUF0D8z0oiLJQLW#^F8ka3|ema&pXJ`@I59uAsrsQURIF*0<81E(azIlpg2? z$?J=Fy@L9$i;eI%9R{3(WcyNzkG6wNr`)S2kSo4na=RBAMU{}3qWkDGJ3&w3fpx2q zr4N3l=CVQ><&tU=T)|#%_LqTy0(D{9=*wR}9_5)X%wC)LH^NhkmO|j!K!dD_x)2R^agv0==#024=BNj@8f5Haxd!U3wJH%}$ zL!WI9>NNad$?pE-s$itsk0hU4; zHg|XQEp`hDJ}ZP7@Mt)FjZ>$WWHCIQAG{&yF- z9n_mY7xT{>yr8I-xG+(c!HFL5!}k)`DueHeRRRWY@Ktx083e{?b?mlzk6p?9Tn|?- zi;yutbXg_{VYS+xoto~rDOh7PpAecX@~DcAPQf9nXH!IymPbd|_*?U8~0U z^+VfRN8T_N?OWf8#$M>2BsNdF)4!c*2l8PoinDTkXAvwtLo1rAE_vCC; zc>NGPhG+3$3q|xVGEQbMna&?U%>Sbp!;XebS=m53!STD0P?9xPwg(b@k=FxdFq`zt zn7;WB)7Z|cI&(i#d_$a4MCH&uuOhh@g-_=0M$b2VItECYlmT|W(zUSkCjDNvgo-=0 zUu8&>b2|0b$ifh^P1?$_m14oC#7xa;mE8-J9ZplXliZWxYFWx%xnWz^+e3E^78o3} zbL-IBAs62|3cs6G@v?ZT+IQrIU!*dV+U2MMPfTa$WgB2TAm45)&A<-T7%?;E9}IjO zpNuHAYWS!S7?}?b-i0u1vsQf@evr4O`yip}(+{uX=RJhjf@}GTs1p>!=GT|Uw`#v? zI#>8;?gMb0rE+0I7-URIJ!RE9L8oVxWfdRFkF1*6PMVf#tD)WTws>Rtb?sxqak>Zo z!vWoEKn4k9{O)74=m+m*z4Y$g{gTCiO*vo2SLeJB0;IM@E@oH0^X3T~3#ym~@#Qz4 zf_idiJYw3}C2*A)3ema8(h2%c&`$%TXVpa*89WJGNz;d+-VxvBS7qYdwhMI1FHN@( z$B|hv^pzE=cLLJ10%hx9n^W7O;QCW*nmxo-=Y~h{GiG?U+kLfv`8zO!!#Bx58D1f< zc!2f`N_uLnw{FjB7B6boxrRx!VMp_PW#|&b-C)7Zcdu)-OHeA)*+Y|8Zr1;BZsqx2 z3=Nxhmu`Evne(zX<-jh3^+wZRTY8E_OwCW^@@I>%mSu*It=P%EFk$oaY@_FYw|Thg zrj4jM8or4CQCc&tD6IQ}j8 zII&<_Ry_yc#nM}@n#+gRp#k{D41Gk%12>isI%>Ur+?km*?F;_2tb?qVM=!$+*7~V2 zu2?PU^CY^?k!Ngc%sxo&D}1Mi&1I ztKQNCxC^{PSWHP!6|+UF#=qkm4GVnsJ`H38`J9PID7e>GsReRR%%gV#w0yYxnv+)S z&8;4%utt66p-#H;o68m{I2>3cuMHV$I}06~Do)SHBL*BjejjqB7`>CS$j>B_5byz> zo;+FX`lG2a=5$8BP~xXY{!^+qfW-J2+{!e#J=)|$kA}qWgBO@x3l1((=@W?&&|Lr3 zfxG^PphFnF#7u{?GOeFO4Kp-=%y??Tuu=WmzU=y)_g+gZW!Qt|2HAM-1|J`;5w1eU za7%FTg)hkk%vm})gZlHtJ>x!&F7M~u-0)jFz&59LBX;6W9OjjC6{hudiaFvoboW1s zoob6z?;mJko%wEDk7b^PV+>PW#SNjGU1(mwc(db?nVN?vd04dJNaK4x|NCY`mE2{& zfuKfzeCtwNhHOK=9D7rP%zqTn$D@{loeI-qcen85+ik~tww5r_lnEc74GGYK%|9M! zIX<`ivE{#j&P@qFg=d~c0naNnZbAnDIKr&xL7UL|lI+*o+|sTs=ol!`64#V-nNqbM z^)PAO@IWcQ*Xi1EB|+Mhu|JXLP*Sy!=hm3A&z7$5BY`wkw5{&_RS@Cj38SAtstC#u zA(^Q5hsb6PyeM;qE;rK=hwsmuHo3Adjj%64^wnf}7tuBHAK6!knDjXGmI^QKMmhON zx6h3VWG{zKOJ(tAS<5ChV)L_nmzYRAO~R$2t=29Jyc~hgd?(nyJp4F#6qu7d+?H^< zigXb@0pihRAq^etU&hJP41OLfFM8wss-R{%d3UUSOQO7f#(2_rHDpl2-U<(n6tNu@ z?-%T#JOr%eI^!edC00_j@YuOu z^Iyr0xHal!1>1KfzP1jV=HdIh){Lzqfb}PqUlbar>U)|ja{zWeg9!`{sN?f6K$Lae}y|}^eBOP><3x5!(66i(4l3YmVVMwC|>zh z6-kuP4g)onu~awMBVdmjb-$U1eiOqdgP?D{+KQjm$YY}m0~G9BvMcL`3!S|mTAHNM zc?sK>U-`$yWQoAMN%0|i6OQ{KRMnl_|F$o<{9C6mAu}_&_|+D+=b`@$`l+a?4!j`h z*)~2dM$ufw+T)o>fe9^V`-8kG6SPk24m6NXsaCb%&!K7&Wmc{8>dan4x{h1D%x?a~`o~0GIF|n+DQ}!CLaHvU=qCwI^76hX+ z_r`x0uTr+8T|P+Ga9n8i$nN(%d-_{AL}7$C*kQo%>75t>+H_!0#YrUC2e0)CxH! zchCYT1lzXE#f|8-eAWnze%9Ixk?f7986yjk*P7u~3NWtipF0_zfVgt*;9}kONG#i# zr7HF*#r2y2N@2?L5O-v$sghOL*kA8y&+1wHm8}QlQ}52I@{KyIz7pCEzTI;dURaq8 z$z+{#(BVaM7BKxAy1-eToRoRU!-i3pA!L+MxkW$z5N~!$))aMGjrUm{01`IvWucr% zxX&gy>#@A(XDBF~%j{$Y3tHZYC#sORv4;^PWjl|OZ55t6o!2(e{$;!l^B46kPPX1U z68x#I=QZ$t9&ysJ?y3`ZJMJqUbr*bC&p?R zN;0gu9*r>zX=&2wDs#A1JBb>ax)a?`w#zQYqP-&X1&SKAsTBG5&a08vL;k10SiAh* z?o5;bj-T==gc-`v%bL%Qqr{Iy|5&n!K28<b zpjsd`w!TR4k@g)sZKDc-a)ZQ2!}(%VEs9l4?}=7^N-vM8^m1GtzY1tiPxbcJ7S@tU z&%>)25-x#1PM*-SQiFy=2pxrlALn34Wb6{Nhzhrhh1FZ>#)*$yZ{|ana$NaZn}UWZ zwi7OagLk8yKwL#ew`Trw1NA`eR;w^+G$or4Kesk$Q+QH z<$ljnS5 z+inwdvdQun)&(U63Y6fOf3@CB$9yCShkl#Y4+yxU5ZR?Xw4m^DSg0&b4@xhHvOIuuXMMr0JOPqr*H*TF$aS z(MsYuZ!upttjtdp8o6pTXQwhB6i!%;`v++0=%yjm_FWI>WbuT$`gUvAZp7_>(hVPv zW}%KU86stzT~^_g*Dok^!$JwFyFDls+PI^oF4OF!?;hf_8>Z=J+M1?TkJ&IKjRAvh z&qy44Wyg42Y)HMC}MO0QMx_)n$xF8gmP}{ikG9XxcOUqc zr=|mtf-#D+SnGs@@#<~vd7+3WqYMVQrl9x`GpAsi(BhsIPHWkrM01a)X`a1tx7ZZ} zx0fPcIrC7Vq!%7}R37}9bEf9cwR)?ek4+!-A(*)Nbm#L`=XkvIoic5eT{C=*<|1kV_Gp`6w|o|BOz3%3r50am>%^tUT@E%Z@2D_& zJFPgp@Me5YHY4t0%hq|03^?I7Et%D2i2nYe81M9KePJN?^U`MAMcn{C5(|oh+2zE8 z;!S7rc_)fzt^;bVjC5$4>qSU`M;>n`yx#IBFUwoC+UxXBAOa6XJmm$$DTDS^*q~RR z5mlYvFyn514_pq_mQK1bKM>6l6TwJO6*w3gAJ_|-@rN$^KiW+F1*<)=K%62VdS7sTRW3)mD+|oDbSc_|QsT%VQs4 zx0IymYgdzJ<5zEH+W)TRhu!|39%<+7XWcK6Gfx^D%G32`HexPIQvzC?Dx<4pat zsh=O^Kv)KvWPHLkZ25ipVXdww+KOYbfT0-D5$b?M@#3bFIvk48t{f)hbn5xJ^XgAh zb@TnDhPTjjz9E@B(16ll~ng$rv{6z4Yhhh~xOyzUxY<~$t5meI_SM`eR&EBX|bPqnH` zFX}Z3Xrdxv$-F&Bi$H@D?nOv+b7jnAtUfpB*H618w^_F5`nU5o8HJ=HvHXChX<(fq zJv!-0+PVr_?TVqRS~EMh975cm31-x(jVI#!aV)AE#zJ7#B4n)ye-gk& z&y>)oKi10Q>p)1n*z2ccH&wlT^VPTW+?eHLR>o`_FKBX^QS|eib*pLqg^Ne(i!$!p z)fI;-JrM*mp|ZFFvrk?XbTJ*9a<5FdY#YY~3LA)8vaB^CRd&Z4Akb11qS!T+9oAGe z)zPCXo?9bxghu#*Kgr80@9r`X1P=FIYe=d<{ryS;1EHTw9F2Wdl?q=34$V3(gGCjd z6wgN+)0#ds{%LYWHR8pA>-u3l{MM;{-pRAHx0G_+I%>VARFj>-p#ej!Y8GIqGw756*#m_Abx*gY}V^*aF5 z<#^oY;Db`RE8 z@qFNjQu=rehV_vB)tmBq7sNP!?M$!CHS*lju?qO)H;EyXN$QTRxV3N?jm!93@~cQq zG0t=NJm}vd<3Pv&+vUSaNRD!o2jLOo*DXGgrMpU8z&GW8>_rM62|{%LM-lf12nkxY z1TjO+OdC;B+&X`VqWiT1kJ?)}WV?8MeH|{!YEl3aG~ycRN}P#fY`@_Zl4zwT>|s|; z8Q7^NJRfxVwUc3sOo^=wc(tVf%EKGCd>wgs?35ZXoR3sWJYi$WGf@{`K){}?H4jt% z`r>I2BJr_zs%EshLX|Q0L6Lup-^Ru|LPvJ03rL-K7o0pR3piqK_PSb2a@+29D_Ab6 zIfxWLJm9)rUipjZ=4<8;`NFHP>#(l(WT6nH$<8~3dW>wBwP4Q@jml$vH;+PSjv6X@ zyxujMfm7H07h*v%E;ZJr#k$WQUI<>UgCE5&B|`9GNOD3_=d;UC$mMJm@yik*R~9}? z?1!+EB{VBS9$@Ly99DH{x@Ii+O(oDGo)rW5il6AhTk(yb47Cq>1U3ZE^cjxwS*=8s zCOh_lyfTgmTt5@rjC4Rv7>fjoq8*l-(^)VnjxR>xXgXEf7n~rjl}4 zmo`9yG;zf4i4zT96F}-%Wn{dsGV{y286~H(z$1}tepXo>>hfr|rN#oAwg|_BAk-wh zaj7pkKA(wT`F$63HH7jTNq^c;xZw$U$yLG`t7$*3_-R7Zmm%Zm7sW{kX7UKO!t()F zk3R-F4Snb?@Ks;2A^fk|np1m~(W8gEu^C_ae}uhfR8!p>J&2-$AfO-uQlbKaR6%-+ zigW=1sS$YTB}6)e8U-oRJ4%bvd+5D~A|N0&(t9V6Py>YczrQszA7|!6zGSU?lUvR? z&)IuFdmk5h_(7R$s*JE3tZRp+7F_F!wGCzxYXNxx9u|GoR?`SzSe1n4-c;?IeI1vq zWpw7ov`_UbqQt0cj#|rRZjc?0U6;Ys_Huxh-2Cfrn+tV~m4$args{DlFQ_?9EYTA5 zQ`IXh&`zl;QByjUHW3=pOBWvEv*gzjx8v<{7!aDOirkv1Zt<}RfECg0MFMl10$~{s z6iE*it`px9G?vXNcO+!Qnx-m+lFOo%HHARWOz1Zx;Jv2_j5AtG+EoFIK%N_v2k5gHp5NDm#KH)}U3IW#2E+9W%RY2Pk4iu4O+2qkw+ zWROr$ z#?cMeYn=B&=7#}kp*$3Vo`EdF!`?+-V@+~Jx|`_P>!9668x+@*ZOMpZUbCbC{^=26 zHmhUv_LL3fLQ62)%Ova%+!k#%BD3}U2JhT0alACam_Yvm2cb^=~IQTG`} zviDK%fy!xWKwcV{JxvpOhaQV$=2|swPqnOE*-m213`~2KxUF=~w0xHW0{Ax@b0^EJ zc5?<9IB105W5kbR?0dt?pgQ_nkYC z#S23#tEJgk3b?04uO|z31HP`>;OS4Mddgfb{aQ#(vb@iUt&y!P`^B-5ZEfa!bj?tu z0kajkkGuxQ&NZH0lm7efeUb|c_U+-l^CCt%N5GGk^WOdsxA5SPf(tqj0{PXnA zrW-qXj*0wwT_D;MtnL|BGCtkDE=kF*cg~K29dBe}m!PI+2{!W5Qe& zklDhuS(Z7~s95pTs9Oq|@RKqcI>mUgL{24EZMkzQ-`CeDh?fxnns=Y*lX8SMF%3x# z#ZFPPGhN>4+M?>0eH>k`&^YM6&~U}MycWOxt_;m@=FFMGNft+TG1jdyoqHMoC8=aU zU45=}7WanVQ(&O-JQBoX`OyKy3FNX`F=7?2$4nVU-R2Tij#$uJSG5>f3kWD-ICTov z#F@3iJ)wTVcAhqZHC)P7D+YYzcYS8aT>GT2x6%)fvH1Hqi8Zj4VRMY0_%Ngg%~e}v z<~;h0RD5H_p=mr~P?PCwH(204*~T%i=*<4TK0!@#>3U=Xt$PpxG}g-BwZJzvrD~C| zRMqzslbKZNV`{q4`hKA(&&?t`(#^#XxWoilX)*X2WB9GL%SEZh~Kv1C&t zVfcF1sHO6rLMGRZnvX7YvM%@8;@p2p?Ldc$?kBG?f0yDtbn*$z%kOfMo0jOOv>fd& zkove3Gw&YjOK2uhUAv?}bopL{Ma%INrJ_u z#W6>FuC~S;tP))sG?6CqNTashlY>e^KrWOAeWX^fsC?vbC}N!L@p#Fi^FO+I*X@N? z?d7`fo(e_z$7_e4{2lVN3!PKY`DElPvb1ENjr|FQF=3(jyGjqyR67S% zQkZME^?Aq}dF1rLltd}au^%gBT0C~IRYK|V4IZ)>Tcdb)M36q~Hgj))62i!m|6TV| zk!1nz_-Uoq(EdzY=6sE>*i-gl0zikqP91}uk zDY_h*w%Lt(XlB&6rgY=t^*+=@bdLxI-HeW^{7oTBhKet;|&h}HF^G?EY>L@-6?j(m7C}}iHT<(lJtHdCn&(f zbSVLJv$PapA6e$7Rz+y#sLkDG=)XT>mYhE?=J)rRgVK^UIYksrcgA)8wWGbZ6b9as zFamvSQ<9Itu7*l7WOyiRN+qTwa_F&H;Bop{y8p<>L)hYmuXi|WXG(jm!YEHC-5!FV zn8PsFgAaRO^C#iu;eXn$^~2u@AKnxXTzl;T5H%mlHla;u$W><9z9)4&)AT-vs@Hk+ zrv&it-SInf6`gWvSMhk-g4IayY@|k8!s=?+=_*`E#Ayh3^r~?R$DIVLr&8#LGT)hY zP~O{r?Q6I?RSR>qSh;dzMb!$<$@Hwet=B0ve61~wzO56e@1pk0Jc;ddFaMET@pkjU z|3%gm3yK|KFYaxfip)8>D6=g7c6$DorGaHBON4+?f?Bt+;q{BT=!e+;BS; zu7b&$3|W2}4*zW87yCqNbWW{vMk4-~yqljv>-w>;S!F>>C~KjW3VrEIJ|KSnlS1QW ztFJiMfitIgT^=I*SJ$DGRb+q697sTFX@5PO`K)i*K!H)kQzFl$h;HV-k4@^(;a{uE zg7b}PqIWSmpyXQ`s7in{fw0EVr>%tyaq<^VM(VViVnk}6n1-L~8*tkR5m9!YHv*c;_CG6JA_Mt=-w9_LP^O*yb6NHkXcx4&ffC~7r+kx{X$ zoEvX*?1*&y@ZlN*YLMSOD)z$~saAX{#4!ult1W2$84|q>-Ylh{r8?Q(*5PmD_7en` ze6_cNBlQ&?VU)UEOT8@U=dEn7mh_jbH=|C7j;uc(u6o2*6?ZEp4!?R7zfgSsr-L)Z zo3D}r4tjpl>q~xMAg~^@>yqkQ6n>Ls7@zT98aB#DKW=6x%t!?a4)+JsU``z&|Hz=P zHYI*k)u#RQ6c`U5K4Law=J~C!3XnKfIPCKcU zg!Qr97|pIdHr@Dox$1|^_UAj3=W5F=LXQZ@W!sud4@qj2NkHu7i$Ta2i$|1}M+(}K zmw6=9Zo5y=(>{RQ#w%B@m_IOw2lpatB*SV=nN+JyUnowBFVZ$#wPNMG=A zw4!GHYue|7K1bF6*}36|`8O}SN>*a&iI-;%dv3SDUkoSPaXQSka0T%`jxun!M&c>A zNP9$WGrKN4#%(8b;-)@LgPZiuiwsQvScNkqAs8h3kIb%}6vTg~a69?X9=w0nK4Ydz z@>}`V;Cj>k!pB2d-4z!Du&Cq5RtLT%fIiR&7jm4%isL9MGQq~aOEALbH1v&J7m=;I zV2H9C`}ujopR39IA}}_VKs^Q=2L|FLd@VN^{*nDOoHsCxHfqf@D%fZpqLUG==Qke| zzG}Eckthe3X5~41!S_N5fs+Baabt&%TmhxVDR+dyUDqtNYyDAv%c#2=WyYGfDsRYm zh`fGU4_&8uM&{gQw{d})LgG|G)u`?Rwwm9wv&(^1pS{*#J&m?RGIBhSE^kVX9)rhf zHXuz8ovniA6dhC6z6N~`g2-80lf=(A%yo4~Tw}D(bQXk6Ir?F{Rq_Ictw|OinkNo- z>4%VE#FuG3>)jU{3rig2NV>ZF31 zk0v7y^=nqt%^M?fYldS$XcXw&TX^>$S;7{4Mkuo>$7>VqdvN+*LV|;@9()@BJrCEJeB z5QPZ0vv)7NGP50MJPIpR823a!IO?=GdEZwSSh{-~@EVm}X=5KHiY#x7@h@{!!bhia*&_#0YMkfMuHPZtP6`^D`{ZA{hA=g9E-F{(hf zJ;Z!yKWu4{a+kywrk(hHa-p-F{YTcqZ?Q2|!+l1L?HUFUP23&4{jA}2OU=i#=mgVQ#Mc8vw@&X?GUWkm`U-%O=aDyr zg*cc4Mg93w>^p_Nt_;oTZs==i)UD54h(3nQ8p2`<3CU5ZO@%x{{q|-*QElRPg(-|3W$As;o%sG4-PV#5(hYQyGZTH?53za-9C@X#D^{g z*S^ua+|oqIf^c0(riWmW7KS3M-2TzezV)^;lRz|*F`|6&)(*RCtOOep9iXXA=Vpx* zk`KTw9!z|Pf6aKB&>2YokBoB*L=b4-YsJfUE;6nHqJQ#k4hB46=?c^G3y{#fzOVMP zB8Ks5vSINdO%Wv(iw3>^*R?dlis{1ztamZ?-49q4Yy_D7U*d)LdW!u4o;C#Xhxvrm%Gs znQkYW@ctP5=K`}oze!|JJXK2BJd>Oe3|0jFj)T{DkjuuLGany}wNU_$1xd zIk#G>O?Ga_K05>P?$adBlHYjW##7ri>Us5m(gPA8|DadADMl@_uSkM+l{D-NqbS}e z%$qQ~)1Ia}nLqY1W_mBGAz?K3#;SZZrU3=LpA(*wyPuz?t?dIFSX6V!ft+|t!@Z2_ zjMK+{14~osvK>`_uaMdB`*jxOj}p)n(en<4YgDKl1FU6D94LQGQ~z83wn zCD~wFQMkWf0MFtkTtlNLMSEL$Q5b0t<(t^9`4P{6+hD zE*mRd6@8wcj2ki|!E!tlXpL>orq;`+IbyJlJM^(xWadtB(1r3g3P*+eg!!MOVI;NC zzL>o2Veg_Yo+li$J|Q#(@o2sa!9GrAWF{+q<;}^%jEWqw*ZZ+lF_NOQLCDVGc$0%= z!;U&+Pn|;Dw@UD~-rYt!jafclv!0ZuwdC@D)Tg02d@0Srq^WX=% z5bzzs;_G^d%V5*6>RYsI5Mw~&qnO+b9DLX87h(y?!5iCMZ^lI^2`IK-q$Tp$FixK4 z1=xvaKXu^{H{|LUiTiR*dw5Tp>Nd&)c)Iq8PMH>qOFjFuw&#SRmDunFmeE!7s%>8} znW(8V(X2KP)T58V*{d1B9lMfP*-KG>P2eaeqGn?E49##mK6nZBwTy&bVP`TP+MLdI zqEJhsX{K8+);Dxmtsh#QNH2;?tt`==73$Aj_w;0uSSgsU{rIt7Hn1$h=%&o^=AOrb zS}n)^vuAE+Q>Sg==irsao-*OpSgiX`I8viBKv?6u)1E-t_b<`xWmQTyxc>%h@P4Yh zC8~;=Zl^_b$}8NTCc<#29vBn4g5cgWBXk)nsSdWQYZsku5!_Ua{<2~K8(@t5FF}O@ zKYsd|V6ki-1g<5;7Hl`A8xhP{{WP`a%Ri_Ieqrci+a-@b`%dn}Q#6}sUX+T!nP`8O z(aOo$k`bybgSVTsrBGAC#9(}iO?G?{pEnP4q%CjhhnF=Zs2d5~cd1|3$;#Aq8&Cgz zMbT;Ya5Xjd_pbF{e-&<{UWR0;_wP3;Zsq3j^GX?C71*qelow`45cH-1obS{BJ}=~K zmdZc?6n9VqzUv@k+nT+j^UYc8N_kSK>|@-afocY$=aS1SMw&1*if-HNx;E9!mW+6P z$Z8d7NRxw~cdQfU<#Z|aNjT-n^x@uYJ)0F{wGxa?)2LG~3d!ePJC9nJC!X=72rkTg zBV8x>{qX0*B?EPu@Xsw0>mLu?AT)p5%XNANa?5g$p0_J|{rk72J1IOx<+k8yy=8wh zCOmB@z&TxS5{@i4I5HjY3&Y+lua#+t({Kl+*4fdL--;8tb8Q&fmR%QW5&30Zm(e=! zY3@v7v%|c^L5cSJg`(X?p`?duKrG&U{};>AlAUJkm7~Wng+8@0k6-jt!vh01>+5U2 zlD&_S`g8NmJ2I*tWVddbWk;-MtV>I)&9_1VH0i6VfLoP&J%abg|L3Qj53#hKE|K0D z$PiGxxcy26Xw*z`J3~!65&?WVIN^96Am8O!B@SABUx8GC`s3kA71KX5s{5@7W&c=q zhlHtsvU6mFIhFro;jb-r#j}NoG;Xp_qK#53t*>{NzQ{b-+NZbAPZRtjawF_x0n+?q z%|Eig?#hw6gvD~!d?PH(Np5>S)Iaw~U(%{^Fyew~rDs3UlOi$qSJfa}XZNhsBifv+ zoUzszz7~-wh+DT5)7|!}$9W3{zh;m@5QBC8uLJTG+e8HT&sQ??M)NQSCBc;m&Bc;qeZ_B+Ju@r_yox zjEQ8&pfHp3bG1v(y*xqK#QAg}wc26Xnrph0>(gJP53247|H$52?dqRshtTgBRzt25 zmSI-1Sxxu1Qd_)(s?yiuJ$M-=y( zI7pLsd|>+^e`pp9>5!&ieaTitaak)jq>M$Fc1~oLUx1_ui_4#JhUfsdodxlP%RM>) zD67R!9l#-(VwYfu^p_^QLcyES7yi}oRO2rTDy>%GnUz1c+z@h?m_O|`G$G}YxX5lD zqrN8r*}d8#Ypl7`F--E!cugQOR-u~63eX@Q4M-#UUN)CR502^b0i&-vo$956-dwe6 z+s?8Xwa3u3*R&W#TJK-01Bs_Fy*J#=cgMbs~420qq_7+?HU`4+MYp90vg zq(L28_I2rg_Z5vOOzwNl$oEW$eDHBJHg~kPd$dV@RK&16k2&p|5u8+Ns_Z;ccz?o} z$u@iUV92=%yyh{;-_-^buh&!0v);8=o=kSJfO@kYQ5E0PZ=xGXvpLv{WUM&M!-s_n zaajx3fGsc?SNvPl^FmNRm*&)sn=YkNOLyTXBis6W$EwG>g@gRh4{;iZK}F2rd#uN6e zqzWU4Qo;4K<<-a$qj9eLrav~P8UVjqP5ZV70-^G=;>^sSWN7+g*Ujw%`!D{H0dc@# z7i)o!NAnw?g%*cGoOQ;!lDt||Ym8hWogl2i-<|zB+GO>nHU~j^O`?42cXUVu+LB-I zM`;-ow0;p<-RJ-KXSB7N&qqd`_pn%p-zo}WZP1At_S?seO5LO9-=i~6-G=(KXx&FP zbySuMv8eL$V4DNb@ZmV?tvwf!St5Tc0hVjBweYyADc)pT;ZMw#5!rhQqbPjhto&|I z5wD;O2liQikNZc>C5ODwZ70$ocl7T8xzAFomnn-IElfwJ%op;gK@E1Q%BF3Ui7=ua?f=WGw%2|a;>g!RMuqjylSg=kkoW% zFQG_|iUfUoNgmxOmuLo4kN55Vrlq~|X2vsly=KwgX!+Zm^vlNH{pZXXZoZ(d;@uQ? z({1m{K9`aJ@|z+9pS8xbuIQ{HreZdRNw7+_wR0XPhhc`8tO9(WdMK+D47OJ7K-~4K z(Ck0#gf)lFTg+`V%t#jS1X|&dr!zR(O3zCZ!kDI{=0xqy1d_CwYT5i`X3lFgAGj4c z+;pXl4rIf%?=2TO0{g{?^0r6t1cJ7wo$K=SvW&kaCoA84V&%`J=P$2uhhq%^r#4}F zczV}j-DVWvYZsui2ZPyuT{gBk#9xNb?aR3*K!Yc1oxi4dISb6}F=Kw)~oy0zfqVt%EbknU1cOjjH&f(?bTI}D&JAQRut#k)8J5@SVI8z~MPIeqS;^x$@tdv9Czr_(F8*!D{^nJNncR-F2ypetm4?~ zeD=03-8MQ8bqeYpc`ACQSL1ZQpE7=afd18oB^=%Qdm_RgQ6mU5kcctROc06epPS3< z^mQG}573>W<0uhGfb{<1O>wwO&djGg*48@GnA4YP;9J|1@#lm5Z+;ft2ZCkHJ8ZrT zu>;iwEPkr>e+A)NZjn&>u41YZ{=2JEgYKX8XWymMgs9dRJ`xf9r1B1$h6i{5QuY>A#^$mKUg@tsUIg`X%AS}+Q~~_82-qaGs$({riQ^*wCU1A zE1~cc=7+1;5>Df)1JeZ;ZKR#o>=ENI;QVQum_ww(OXRFz!SAXF{C+FV2XtK|c4ry_ z0y0^1DG{UM!{KLO;Ae`qj0?U=>wPB~oKP`02sBn3)I%x;3nAG7$z#%Iw{I;9rmq=n z2Q3Pzj;LS#NYx-D7m!BFoC7GZk6pzA>4i8aTl|*iIjqg4PFm{zOC;;gAW!DWde9;; zrH<1wSj0l0KB7fLA%pgT%`QZ3)BkI#trWsNWvglr7c>Ed1Cr!nJ?<@8qOWsNhLqV_I% zy9%XOi+0U<2;PuXvnkK?{`dTv7Q8dE7Ov(^E*eQyMkCp=9%pt-E&5@I*<>52*&x*8 zjR6HoFyuf^a82=ut_Q3Z&`wiJyL1;f~b9L0}?Ozyn(u`FSxglbku5OIQLT)MV_? zMdD^X4_<%)H{>7iv}E~cguoZWNru3`oG7;%DGihT>q8N6$_%KQyl=i^7i(1ad?qh<#kEd$@wlZt1G9j7$K?c5ta`@<7!B6A67Y?X@XWR46fWxMwn7<;m;>G5ZxIB} zk9qjZE-%pCw&$jh?KV)`)qdhn2NC6j9Ua;SJ{x488Qk>WKlo4aqt2(r)D^__0%8}@ z$dJ73H_$uxhyS7!*B2&01TB|=RmYb#{Ah$`WM%E+EG#3$DI+L;yt^5QSb6Fk-eIw= zlf%gJzP+`7U@RI19e~V3p*j0R@G|j%M5{@y{wl4x*O_KBV9*8yYU-&~66MLI^nA~g zejFCzpJ#1<(yB~9y?Z9a1PbNn>myNyT?%if*-U1(qd|PEBPW;sDkaWwzD$<}dwzDe z+RC!q*<*aZD~Yqc8AB|lYBn8j1-5g52F9DvdjH5eI7uo4fL9cKyDiJ{E<}Q0mkyCw zybs33J9aX*s$Lr0K9eqRMBqrtoZ%_>0i1yqjYF`<}Upjy|c%1d1H+8rV- zHJhO_liZ-WAlppl{5m(kW^@01{tpbK)?^5pG)rzcl)o~UvK5YP+oMuB`=fugB?La0sJY{aLgANDjg4=dW+tV8Tgb=8@b z8g?^ib0G9zesJ)OL2bZ=H8EmFKkYmkr^HoJLKSXmI`>5=FOCOeeJ}P3*i$S@_>S!l zhlS^zGmmSr&jP&_R{1aF3Dw{bj<-AqZN10cYh9%(NG^#?q~UPP4Pt5sAasQUK;OR6@`*WU@*qs`?4G28Vr zv1v=?O2>E+R=%&lH1vA@`xU1&OZo5B2oBNIN&Tm&5-+c&x;pj#)~u#Qv(5d5>o{Rb zxLvQ*2Mnm&rN?sZDz*y!YB;(0GK=&?OC*W&X~BMv*h*&FD1N<~V{v(S&kHE(nLd+b z;N#1&eZsUvvj(JD%OrOHN4=?;{!yAo$b-im+pi3|9gBW(E6ei_dyIhKdRdMpCx*>-P!4jzea1O0)e>sC*S zH~T@0j&B&g`_nBLZhK^W`0D1X8z-m)R75o8;yo4_n2AAKyf2uith@=?81SscXqm_; zlOdh>AC8dGYoe8>{(gr~!7#zQ_#mG&;`8)a-mupk=Ryk3bI=)Kj~d@efYb=)bzXZ{ z^?abga;^G0Sue#AY6!-P_QfuC3%d6(8I)MLu0XziTnbeqKet(1AiwJxpB2zo8_))H zM(kzR^BwxD;>C_sK#2@W*)n9UKK*ylF&p*!3bz7>QUwc!0K-O&?zfF|+q7Sp_Rvyj zYwz6-E5elV1D~X|lRT-WgiQlj=M1K42gsX?JpxCFvK>gGi$$WWY>_>feZU4O7>P3$ z4o_q1+#R8S&#IAr;SG}6n~WU2#527lBo+%-kU-+9!`uqTtqc9l8bTIQ3qGPqLK)qlIkd5T?I&yJzyHyTrU5KGT9}G z;S=o7?m`9~)7%ufD&&5Z{~7rEw^Qv=ozG5Ag2EJm`jX3^iC~56>j>nj$6eKx6g{s? zRc~*gz`6~}hJ{y!-fkq1!pFvC*hS!Mq6aEY+M1Fkgn0&%o6LPYnoYPCnm$}n2N4p# z5}cp^jOp+bH%l;oxcMb{%r(h3A5}IE$xqV^q}@&9J_xN%F9Yk=G*(Us*w_of$~i@b zZbZ2J+WE`Z5kx5$Z1(k%#oqw8*fBB_+o>Rm_e{wvv{zu6Fw{w-rX14o}E6FqxYr1PX#7)U{M^<2s2glSuWmIx zXE|kJ5A`fEuhv!}Ah%a96kQfz9e-O!n3x_`28Ed1OVbC#CndHAO9M705}Imr6Dv=U zohSl-Y6o4k*;}tRh4Ew7ZP#?u09H+Fo*zeC*Xa@SahOpPiF&&gc~RDRg~O?f;iZoe zem(|9xg5m(Y7^`RvX0S)Q37CQv@gTP1~GhrN*MD-Y_y}FnP3T@*g ze1tYu&<`K3?lCz9+|c{t1>O%f`%}vPiY@pTXREuqXk<-t?62y#sm}-b1I$H#%Df;M z_r61TBv>c`!-RpvPq14m2s)5cS-C=};)a9&yVlS?QJyffAdo?3`iq6?scrgC_fbx;wdV%I>)_R%VvExWG$N+H3kgIm;=oMn45Vu*Vkqi`Q$Q z?swRt?Oo+GMO)67-}lB$AM5GqJ^lTd=k}j8M?OudesLDD9Kkjgi3C51F~|?22u)Kp zXV}!P=T6K{1P&awhV=Z6?8?6FwQmW(=BBpN zdKfjx)3<)~9)HZEu5BYVAb9bN>%Qy#;*zn1ghL0?{~Y7foc`Zpg#VxK8P9V7{}fiE z(nTt{C!4NMk3Y4wHz%}flpM8_Xz42<$Y2Fp1+$flqzI$a?zhmtfWrBl1%NJ@wnn1y z*FQAgdSa$=q_QTw7o2ldu!0GP1&*E~>i$w{q)_FaN4%6id*`~tzXbqxb^x6XkttDh zJyIT|?fTd2JNdxs547HY5MgXC#SEX%F9M%Gm-G;wL@fk5b zY^#iCEPzyErLv(N7M7&zz^{HK&!E8nnb1z7C=|+(YrW1fRlo85G&Lj;P&8k7q#Rhe zx{Sx=OaJ2gd(d$F=;%1Ng`na7b9&ImuHZLDxAKhSHgr3-hnfJ<&7`4y@i+8(A0 zFX=EjPPDK1g{wIQY(?X_MCfeIy=G>v|J-Q&YZ}~2D?tVqlN^4tshJB`WrOYU7Xt7EDrB7pAH?r) z+qva9n*Y=T3RBS74PQ&Z8h^=tGgs((7$=gs=$E!rN+KUw;jT*HlA zz5_A?_SZq)yE2&G*lAUGYR|*ksiG3IowIkX69*e=e7)~@ISFki0nwLII|{70)X$#O z0fuiIVs+!^b250ovy}ufy2j~o(Yh(W=<)A`>XuXA(+z>Bzn`y}UH1bi1(i`9=NNz; z%=$J*u+q5C9@<|5InzW*@6#Z4bHraF9T$2CJ5We}Vc<|3^|yX%;lJ^-a%@NO1fcIZ zaHb6ubg&GHo`fxj^^fk`C{c$-zovi1S#(-#UfI|20PyxHSu&ntO1S4()gQuT^Z60O ztSlsAC+4wS5wIYS06b%EHJ=x0{GD&$KJbo-O2?8Dg^kP06it3%U7ts@+)H*E*c+kdE8pAR73K9&c8mKp{srt!DGHHrjU6hGDOAvi^R67B4g7sn6KlA58Y; zh=!L3+Kyz&SzStiZk>x@Lsru)SXCLVqbq!N;5-G(9}Mzvwt}*H^@bs7U;&9$jyu*T zkDFuuqEK4FOY;2M4K?Y#i917L!<_ZnG>+7FbSg#$-e?(LWLzB0RJAxPQF@l?DpgGg z91tZv=;Gmm3k&ef7i|)1WdF^R{*&r+GSFr{WuHB;jqDmpFlnV5M$YPWh?o!=lV`^8$^xx>m6WKxdU9oQ+dQohbZdxwB82(FNg2!Ld$XQGUQiy-h zTk#QE^y|wTt{DNchI8gs^*!H690cEOPeEEuN7h{~D*=Jx(ekH0_;$5FfCnIm z9i6wEG85P`<6c8=V#eE0|KE0qZh?y>x)v^GC8rM`4V!WBHCG%h`g$tHZJ@ENc{PK4 z&GVTFeX3sfeD>T{;)Q92Y<{m>QLnG>X9x!a!Ci3vYh!J-m(lFn=aJo*+dO0K;sEuX z$w5Xyt)On0z^A~mGUi{L#4k5TpM)7rtYz)Ys7@Kn^>g}vTXhz8Z1;*+DRT#6)|~J9 zzadDjI`GsJ&V5z}r~K@VJp|R^k65!UKiqg^q5errCVru9K#pQ4`XZute5184>#B`4 zkf&dNRpp`Cn339Sz$(;x;UC%Oiy^?S!RhoWdy>S9_ebsFV{9>I}BGG|ChX$fkQYEb@A)y-%K8sr)C;=KCvJRq%YnhuC+sj zzk=`7Ub$hE@b%%GQ5Hu1uA3jxjK3B$T;p8L=7lNo`WDZ0dR}Wi3;536T3@-Wk9VgI zo66@<^PDu_|C30f;#@H<1%K3LF+;DH{T`x|Rd{D|V}xVAsBk+s zpnOJjxKhNFq=RVQVBB=hvm<)qIr3KNBGY0@iblAxCzzBY^|=&o3a$%3I`sph?BzSS zl@`HRB2j`_EmTTs(AoytpN)~JC%s^TH?Pox;>NR23mCGcqW2Iu;lr!4lk5ZT8bUcU85MTk?+>I?mDdGp`0EvLLH znH@-ie_i4$@z!AR)}h!1&Emi;La{8uwa$Os6{ws> zdvbT3@GUsTsaT2(^RCD-zBQoos5o_0%kvsHpNE-lZ;gPse=i63c9nB3wKbV~YO``t^eG~#4q(UiJFwS{iPq33=&YA4 zR*T!8`-zT2$!Nto#-qeR%je)v86L-*;)r_7EaX?s%UM=0de`K&ht|RRS z|Hx8HZt82H*)Jw#Gj)eodi)!6tQtbEb?9qrwQD86#|Ydv^2zDjzahgo-sd7Bn%F|V zSg>niM&BsY`}2-O$;dZp(!LDFVFgL;Ak&)l@xi!%<_A?t>wA6XzGCcj8h^g)&i{yZ z9SmiQvb%9omh+@BIT{jK5}?@aE9a(Ww@&@{O%UD`8?RBm`lN8~-L(X!glptH1-o`Z zB-ZUfF1&E0oXxT(>#6ocjrMK01*^d&=(9NN_3(`JQ>WyLgqN^9%BV#lwU=6SL$Q6% zEQC7eJ3~;PyhRn~!s$6BcL&jXZMW}-s@%9>y9?by-2p%tb+A3?>w@WKOdv1(yLG4( zHhaP;?}2-+^QMsn3JMQ*s20)Qv|yeh zF*ScwSQ>J{_GoF%i$%K7;~&{`qQt~~L^0Fd{qyGKVolE2Fqvvla^NW0NP!@6cN^+2 zj@aD;pP~nK2!h0_e`K?)EMM2DHb8a}^xW}O@*i1EXtf=CSGDk`T89th z@ejjwRC#8-cg-n@uZ&hEj%V))xXVXJ8I0Ay8ofWMkEk{mQJ12kHshpj1d9b0T% z+ubl*C1vGJB||1j@0ulJnDW8QB%QZ>A4?j^eW~(S;P(0cH&+1aoZd|E!||EEFM+x_ z9MEDVmFiza+FVvk{84k(RU?LIE=P(Kw`4t@vWW`m4`B}6e=&4|;uTlf0=>4l{BB zBKPT)?`Ow0iPYe(mEA%-gfvwVHZ|uvKRjarogL)!XJR~tB)cDS2?neft;7x|ymEVF z$;|_L`Ul?ga3s{j_=HAq1AoJ%<+*Z2_aoa&13C)SU{GqiMj@k42q}~O|%8$i*6yvCSn3HSwOT-*^I+H)yaQ?j2o+8Um4oDE) zKOkVvEp{%aff|8(Rv?7bk|DO9NS{ukYF+}xEK+(1lM`}!OMG6U@(tV+-IX zuE;2Fn=|M=X|@{xh;zvIBc4^ht-r_LJFta*oU{h&%`}fj*516Y^YZ5X_lEUqK zyGJ2t=0P>i5Pgo^EMD^AcBjS^x@n4)oEI<dn&9;&3Cj z_B8{iWW_O01q%v5s0sYB#QW`CXJ8sn;gGBwQ-YpldPWw`<>oVz-(hwiX-#g#`J*`F z80!)ky@QW9z!F5M->Flix3QbftkPTEc*178$zG0b97cV<55->@LA@CT)CuM>B$z_-dk*=Cr*Op4x4a!QeB(AM*KekkO=$j^TlIrBjxO zxs3hdJ%rMBAIV1nUdVE%6W_a<%+R?u7@C!ib z;T~CJW-6bX0f>dDV1*Z4@!KR|I~(LjWW35Q_n245bj_S~l<*tc7qsFI&ETN}gwx-K zh8)(qw4cXJOGT;3hj>E4OBwA|v0u0iV2Y=o@Ea({%h(Go9j(}gIOmp@c?Y;JM>ecAEUbO5jSCJ=Y-Y13jz2EVR z4u}Vjp;7m5=a{`lWg)#DNuQLfcGdhOdf#ty=fB!NMEEQZy!(<=wBJ-7yB1Il06^_~ z*d?Fn)7VQHg37xlyM;5-b3AQM`5=E*Y5xYANqS_i$I&Ek0>2aZunpH90%)id?v6Sq z-`vk!mcKr(3H`}x^9IFyWc}{tW7B~(@|c_cnwMZiCs&(vAZC#f)xwzTIEMJ>aLVB5 zUEw%WKb+O{B^rT$WrE*E?^l+>_Vc~qoMfaEE8{6qdJyB~$I|S%*g=!RKG5?Oekv?fuTuBxc zlN$`EgEBCwoB`#_DbMaJ->)-|!olSxZ0)}7Z?Trk%LIydZSQ(k?vHEr*7pGI{|nLt z#+A=Ml`-{2Y?iFDcJrR|H0YOr1yYc+4GI`UnTFA?fcR!V#0BGZoO{%XyjBnPgP)082K9P`p zx%-Q~mH*UzxqH_gclJ6yaCaN`{K5xnyu8)L&AA24Ac5?S!eDbCc3@br!|&CK}O`GBUOz{-*Dbj!S`kHAp$4D2yPR`>u z@TT@u&F_qvp}j`sp55X2U>`5=cAw!UOSrD`2TZ$;$>2R*owdX!g;^=QUc`}8-rDzk z3C}`P_3@fKIQF1s^KhdY`~tD`bAfsMf7TcTA@Kjecxc}MU_DamFXF!PWi%gF*VOut z?7|iO`K;qX{Pi;86Qw0p_djsw(^!J{GJ?R{hc*uld~}s4Kw>2nAH4(ElrI|HqkRQk zUA&JQ^yDn($YzXKHO8q&fDjc)GwFEc5tW+Qn9doIT6UJ;lyj*9Q{U*Y^WGc1XAIhMmqchNnSS zMJ*I;XC|8f3LA4#1vTJZ6C_1@dds{m!>r#(vZT1}vX7XI3gE`^tkgx~$5$wb_al4F z*c&fx!&YL$d_NXg2|XXW-v(;+yd(R3m~w}bvo@ghQW()Gecb*@rl9WtoB0vM0>EAz zE!qgwqC@pI(l%y*wOaVQecup53idrUkl|6lsM)JadPFB}&B5R5<-R^7^S*@wRRo-B13wP%0#%WoGna{&epD+M$g%pY`7hG!G2VR_0Q60g>| z4QUK=&6_>8hLcq|pwFJwvQC?a0(}X2GX9lkko1J6u@BV|eph+ielVCe^A)h-TOz)+ zgAhxLn!*NnL~x6!XQVdO?!}kDCzm&LcD()%XYU!!=KseJ>z7vTE~92!RBLZF)7BSN zMQKqptx&7>3L>g4TC*sMqH5KMSg}RzP3?*iF>8dxh>-EUuit&n{qTS8bN&zVMB;&5 zm+SL>zoz2+5?ISG?lbx|?~q-oxV4oVlP}mbqJsr}8~T2w9iTsOUZpEW+1Wc3s9eCG z$`a2BJ6l_aG4Bhel*_%}b-hWD zenGi##jf9QU;1mYwNx<6iVLsvi(yVV<`2Cz&)Htn%WV2T68Jrz+r?pexw2ryjd;i9 zCLY9}qXQU6XyDzcQq#Eu0ICC|`^e^{*wK-e?SLsWJve8${Qs$;^#A+06>zH%z+w7% z%e+xenCq{m=RxttbncTL7@!$FA4q0iF~u0+k|L>6I9rRxX%y(H0YeDq&D!{myD2LV z6(8!C8TLJUtLP&&HQ+7@J$sfuu=5v&aBAnY^4#05A0=v) z<(+&Lai_V{0J`H9h>6|}V9)uJFl`s1jRpV^d}iPH2|izH_}Nf`EIRgRcAbH{G#=<`ZC@VWwW0?91a3j|Qr-4T!zpNj~_hydFii9aT}^ z=U2Puo*kx#dn7ArQblQG$sIrO60ev;58PtdN*?v9zx`x@$Q7IZ zC9W)&#>6{LSFM*mUA$t*-u2F8JZ;Pi=ynEJ112qS5fwuAFWJ@*T5LOxMldwTIJFct z2%vY8aFP#JC)$)qW3-f3&1FD#?(i3Va{|yH(Rs+Rc18k~TXoiBhOgjdJ0~&5zb=I! z2iiYYk%#CknUse{%Vg?<5MWXn>8{!i4a#?aj94sex~mbS8QCT0hwjXkOc}QI8Z4Nh ziDNgKzmY>zy26q?+d!2uOA+<5(Z6Bmi67n!LhLWBp2U1ZYr=ozP*}E+IPjeRui)%; zo&&e!+9% zfAhYdx}(N%r8mh3IB(v;N3%e?ZOdRTa@PdJGa&tJR?F~F0KAg)sePi-i6HC^^qt>U8 zTAM&57=okv@{bS)%Lzq>fz7rsL|Vdng$F=$rRNBgdD>@4{t?cUlse4DZBhkUDB4t( zNx3?EweCrB%G5&k2egs(>eX7wy_-(=|1iD$2bfKc5xi8vO@ekqNQPB%JtuSWO_9OY z_R`r5YIDXy`?KN~v9Pgp1FX$-aq&#WXQ-S};~^)X%63;Io$%0OUGD0RCH)pLI8iw) z4ypz6E!Z&>U;o~$qK9zk=Jop7w+QZ#S?a%=gloDYXZk;f;U{OJk<{|d@T+vz zc8WGkkDN*5?QT9vK-L+;o+0$KbIRSUuHKEj^(k2C2cfX{9Mk4o_xy}mH~OBDNjYNn zRWCxt?6LX(;M)B913TEcsbaS*GmpT3UJ6RSzJFivF!qcM2ai)t!wGPEAZx25`Nf%~ zZiv1O?_(A|CZ6DdYkHoMEI@?dEK_mbF%CE4?3$+S|C{G{GuQfPVXU3DNUDBBMCf%JdART{Sl<&pBYf#_=^#SBV>u~o* zRzB-6#8mbys-T>bxA3_80i2*yda@E*e1^qyhm3^(WuIfd zV0HeFQy``ZiTaNLk~GKGB~qQyQ7*zt4qbF=#MEqOWh2k@%l(sbtp$+gL8Ul-X1lCo zf$~4Q)V7|dkLE9IFy@)ktB?;975Vt#eat_0Zf7XxMTpPISoyi@&KqS_A_-b@9Uwqh z7D;ECT&+iuBl5=t-LGZ01T?ywr8A}4S@mJbqO%=&@%+Z!zEHVGlk3Uy2J5=B^m5`djdE5XB(q{sNfee$BQn{$R1@+hWP47x=@#QEUwtMz z3&@aU(`-KcCtkA0-aXro+qlBzV-sLz1tSOYxOxQDOs|{HwTT$e0uCriEJV(P+fBs4 zH?ZC$yeBJN6CfGo<%myGdM@*O2@4^)O%yslZ;emajE*&Y& z!nnXsq>S;}dF0-RJ@idn*3VN^onR#h&{pF&+JNSRzKF}PSF|jA9saS5_%q|SM3pcO zMFHzdQbNmy>(q4t2H3En%Gr!#Eq`iJhDF>eWWrDwc0KJ4)v_uc!wQcNWRWI z)K^h4NrgIc@DXnUmSi{)hyXuMGHy*5 z6Y)+7@WxBL*~jRLD42eyv}syxa3!Ke+@)6RA7YI?q7J?_egKjK-%pX&tY*$O%8SXl zy$ar>92)_lpEqpNh0QnLH=v~iY$oc$!Dh1+D-$-_&-(pbtXY&qz7RBh&#bzi;<9pk zpA%Cy()O~FWYQ+4)wR#sn?#(26{55ZP+gP0ahASbC*gGNhJXG1=p%G?RbPy)oyUny zE!4j&xOToTNIX;Sb?e>IC<_tAQ?@ilnuDMJ1nLJZlPgRn-;(c6<9&H8EF(>)*Fm`zYdn?Oo9 zzrvrN-#5O3?%3oCkYkFstu&_2z%j2=O=nPT5UaM>i??38zOH>*niHLv68_!0q#5J+Ni!JzelCGr~vBTxnhtacDc{nPyE}JkO9bNgJA=Q zdx)?EIU{hKMp44>mHVFiFrx?$b@|<5V;v!x ziYcL`$BWu}hle_0v^ZKKy432%m>7y}0>@JtVed0v+E(4lHsYQ6qd==%|mFA-2) z$0b@pURg0h{_&fRx;OJ>$|k)z5KtI3zi58Ub&^a44U>&XlC->=q%^|7XCa9 zN~B5kQDv61!JMwD3F0Ml>#-eKMlm1&h!3Da%Oe=k+y+D!i+3J>)}~~SSqc*s#OP1V zq&*r_7X9=Y7!mM>n1LHym^ zN5f}l8iqXuYZDk7DbL+l1S5OJVq9x`RH?C_V(9U)}=olI?N43-q==yz(DTN0%fFt zTTsu<7dA45aH8$-OA`YvVo%uhy$DmrjLDu?ILWd?`;;2^QEE%e7GjK90(aI}(Y2kD z5?{~)w^!B)84nmjk}WV%vvb8M7=b@*^ zbn$gj;xB7W$s@)tpfMyZ2Ab>g&<;Hgw3h@v5SI!Wa7Bd66>kFM{7=62*M(($*{R-YGH9dV zhT)xv<=A$ve8MbVx74lS=?E>q49aHN`nkV|8v>oSRLE`ON`a@H(r`i-4uSgDB1G9~ z>Z5ZDCjTVuD`-KQZns+kV^1Ck71I@gfsiUtvw$eQn2?BY0k#j*DSZ0+o(#QP=E@@{ zj+@f9!v_7k8ouDH`kf1D`G$pCYX4}uu7dHN&qN|7#P$<4!&hg@-#5nAtBJ(*400-c zb6Ygpog4A+`eZZUzLc)C0?T|qfIbupf+dFI_>1omkk@u7Atu!Z8;@pqJ zDLOveJ^sSk`^W_g1ZS8nIL00G&Qv^iazom{BMtkDxwe8Alr`?$a9SHE_6KeBb*r)YNx;YTtS|IvPuifFJFS&L5|-=1tex!isGA7k>~pVH%SqfX+YTi%<=V-~NhMV-Md zc{A3{bxwtW;*k|~t1h0C_g&3lN`pfr{RWw9EYO;QiE%#vzI6KiJ_Xm9BxfLp9CdkUB4bzOD%Qo9A-Rpph5ID1!!T6h= z6p*!STfyJ*;1U+hO~}uylA4$M#UJPO$Cgtb)5nR_U}8{SIW*4b5^7CyCMe5K2GLf< zXK||Ux4@oasFh-J6t!7U9R@y}0M7jP6+3?n9ZH zTf(36TE^75SBIG2pKZ?OsNhvj+6uj2Bic^(D6V1Sh{UsoX>}mJqFp8jdBO*<7W&?w z;ygIB!)a||1)lxiE*>@%|JGI*31^`w?j h;+yKJI)*?aoh;8=ajwJ_92}a2nPJ+ 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 a-e1ZcK>4lj@9H_%_%#Q2H@0{R~31+!+^4Cky6! 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
`vjBa-8s-E5G|rwb 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 +#include +#include "Dhcp.h" +#include "Arduino.h" +#include "utility/util.h" + +int DhcpClass::beginWithDHCP(uint8_t *mac, unsigned long timeout, unsigned long responseTimeout) +{ + _dhcpLeaseTime=0; + _dhcpT1=0; + _dhcpT2=0; + _lastCheck=0; + _timeout = timeout; + _responseTimeout = responseTimeout; + + // zero out _dhcpMacAddr + memset(_dhcpMacAddr, 0, 6); + reset_DHCP_lease(); + + memcpy((void*)_dhcpMacAddr, (void*)mac, 6); + _dhcp_state = STATE_DHCP_START; + return request_DHCP_lease(); +} + +void DhcpClass::reset_DHCP_lease(){ + // zero out _dhcpSubnetMask, _dhcpGatewayIp, _dhcpLocalIp, _dhcpDhcpServerIp, _dhcpDnsServerIp + memset(_dhcpLocalIp, 0, 20); +} + +//return:0 on error, 1 if request is sent and response is received +int DhcpClass::request_DHCP_lease(){ + + uint8_t messageType = 0; + + + + // Pick an initial transaction ID + _dhcpTransactionId = random(1UL, 2000UL); + _dhcpInitialTransactionId = _dhcpTransactionId; + + _dhcpUdpSocket.stop(); + if (_dhcpUdpSocket.begin(DHCP_CLIENT_PORT) == 0) + { + // Couldn't get a socket + return 0; + } + + presend_DHCP(); + + int result = 0; + + unsigned long startTime = millis(); + + while(_dhcp_state != STATE_DHCP_LEASED) + { + if(_dhcp_state == STATE_DHCP_START) + { + _dhcpTransactionId++; + + send_DHCP_MESSAGE(DHCP_DISCOVER, ((millis() - startTime) / 1000)); + _dhcp_state = STATE_DHCP_DISCOVER; + } + else if(_dhcp_state == STATE_DHCP_REREQUEST){ + _dhcpTransactionId++; + send_DHCP_MESSAGE(DHCP_REQUEST, ((millis() - startTime)/1000)); + _dhcp_state = STATE_DHCP_REQUEST; + } + else if(_dhcp_state == STATE_DHCP_DISCOVER) + { + uint32_t respId; + messageType = parseDHCPResponse(_responseTimeout, respId); + if(messageType == DHCP_OFFER) + { + // We'll use the transaction ID that the offer came with, + // rather than the one we were up to + _dhcpTransactionId = respId; + send_DHCP_MESSAGE(DHCP_REQUEST, ((millis() - startTime) / 1000)); + _dhcp_state = STATE_DHCP_REQUEST; + } + } + else if(_dhcp_state == STATE_DHCP_REQUEST) + { + uint32_t respId; + messageType = parseDHCPResponse(_responseTimeout, respId); + if(messageType == DHCP_ACK) + { + _dhcp_state = STATE_DHCP_LEASED; + result = 1; + //use default lease time if we didn't get it + if(_dhcpLeaseTime == 0){ + _dhcpLeaseTime = DEFAULT_LEASE; + } + //calculate T1 & T2 if we didn't get it + if(_dhcpT1 == 0){ + //T1 should be 50% of _dhcpLeaseTime + _dhcpT1 = _dhcpLeaseTime >> 1; + } + if(_dhcpT2 == 0){ + //T2 should be 87.5% (7/8ths) of _dhcpLeaseTime + _dhcpT2 = _dhcpT1 << 1; + } + _renewInSec = _dhcpT1; + _rebindInSec = _dhcpT2; + } + else if(messageType == DHCP_NAK) + _dhcp_state = STATE_DHCP_START; + } + + if(messageType == 255) + { + messageType = 0; + _dhcp_state = STATE_DHCP_START; + } + + if(result != 1 && ((millis() - startTime) > _timeout)) + break; + } + + // We're done with the socket now + _dhcpUdpSocket.stop(); + _dhcpTransactionId++; + + return result; +} + +void DhcpClass::presend_DHCP() +{ +} + +void DhcpClass::send_DHCP_MESSAGE(uint8_t messageType, uint16_t secondsElapsed) +{ + uint8_t buffer[32]; + memset(buffer, 0, 32); + IPAddress dest_addr( 255, 255, 255, 255 ); // Broadcast address + + if (-1 == _dhcpUdpSocket.beginPacket(dest_addr, DHCP_SERVER_PORT)) + { + // FIXME Need to return errors + return; + } + + buffer[0] = DHCP_BOOTREQUEST; // op + buffer[1] = DHCP_HTYPE10MB; // htype + buffer[2] = DHCP_HLENETHERNET; // hlen + buffer[3] = DHCP_HOPS; // hops + + // xid + unsigned long xid = htonl(_dhcpTransactionId); + memcpy(buffer + 4, &(xid), 4); + + // 8, 9 - seconds elapsed + buffer[8] = ((secondsElapsed & 0xff00) >> 8); + buffer[9] = (secondsElapsed & 0x00ff); + + // flags + unsigned short flags = htons(DHCP_FLAGSBROADCAST); + memcpy(buffer + 10, &(flags), 2); + + // ciaddr: already zeroed + // yiaddr: already zeroed + // siaddr: already zeroed + // giaddr: already zeroed + + //put data in W5100 transmit buffer + _dhcpUdpSocket.write(buffer, 28); + + memset(buffer, 0, 32); // clear local buffer + + memcpy(buffer, _dhcpMacAddr, 6); // chaddr + + //put data in W5100 transmit buffer + _dhcpUdpSocket.write(buffer, 16); + + memset(buffer, 0, 32); // clear local buffer + + // leave zeroed out for sname && file + // put in W5100 transmit buffer x 6 (192 bytes) + + for(int i = 0; i < 6; i++) { + _dhcpUdpSocket.write(buffer, 32); + } + + // OPT - Magic Cookie + buffer[0] = (uint8_t)((MAGIC_COOKIE >> 24)& 0xFF); + buffer[1] = (uint8_t)((MAGIC_COOKIE >> 16)& 0xFF); + buffer[2] = (uint8_t)((MAGIC_COOKIE >> 8)& 0xFF); + buffer[3] = (uint8_t)(MAGIC_COOKIE& 0xFF); + + // OPT - message type + buffer[4] = dhcpMessageType; + buffer[5] = 0x01; + buffer[6] = messageType; //DHCP_REQUEST; + + // OPT - client identifier + buffer[7] = dhcpClientIdentifier; + buffer[8] = 0x07; + buffer[9] = 0x01; + memcpy(buffer + 10, _dhcpMacAddr, 6); + + // OPT - host name + buffer[16] = hostName; + buffer[17] = strlen(HOST_NAME) + 6; // length of hostname + last 3 bytes of mac address + strcpy((char*)&(buffer[18]), HOST_NAME); + + printByte((char*)&(buffer[24]), _dhcpMacAddr[3]); + printByte((char*)&(buffer[26]), _dhcpMacAddr[4]); + printByte((char*)&(buffer[28]), _dhcpMacAddr[5]); + + //put data in W5100 transmit buffer + _dhcpUdpSocket.write(buffer, 30); + + if(messageType == DHCP_REQUEST) + { + buffer[0] = dhcpRequestedIPaddr; + buffer[1] = 0x04; + buffer[2] = _dhcpLocalIp[0]; + buffer[3] = _dhcpLocalIp[1]; + buffer[4] = _dhcpLocalIp[2]; + buffer[5] = _dhcpLocalIp[3]; + + buffer[6] = dhcpServerIdentifier; + buffer[7] = 0x04; + buffer[8] = _dhcpDhcpServerIp[0]; + buffer[9] = _dhcpDhcpServerIp[1]; + buffer[10] = _dhcpDhcpServerIp[2]; + buffer[11] = _dhcpDhcpServerIp[3]; + + //put data in W5100 transmit buffer + _dhcpUdpSocket.write(buffer, 12); + } + + buffer[0] = dhcpParamRequest; + buffer[1] = 0x06; + buffer[2] = subnetMask; + buffer[3] = routersOnSubnet; + buffer[4] = dns; + buffer[5] = domainName; + buffer[6] = dhcpT1value; + buffer[7] = dhcpT2value; + buffer[8] = endOption; + + //put data in W5100 transmit buffer + _dhcpUdpSocket.write(buffer, 9); + + _dhcpUdpSocket.endPacket(); +} + +uint8_t DhcpClass::parseDHCPResponse(unsigned long responseTimeout, uint32_t& transactionId) +{ + uint8_t type = 0; + uint8_t opt_len = 0; + + unsigned long startTime = millis(); + + while(_dhcpUdpSocket.parsePacket() <= 0) + { + if((millis() - startTime) > responseTimeout) + { + return 255; + } + delay(50); + } + // start reading in the packet + RIP_MSG_FIXED fixedMsg; + _dhcpUdpSocket.read((uint8_t*)&fixedMsg, sizeof(RIP_MSG_FIXED)); + + if(fixedMsg.op == DHCP_BOOTREPLY && _dhcpUdpSocket.remotePort() == DHCP_SERVER_PORT) + { + transactionId = ntohl(fixedMsg.xid); + if(memcmp(fixedMsg.chaddr, _dhcpMacAddr, 6) != 0 || (transactionId < _dhcpInitialTransactionId) || (transactionId > _dhcpTransactionId)) + { + // Need to read the rest of the packet here regardless + _dhcpUdpSocket.flush(); + return 0; + } + + memcpy(_dhcpLocalIp, fixedMsg.yiaddr, 4); + + // Skip to the option part + // Doing this a byte at a time so we don't have to put a big buffer + // on the stack (as we don't have lots of memory lying around) + for (int i =0; i < (240 - (int)sizeof(RIP_MSG_FIXED)); i++) + { + _dhcpUdpSocket.read(); // we don't care about the returned byte + } + + while (_dhcpUdpSocket.available() > 0) + { + switch (_dhcpUdpSocket.read()) + { + case endOption : + break; + + case padOption : + break; + + case dhcpMessageType : + opt_len = _dhcpUdpSocket.read(); + type = _dhcpUdpSocket.read(); + break; + + case subnetMask : + opt_len = _dhcpUdpSocket.read(); + _dhcpUdpSocket.read(_dhcpSubnetMask, 4); + break; + + case routersOnSubnet : + opt_len = _dhcpUdpSocket.read(); + _dhcpUdpSocket.read(_dhcpGatewayIp, 4); + for (int i = 0; i < opt_len-4; i++) + { + _dhcpUdpSocket.read(); + } + break; + + case dns : + opt_len = _dhcpUdpSocket.read(); + _dhcpUdpSocket.read(_dhcpDnsServerIp, 4); + for (int i = 0; i < opt_len-4; i++) + { + _dhcpUdpSocket.read(); + } + break; + + case dhcpServerIdentifier : + opt_len = _dhcpUdpSocket.read(); + if( *((uint32_t*)_dhcpDhcpServerIp) == 0 || + IPAddress(_dhcpDhcpServerIp) == _dhcpUdpSocket.remoteIP() ) + { + _dhcpUdpSocket.read(_dhcpDhcpServerIp, sizeof(_dhcpDhcpServerIp)); + } + else + { + // Skip over the rest of this option + while (opt_len--) + { + _dhcpUdpSocket.read(); + } + } + break; + + case dhcpT1value : + opt_len = _dhcpUdpSocket.read(); + _dhcpUdpSocket.read((uint8_t*)&_dhcpT1, sizeof(_dhcpT1)); + _dhcpT1 = ntohl(_dhcpT1); + break; + + case dhcpT2value : + opt_len = _dhcpUdpSocket.read(); + _dhcpUdpSocket.read((uint8_t*)&_dhcpT2, sizeof(_dhcpT2)); + _dhcpT2 = ntohl(_dhcpT2); + break; + + case dhcpIPaddrLeaseTime : + opt_len = _dhcpUdpSocket.read(); + _dhcpUdpSocket.read((uint8_t*)&_dhcpLeaseTime, sizeof(_dhcpLeaseTime)); + _dhcpLeaseTime = ntohl(_dhcpLeaseTime); + _renewInSec = _dhcpLeaseTime; + break; + + default : + opt_len = _dhcpUdpSocket.read(); + // Skip over the rest of this option + while (opt_len--) + { + _dhcpUdpSocket.read(); + } + break; + } + } + } + + // Need to skip to end of the packet regardless here + _dhcpUdpSocket.flush(); + + return type; +} + + +/* + returns: + 0/DHCP_CHECK_NONE: nothing happened + 1/DHCP_CHECK_RENEW_FAIL: renew failed + 2/DHCP_CHECK_RENEW_OK: renew success + 3/DHCP_CHECK_REBIND_FAIL: rebind fail + 4/DHCP_CHECK_REBIND_OK: rebind success +*/ +int DhcpClass::checkLease(){ + //this uses a signed / unsigned trick to deal with millis overflow + unsigned long now = millis(); + signed long snow = (long)now; + int rc=DHCP_CHECK_NONE; + if (_lastCheck != 0){ + signed long factor; + //calc how many ms past the timeout we are + factor = snow - (long)_secTimeout; + //if on or passed the timeout, reduce the counters + if ( factor >= 0 ){ + //next timeout should be now plus 1000 ms minus parts of second in factor + _secTimeout = snow + 1000 - factor % 1000; + //how many seconds late are we, minimum 1 + factor = factor / 1000 +1; + + //reduce the counters by that mouch + //if we can assume that the cycle time (factor) is fairly constant + //and if the remainder is less than cycle time * 2 + //do it early instead of late + if(_renewInSec < factor*2 ) + _renewInSec = 0; + else + _renewInSec -= factor; + + if(_rebindInSec < factor*2 ) + _rebindInSec = 0; + else + _rebindInSec -= factor; + } + + //if we have a lease but should renew, do it + if (_dhcp_state == STATE_DHCP_LEASED && _renewInSec <=0){ + _dhcp_state = STATE_DHCP_REREQUEST; + rc = 1 + request_DHCP_lease(); + } + + //if we have a lease or is renewing but should bind, do it + if( (_dhcp_state == STATE_DHCP_LEASED || _dhcp_state == STATE_DHCP_START) && _rebindInSec <=0){ + //this should basically restart completely + _dhcp_state = STATE_DHCP_START; + reset_DHCP_lease(); + rc = 3 + request_DHCP_lease(); + } + } + else{ + _secTimeout = snow + 1000; + } + + _lastCheck = now; + return rc; +} + +IPAddress DhcpClass::getLocalIp() +{ + return IPAddress(_dhcpLocalIp); +} + +IPAddress DhcpClass::getSubnetMask() +{ + return IPAddress(_dhcpSubnetMask); +} + +IPAddress DhcpClass::getGatewayIp() +{ + return IPAddress(_dhcpGatewayIp); +} + +IPAddress DhcpClass::getDhcpServerIp() +{ + return IPAddress(_dhcpDhcpServerIp); +} + +IPAddress DhcpClass::getDnsServerIp() +{ + return IPAddress(_dhcpDnsServerIp); +} + +void DhcpClass::printByte(char * buf, uint8_t n ) { + char *str = &buf[1]; + buf[0]='0'; + do { + unsigned long m = n; + n /= 16; + char c = m - 16 * n; + *str-- = c < 10 ? c + '0' : c + 'A' - 10; + } while(n); +} diff --git a/STM32F1/libraries/Ethernet_STM/src/Dhcp.h b/STM32F1/libraries/Ethernet_STM/src/Dhcp.h new file mode 100644 index 0000000..6f9c632 --- /dev/null +++ b/STM32F1/libraries/Ethernet_STM/src/Dhcp.h @@ -0,0 +1,178 @@ +// DHCP Library v0.3 - April 25, 2009 +// Author: Jordan Terrell - blog.jordanterrell.com + +#ifndef Dhcp_h +#define Dhcp_h + +#include "EthernetUdp.h" + +/* DHCP state machine. */ +#define STATE_DHCP_START 0 +#define STATE_DHCP_DISCOVER 1 +#define STATE_DHCP_REQUEST 2 +#define STATE_DHCP_LEASED 3 +#define STATE_DHCP_REREQUEST 4 +#define STATE_DHCP_RELEASE 5 + +#define DHCP_FLAGSBROADCAST 0x8000 + +/* UDP port numbers for DHCP */ +#define DHCP_SERVER_PORT 67 /* from server to client */ +#define DHCP_CLIENT_PORT 68 /* from client to server */ + +/* DHCP message OP code */ +#define DHCP_BOOTREQUEST 1 +#define DHCP_BOOTREPLY 2 + +/* DHCP message type */ +#define DHCP_DISCOVER 1 +#define DHCP_OFFER 2 +#define DHCP_REQUEST 3 +#define DHCP_DECLINE 4 +#define DHCP_ACK 5 +#define DHCP_NAK 6 +#define DHCP_RELEASE 7 +#define DHCP_INFORM 8 + +#define DHCP_HTYPE10MB 1 +#define DHCP_HTYPE100MB 2 + +#define DHCP_HLENETHERNET 6 +#define DHCP_HOPS 0 +#define DHCP_SECS 0 + +#define MAGIC_COOKIE 0x63825363 +#define MAX_DHCP_OPT 16 + +#define HOST_NAME "WIZnet" +#define DEFAULT_LEASE (900) //default lease time in seconds + +#define DHCP_CHECK_NONE (0) +#define DHCP_CHECK_RENEW_FAIL (1) +#define DHCP_CHECK_RENEW_OK (2) +#define DHCP_CHECK_REBIND_FAIL (3) +#define DHCP_CHECK_REBIND_OK (4) + +enum +{ + padOption = 0, + subnetMask = 1, + timerOffset = 2, + routersOnSubnet = 3, + /* timeServer = 4, + nameServer = 5,*/ + dns = 6, + /*logServer = 7, + cookieServer = 8, + lprServer = 9, + impressServer = 10, + resourceLocationServer = 11,*/ + hostName = 12, + /*bootFileSize = 13, + meritDumpFile = 14,*/ + domainName = 15, + /*swapServer = 16, + rootPath = 17, + extentionsPath = 18, + IPforwarding = 19, + nonLocalSourceRouting = 20, + policyFilter = 21, + maxDgramReasmSize = 22, + defaultIPTTL = 23, + pathMTUagingTimeout = 24, + pathMTUplateauTable = 25, + ifMTU = 26, + allSubnetsLocal = 27, + broadcastAddr = 28, + performMaskDiscovery = 29, + maskSupplier = 30, + performRouterDiscovery = 31, + routerSolicitationAddr = 32, + staticRoute = 33, + trailerEncapsulation = 34, + arpCacheTimeout = 35, + ethernetEncapsulation = 36, + tcpDefaultTTL = 37, + tcpKeepaliveInterval = 38, + tcpKeepaliveGarbage = 39, + nisDomainName = 40, + nisServers = 41, + ntpServers = 42, + vendorSpecificInfo = 43, + netBIOSnameServer = 44, + netBIOSdgramDistServer = 45, + netBIOSnodeType = 46, + netBIOSscope = 47, + xFontServer = 48, + xDisplayManager = 49,*/ + dhcpRequestedIPaddr = 50, + dhcpIPaddrLeaseTime = 51, + /*dhcpOptionOverload = 52,*/ + dhcpMessageType = 53, + dhcpServerIdentifier = 54, + dhcpParamRequest = 55, + /*dhcpMsg = 56, + dhcpMaxMsgSize = 57,*/ + dhcpT1value = 58, + dhcpT2value = 59, + /*dhcpClassIdentifier = 60,*/ + dhcpClientIdentifier = 61, + endOption = 255 +}; + +typedef struct _RIP_MSG_FIXED +{ + uint8_t op; + uint8_t htype; + uint8_t hlen; + uint8_t hops; + uint32_t xid; + uint16_t secs; + uint16_t flags; + uint8_t ciaddr[4]; + uint8_t yiaddr[4]; + uint8_t siaddr[4]; + uint8_t giaddr[4]; + uint8_t chaddr[6]; +}RIP_MSG_FIXED; + +class DhcpClass { +private: + uint32_t _dhcpInitialTransactionId; + uint32_t _dhcpTransactionId; + uint8_t _dhcpMacAddr[6]; + uint8_t _dhcpLocalIp[4]; + uint8_t _dhcpSubnetMask[4]; + uint8_t _dhcpGatewayIp[4]; + uint8_t _dhcpDhcpServerIp[4]; + uint8_t _dhcpDnsServerIp[4]; + uint32_t _dhcpLeaseTime; + uint32_t _dhcpT1, _dhcpT2; + signed long _renewInSec; + signed long _rebindInSec; + signed long _lastCheck; + unsigned long _timeout; + unsigned long _responseTimeout; + unsigned long _secTimeout; + uint8_t _dhcp_state; + EthernetUDP _dhcpUdpSocket; + + int request_DHCP_lease(); + void reset_DHCP_lease(); + void presend_DHCP(); + void send_DHCP_MESSAGE(uint8_t, uint16_t); + void printByte(char *, uint8_t); + + uint8_t parseDHCPResponse(unsigned long responseTimeout, uint32_t& transactionId); +public: + IPAddress getLocalIp(); + IPAddress getSubnetMask(); + IPAddress getGatewayIp(); + IPAddress getDhcpServerIp(); + IPAddress getDnsServerIp(); + + int beginWithDHCP(uint8_t *, unsigned long timeout = 60000, unsigned long responseTimeout = 4000); + int checkLease(); +}; + +#endif diff --git a/STM32F1/libraries/Ethernet_STM/src/Dns.cpp b/STM32F1/libraries/Ethernet_STM/src/Dns.cpp new file mode 100644 index 0000000..62e36f8 --- /dev/null +++ b/STM32F1/libraries/Ethernet_STM/src/Dns.cpp @@ -0,0 +1,423 @@ +// Arduino DNS client for WizNet5100-based Ethernet shield +// (c) Copyright 2009-2010 MCQN Ltd. +// Released under Apache License, version 2.0 + +#include "utility/w5100.h" +#include "EthernetUdp.h" +#include "utility/util.h" + +#include "Dns.h" +#include +//#include +#include "Arduino.h" + + +#define SOCKET_NONE 255 +// Various flags and header field values for a DNS message +#define UDP_HEADER_SIZE 8 +#define DNS_HEADER_SIZE 12 +#define TTL_SIZE 4 +#define QUERY_FLAG (0) +#define RESPONSE_FLAG (1<<15) +#define QUERY_RESPONSE_MASK (1<<15) +#define OPCODE_STANDARD_QUERY (0) +#define OPCODE_INVERSE_QUERY (1<<11) +#define OPCODE_STATUS_REQUEST (2<<11) +#define OPCODE_MASK (15<<11) +#define AUTHORITATIVE_FLAG (1<<10) +#define TRUNCATION_FLAG (1<<9) +#define RECURSION_DESIRED_FLAG (1<<8) +#define RECURSION_AVAILABLE_FLAG (1<<7) +#define RESP_NO_ERROR (0) +#define RESP_FORMAT_ERROR (1) +#define RESP_SERVER_FAILURE (2) +#define RESP_NAME_ERROR (3) +#define RESP_NOT_IMPLEMENTED (4) +#define RESP_REFUSED (5) +#define RESP_MASK (15) +#define TYPE_A (0x0001) +#define CLASS_IN (0x0001) +#define LABEL_COMPRESSION_MASK (0xC0) +// Port number that DNS servers listen on +#define DNS_PORT 53 + +// Possible return codes from ProcessResponse +#define SUCCESS 1 +#define TIMED_OUT -1 +#define INVALID_SERVER -2 +#define TRUNCATED -3 +#define INVALID_RESPONSE -4 + +void DNSClient::begin(const IPAddress& aDNSServer) +{ + iDNSServer = aDNSServer; + iRequestId = 0; +} + + +int DNSClient::inet_aton(const char* aIPAddrString, IPAddress& aResult) +{ + // See if we've been given a valid IP address + const char* p =aIPAddrString; + while (*p && + ( (*p == '.') || (*p >= '0') || (*p <= '9') )) + { + p++; + } + + if (*p == '\0') + { + // It's looking promising, we haven't found any invalid characters + p = aIPAddrString; + int segment =0; + int segmentValue =0; + while (*p && (segment < 4)) + { + if (*p == '.') + { + // We've reached the end of a segment + if (segmentValue > 255) + { + // You can't have IP address segments that don't fit in a byte + return 0; + } + else + { + aResult[segment] = (byte)segmentValue; + segment++; + segmentValue = 0; + } + } + else + { + // Next digit + segmentValue = (segmentValue*10)+(*p - '0'); + } + p++; + } + // We've reached the end of address, but there'll still be the last + // segment to deal with + if ((segmentValue > 255) || (segment > 3)) + { + // You can't have IP address segments that don't fit in a byte, + // or more than four segments + return 0; + } + else + { + aResult[segment] = (byte)segmentValue; + return 1; + } + } + else + { + return 0; + } +} + +int DNSClient::getHostByName(const char* aHostname, IPAddress& aResult) +{ + int ret =0; + + // See if it's a numeric IP address + if (inet_aton(aHostname, aResult)) + { + // It is, our work here is done + return 1; + } + + // Check we've got a valid DNS server to use + if (iDNSServer == INADDR_NONE) + { + return INVALID_SERVER; + } + + // Find a socket to use + if (iUdp.begin(1024+(millis() & 0xF)) == 1) + { + // Try up to three times + int retries = 0; +// while ((retries < 3) && (ret <= 0)) + { + // Send DNS request + ret = iUdp.beginPacket(iDNSServer, DNS_PORT); + if (ret != 0) + { + // Now output the request data + ret = BuildRequest(aHostname); + if (ret != 0) + { + // And finally send the request + ret = iUdp.endPacket(); + if (ret != 0) + { + // Now wait for a response + int wait_retries = 0; + ret = TIMED_OUT; + while ((wait_retries < 3) && (ret == TIMED_OUT)) + { + ret = ProcessResponse(5000, aResult); + wait_retries++; + } + } + } + } + retries++; + } + + // We're done with the socket now + iUdp.stop(); + } + + return ret; +} + +uint16_t DNSClient::BuildRequest(const char* aName) +{ + // Build header + // 1 1 1 1 1 1 + // 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 + // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + // | ID | + // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + // |QR| Opcode |AA|TC|RD|RA| Z | RCODE | + // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + // | QDCOUNT | + // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + // | ANCOUNT | + // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + // | NSCOUNT | + // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + // | ARCOUNT | + // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + // As we only support one request at a time at present, we can simplify + // some of this header + iRequestId = millis(); // generate a random ID + uint16_t twoByteBuffer; + + // FIXME We should also check that there's enough space available to write to, rather + // FIXME than assume there's enough space (as the code does at present) + iUdp.write((uint8_t*)&iRequestId, sizeof(iRequestId)); + + twoByteBuffer = htons(QUERY_FLAG | OPCODE_STANDARD_QUERY | RECURSION_DESIRED_FLAG); + iUdp.write((uint8_t*)&twoByteBuffer, sizeof(twoByteBuffer)); + + twoByteBuffer = htons(1); // One question record + iUdp.write((uint8_t*)&twoByteBuffer, sizeof(twoByteBuffer)); + + twoByteBuffer = 0; // Zero answer records + iUdp.write((uint8_t*)&twoByteBuffer, sizeof(twoByteBuffer)); + + iUdp.write((uint8_t*)&twoByteBuffer, sizeof(twoByteBuffer)); + // and zero additional records + iUdp.write((uint8_t*)&twoByteBuffer, sizeof(twoByteBuffer)); + + // Build question + const char* start =aName; + const char* end =start; + uint8_t len; + // Run through the name being requested + while (*end) + { + // Find out how long this section of the name is + end = start; + while (*end && (*end != '.') ) + { + end++; + } + + if (end-start > 0) + { + // Write out the size of this section + len = end-start; + iUdp.write(&len, sizeof(len)); + // And then write out the section + iUdp.write((uint8_t*)start, end-start); + } + start = end+1; + } + + // We've got to the end of the question name, so + // terminate it with a zero-length section + len = 0; + iUdp.write(&len, sizeof(len)); + // Finally the type and class of question + twoByteBuffer = htons(TYPE_A); + iUdp.write((uint8_t*)&twoByteBuffer, sizeof(twoByteBuffer)); + + twoByteBuffer = htons(CLASS_IN); // Internet class of question + iUdp.write((uint8_t*)&twoByteBuffer, sizeof(twoByteBuffer)); + // Success! Everything buffered okay + return 1; +} + + +uint16_t DNSClient::ProcessResponse(uint16_t aTimeout, IPAddress& aAddress) +{ + uint32_t startTime = millis(); + + // Wait for a response packet + while(iUdp.parsePacket() <= 0) + { + if((millis() - startTime) > aTimeout) + return TIMED_OUT; + delay(50); + } + + // We've had a reply! + // Read the UDP header + uint8_t header[DNS_HEADER_SIZE]; // Enough space to reuse for the DNS header + // Check that it's a response from the right server and the right port + if ( (iDNSServer != iUdp.remoteIP()) || + (iUdp.remotePort() != DNS_PORT) ) + { + // It's not from who we expected + return INVALID_SERVER; + } + + // Read through the rest of the response + if (iUdp.available() < DNS_HEADER_SIZE) + { + return TRUNCATED; + } + iUdp.read(header, DNS_HEADER_SIZE); + + uint16_t header_flags = htons(*((uint16_t*)&header[2])); + // Check that it's a response to this request + if ( ( iRequestId != (*((uint16_t*)&header[0])) ) || + ((header_flags & QUERY_RESPONSE_MASK) != (uint16_t)RESPONSE_FLAG) ) + { + // Mark the entire packet as read + iUdp.flush(); + return INVALID_RESPONSE; + } + // Check for any errors in the response (or in our request) + // although we don't do anything to get round these + if ( (header_flags & TRUNCATION_FLAG) || (header_flags & RESP_MASK) ) + { + // Mark the entire packet as read + iUdp.flush(); + return -5; //INVALID_RESPONSE; + } + + // And make sure we've got (at least) one answer + uint16_t answerCount = htons(*((uint16_t*)&header[6])); + if (answerCount == 0 ) + { + // Mark the entire packet as read + iUdp.flush(); + return -6; //INVALID_RESPONSE; + } + + // Skip over any questions + for (uint16_t i =0; i < htons(*((uint16_t*)&header[4])); i++) + { + // Skip over the name + uint8_t len; + do + { + iUdp.read(&len, sizeof(len)); + if (len > 0) + { + // Don't need to actually read the data out for the string, just + // advance ptr to beyond it + while(len--) + { + iUdp.read(); // we don't care about the returned byte + } + } + } while (len != 0); + + // Now jump over the type and class + for (int i =0; i < 4; i++) + { + iUdp.read(); // we don't care about the returned byte + } + } + + // Now we're up to the bit we're interested in, the answer + // There might be more than one answer (although we'll just use the first + // type A answer) and some authority and additional resource records but + // we're going to ignore all of them. + + for (uint16_t i =0; i < answerCount; i++) + { + // Skip the name + uint8_t len; + do + { + iUdp.read(&len, sizeof(len)); + if ((len & LABEL_COMPRESSION_MASK) == 0) + { + // It's just a normal label + if (len > 0) + { + // And it's got a length + // Don't need to actually read the data out for the string, + // just advance ptr to beyond it + while(len--) + { + iUdp.read(); // we don't care about the returned byte + } + } + } + else + { + // This is a pointer to a somewhere else in the message for the + // rest of the name. We don't care about the name, and RFC1035 + // says that a name is either a sequence of labels ended with a + // 0 length octet or a pointer or a sequence of labels ending in + // a pointer. Either way, when we get here we're at the end of + // the name + // Skip over the pointer + iUdp.read(); // we don't care about the returned byte + // And set len so that we drop out of the name loop + len = 0; + } + } while (len != 0); + + // Check the type and class + uint16_t answerType; + uint16_t answerClass; + iUdp.read((uint8_t*)&answerType, sizeof(answerType)); + iUdp.read((uint8_t*)&answerClass, sizeof(answerClass)); + + // Ignore the Time-To-Live as we don't do any caching + for (int i =0; i < TTL_SIZE; i++) + { + iUdp.read(); // we don't care about the returned byte + } + + // And read out the length of this answer + // Don't need header_flags anymore, so we can reuse it here + iUdp.read((uint8_t*)&header_flags, sizeof(header_flags)); + + if ( (htons(answerType) == TYPE_A) && (htons(answerClass) == CLASS_IN) ) + { + if (htons(header_flags) != 4) + { + // It's a weird size + // Mark the entire packet as read + iUdp.flush(); + return -9;//INVALID_RESPONSE; + } + iUdp.read(aAddress.raw_address(), 4); + return SUCCESS; + } + else + { + // This isn't an answer type we're after, move onto the next one + for (uint16_t i =0; i < htons(header_flags); i++) + { + iUdp.read(); // we don't care about the returned byte + } + } + } + + // Mark the entire packet as read + iUdp.flush(); + + // If we get here then we haven't found an answer + return -10;//INVALID_RESPONSE; +} + diff --git a/STM32F1/libraries/Ethernet_STM/src/Dns.h b/STM32F1/libraries/Ethernet_STM/src/Dns.h new file mode 100644 index 0000000..c99f5c3 --- /dev/null +++ b/STM32F1/libraries/Ethernet_STM/src/Dns.h @@ -0,0 +1,41 @@ +// Arduino DNS client for WizNet5100-based Ethernet shield +// (c) Copyright 2009-2010 MCQN Ltd. +// Released under Apache License, version 2.0 + +#ifndef DNSClient_h +#define DNSClient_h + +#include + +class DNSClient +{ +public: + // ctor + void begin(const IPAddress& aDNSServer); + + /** Convert a numeric IP address string into a four-byte IP address. + @param aIPAddrString IP address to convert + @param aResult IPAddress structure to store the returned IP address + @result 1 if aIPAddrString was successfully converted to an IP address, + else error code + */ + int inet_aton(const char *aIPAddrString, IPAddress& aResult); + + /** Resolve the given hostname to an IP address. + @param aHostname Name to be resolved + @param aResult IPAddress structure to store the returned IP address + @result 1 if aIPAddrString was successfully converted to an IP address, + else error code + */ + int getHostByName(const char* aHostname, IPAddress& aResult); + +protected: + uint16_t BuildRequest(const char* aName); + uint16_t ProcessResponse(uint16_t aTimeout, IPAddress& aAddress); + + IPAddress iDNSServer; + uint16_t iRequestId; + EthernetUDP iUdp; +}; + +#endif diff --git a/STM32F1/libraries/Ethernet_STM/src/EthernetClient.cpp b/STM32F1/libraries/Ethernet_STM/src/EthernetClient.cpp new file mode 100644 index 0000000..e14c612 --- /dev/null +++ b/STM32F1/libraries/Ethernet_STM/src/EthernetClient.cpp @@ -0,0 +1,168 @@ +#include "utility/w5100.h" +#include "utility/socket.h" + +extern "C" { + #include "string.h" +} + +#include "Arduino.h" + +#include "Ethernet_STM.h" +#include "EthernetClient.h" +#include "EthernetServer.h" +#include "Dns.h" + +uint16_t EthernetClient::_srcport = 1024; + +EthernetClient::EthernetClient() : _sock(MAX_SOCK_NUM) { +} + +EthernetClient::EthernetClient(uint8_t sock) : _sock(sock) { +} + +int EthernetClient::connect(const char* host, uint16_t port) { + // Look up the host first + int ret = 0; + DNSClient dns; + IPAddress remote_addr; + + dns.begin(Ethernet.dnsServerIP()); + ret = dns.getHostByName(host, remote_addr); + if (ret == 1) { + return connect(remote_addr, port); + } else { + return ret; + } +} + +int EthernetClient::connect(IPAddress ip, uint16_t port) { + if (_sock != MAX_SOCK_NUM) + return 0; + + for (int i = 0; i < MAX_SOCK_NUM; i++) { + uint8_t s = W5100.readSnSR(i); + if (s == SnSR::CLOSED || s == SnSR::FIN_WAIT || s == SnSR::CLOSE_WAIT) { + _sock = i; + break; + } + } + + if (_sock == MAX_SOCK_NUM) + return 0; + + _srcport++; + if (_srcport == 0) _srcport = 1024; + socket(_sock, SnMR::TCP, _srcport, 0); + + if (!::connect(_sock, rawIPAddress(ip), port)) { + _sock = MAX_SOCK_NUM; + return 0; + } + + while (status() != SnSR::ESTABLISHED) { + delay(1); + if (status() == SnSR::CLOSED) { + _sock = MAX_SOCK_NUM; + return 0; + } + } + + return 1; +} + +size_t EthernetClient::write(uint8_t b) { + return write(&b, 1); +} + +size_t EthernetClient::write(const uint8_t *buf, size_t size) { + if (_sock == MAX_SOCK_NUM) { + setWriteError(); + return 0; + } + if (!send(_sock, buf, size)) { + setWriteError(); + return 0; + } + return size; +} + +int EthernetClient::available() { + if (_sock != MAX_SOCK_NUM) + return W5100.getRXReceivedSize(_sock); + return 0; +} + +int EthernetClient::read() { + uint8_t b; + if ( recv(_sock, &b, 1) > 0 ) + { + // recv worked + return b; + } + else + { + // No data available + return -1; + } +} + +int EthernetClient::read(uint8_t *buf, size_t size) { + return recv(_sock, buf, size); +} + +int EthernetClient::peek() { + uint8_t b; + // Unlike recv, peek doesn't check to see if there's any data available, so we must + if (!available()) + return -1; + ::peek(_sock, &b); + return b; +} + +void EthernetClient::flush() { + ::flush(_sock); +} + +void EthernetClient::stop() { + if (_sock == MAX_SOCK_NUM) + return; + + // attempt to close the connection gracefully (send a FIN to other side) + disconnect(_sock); + unsigned long start = millis(); + + // wait a second for the connection to close + while (status() != SnSR::CLOSED && millis() - start < 1000) + delay(1); + + // if it hasn't closed, close it forcefully + if (status() != SnSR::CLOSED) + close(_sock); + + EthernetClass::_server_port[_sock] = 0; + _sock = MAX_SOCK_NUM; +} + +uint8_t EthernetClient::connected() { + if (_sock == MAX_SOCK_NUM) return 0; + + uint8_t s = status(); + return !(s == SnSR::LISTEN || s == SnSR::CLOSED || s == SnSR::FIN_WAIT || + (s == SnSR::CLOSE_WAIT && !available())); +} + +uint8_t EthernetClient::status() { + if (_sock == MAX_SOCK_NUM) return SnSR::CLOSED; + return W5100.readSnSR(_sock); +} + +// the next function allows us to use the client returned by +// EthernetServer::available() as the condition in an if-statement. + +EthernetClient::operator bool() { + return _sock != MAX_SOCK_NUM; +} + +bool EthernetClient::operator==(const EthernetClient& rhs) { + return _sock == rhs._sock && _sock != MAX_SOCK_NUM && rhs._sock != MAX_SOCK_NUM; +} diff --git a/STM32F1/libraries/Ethernet_STM/src/EthernetClient.h b/STM32F1/libraries/Ethernet_STM/src/EthernetClient.h new file mode 100644 index 0000000..1992db0 --- /dev/null +++ b/STM32F1/libraries/Ethernet_STM/src/EthernetClient.h @@ -0,0 +1,39 @@ +#ifndef ethernetclient_h +#define ethernetclient_h +#include "Arduino.h" +#include "Print.h" +#include "Client.h" +#include "IPAddress.h" + +class EthernetClient : public Client { + +public: + EthernetClient(); + EthernetClient(uint8_t sock); + + uint8_t status(); + virtual int connect(IPAddress ip, uint16_t port); + virtual int connect(const char *host, uint16_t port); + virtual size_t write(uint8_t); + virtual size_t write(const uint8_t *buf, size_t size); + virtual int available(); + virtual int read(); + virtual int read(uint8_t *buf, size_t size); + virtual int peek(); + virtual void flush(); + virtual void stop(); + virtual uint8_t connected(); + virtual operator bool(); + virtual bool operator==(const EthernetClient&); + virtual bool operator!=(const EthernetClient& rhs) { return !this->operator==(rhs); }; + + friend class EthernetServer; + + using Print::write; + +private: + static uint16_t _srcport; + uint8_t _sock; +}; + +#endif diff --git a/STM32F1/libraries/Ethernet_STM/src/EthernetServer.cpp b/STM32F1/libraries/Ethernet_STM/src/EthernetServer.cpp new file mode 100644 index 0000000..b9d946d --- /dev/null +++ b/STM32F1/libraries/Ethernet_STM/src/EthernetServer.cpp @@ -0,0 +1,91 @@ +#include "utility/w5100.h" +#include "utility/socket.h" +extern "C" { +#include "string.h" +} + +#include "Ethernet_STM.h" +#include "EthernetClient.h" +#include "EthernetServer.h" + +EthernetServer::EthernetServer(uint16_t port) +{ + _port = port; +} + +void EthernetServer::begin() +{ + for (int sock = 0; sock < MAX_SOCK_NUM; sock++) { + EthernetClient client(sock); + if (client.status() == SnSR::CLOSED) { + socket(sock, SnMR::TCP, _port, 0); + listen(sock); + EthernetClass::_server_port[sock] = _port; + break; + } + } +} + +void EthernetServer::accept() +{ + int listening = 0; + + for (int sock = 0; sock < MAX_SOCK_NUM; sock++) { + EthernetClient client(sock); + + if (EthernetClass::_server_port[sock] == _port) { + if (client.status() == SnSR::LISTEN) { + listening = 1; + } + else if (client.status() == SnSR::CLOSE_WAIT && !client.available()) { + client.stop(); + } + } + } + + if (!listening) { + begin(); + } +} + +EthernetClient EthernetServer::available() +{ + accept(); + + for (int sock = 0; sock < MAX_SOCK_NUM; sock++) { + EthernetClient client(sock); + if (EthernetClass::_server_port[sock] == _port && + (client.status() == SnSR::ESTABLISHED || + client.status() == SnSR::CLOSE_WAIT)) { + if (client.available()) { + // XXX: don't always pick the lowest numbered socket. + return client; + } + } + } + + return EthernetClient(MAX_SOCK_NUM); +} + +size_t EthernetServer::write(uint8_t b) +{ + return write(&b, 1); +} + +size_t EthernetServer::write(const uint8_t *buffer, size_t size) +{ + size_t n = 0; + + accept(); + + for (int sock = 0; sock < MAX_SOCK_NUM; sock++) { + EthernetClient client(sock); + + if (EthernetClass::_server_port[sock] == _port && + client.status() == SnSR::ESTABLISHED) { + n += client.write(buffer, size); + } + } + + return n; +} diff --git a/STM32F1/libraries/Ethernet_STM/src/EthernetServer.h b/STM32F1/libraries/Ethernet_STM/src/EthernetServer.h new file mode 100644 index 0000000..86ccafe --- /dev/null +++ b/STM32F1/libraries/Ethernet_STM/src/EthernetServer.h @@ -0,0 +1,22 @@ +#ifndef ethernetserver_h +#define ethernetserver_h + +#include "Server.h" + +class EthernetClient; + +class EthernetServer : +public Server { +private: + uint16_t _port; + void accept(); +public: + EthernetServer(uint16_t); + EthernetClient available(); + virtual void begin(); + virtual size_t write(uint8_t); + virtual size_t write(const uint8_t *buf, size_t size); + using Print::write; +}; + +#endif diff --git a/STM32F1/libraries/Ethernet_STM/src/EthernetUdp.cpp b/STM32F1/libraries/Ethernet_STM/src/EthernetUdp.cpp new file mode 100644 index 0000000..efddf41 --- /dev/null +++ b/STM32F1/libraries/Ethernet_STM/src/EthernetUdp.cpp @@ -0,0 +1,218 @@ +/* + * Udp.cpp: Library to send/receive UDP packets with the Arduino ethernet shield. + * This version only offers minimal wrapping of socket.c/socket.h + * Drop Udp.h/.cpp into the Ethernet library directory at hardware/libraries/Ethernet/ + * + * MIT License: + * Copyright (c) 2008 Bjoern Hartmann + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * bjoern@cs.stanford.edu 12/30/2008 + */ + +#include "utility/w5100.h" +#include "utility/socket.h" +#include "Ethernet_STM.h" +#include "Udp.h" +#include "Dns.h" + +/* Constructor */ +EthernetUDP::EthernetUDP() : _sock(MAX_SOCK_NUM) {} + +/* Start EthernetUDP socket, listening at local port PORT */ +uint8_t EthernetUDP::begin(uint16_t port) { + if (_sock != MAX_SOCK_NUM) + return 0; + + for (int i = 0; i < MAX_SOCK_NUM; i++) { + uint8_t s = W5100.readSnSR(i); + if (s == SnSR::CLOSED || s == SnSR::FIN_WAIT) { + _sock = i; + break; + } + } + + if (_sock == MAX_SOCK_NUM) + return 0; + + _port = port; + _remaining = 0; + socket(_sock, SnMR::UDP, _port, 0); + + return 1; +} + +/* return number of bytes available in the current packet, + will return zero if parsePacket hasn't been called yet */ +int EthernetUDP::available() { + return _remaining; +} + +/* Release any resources being used by this EthernetUDP instance */ +void EthernetUDP::stop() +{ + if (_sock == MAX_SOCK_NUM) + return; + + close(_sock); + + EthernetClass::_server_port[_sock] = 0; + _sock = MAX_SOCK_NUM; +} + +int EthernetUDP::beginPacket(const char *host, uint16_t port) +{ + // Look up the host first + int ret = 0; + DNSClient dns; + IPAddress remote_addr; + + dns.begin(Ethernet.dnsServerIP()); + ret = dns.getHostByName(host, remote_addr); + if (ret == 1) { + return beginPacket(remote_addr, port); + } else { + return ret; + } +} + +int EthernetUDP::beginPacket(IPAddress ip, uint16_t port) +{ + _offset = 0; + return startUDP(_sock, rawIPAddress(ip), port); +} + +int EthernetUDP::endPacket() +{ + return sendUDP(_sock); +} + +size_t EthernetUDP::write(uint8_t byte) +{ + return write(&byte, 1); +} + +size_t EthernetUDP::write(const uint8_t *buffer, size_t size) +{ + uint16_t bytes_written = bufferData(_sock, _offset, buffer, size); + _offset += bytes_written; + return bytes_written; +} + +int EthernetUDP::parsePacket() +{ + // discard any remaining bytes in the last packet + flush(); + + if (W5100.getRXReceivedSize(_sock) > 0) + { + //HACK - hand-parse the UDP packet using TCP recv method + uint8_t tmpBuf[8]; + int ret =0; + //read 8 header bytes and get IP and port from it + ret = recv(_sock,tmpBuf,8); + if (ret > 0) + { + _remoteIP = tmpBuf; + _remotePort = tmpBuf[4]; + _remotePort = (_remotePort << 8) + tmpBuf[5]; + _remaining = tmpBuf[6]; + _remaining = (_remaining << 8) + tmpBuf[7]; + + // When we get here, any remaining bytes are the data + ret = _remaining; + } + return ret; + } + // There aren't any packets available + return 0; +} + +int EthernetUDP::read() +{ + uint8_t byte; + + if ((_remaining > 0) && (recv(_sock, &byte, 1) > 0)) + { + // We read things without any problems + _remaining--; + return byte; + } + + // If we get here, there's no data available + return -1; +} + +int EthernetUDP::read(unsigned char* buffer, size_t len) +{ + + if (_remaining > 0) + { + + int got; + + if (_remaining <= len) + { + // data should fit in the buffer + got = recv(_sock, buffer, _remaining); + } + else + { + // too much data for the buffer, + // grab as much as will fit + got = recv(_sock, buffer, len); + } + + if (got > 0) + { + _remaining -= got; + return got; + } + + } + + // If we get here, there's no data available or recv failed + return -1; + +} + +int EthernetUDP::peek() +{ + uint8_t b; + // Unlike recv, peek doesn't check to see if there's any data available, so we must. + // If the user hasn't called parsePacket yet then return nothing otherwise they + // may get the UDP header + if (!_remaining) + return -1; + ::peek(_sock, &b); + return b; +} + +void EthernetUDP::flush() +{ + // could this fail (loop endlessly) if _remaining > 0 and recv in read fails? + // should only occur if recv fails after telling us the data is there, lets + // hope the w5100 always behaves :) + + while (_remaining) + { + read(); + } +} + diff --git a/STM32F1/libraries/Ethernet_STM/src/EthernetUdp.h b/STM32F1/libraries/Ethernet_STM/src/EthernetUdp.h new file mode 100644 index 0000000..8a6b7ab --- /dev/null +++ b/STM32F1/libraries/Ethernet_STM/src/EthernetUdp.h @@ -0,0 +1,99 @@ +/* + * Udp.cpp: Library to send/receive UDP packets with the Arduino ethernet shield. + * This version only offers minimal wrapping of socket.c/socket.h + * Drop Udp.h/.cpp into the Ethernet library directory at hardware/libraries/Ethernet/ + * + * NOTE: UDP is fast, but has some important limitations (thanks to Warren Gray for mentioning these) + * 1) UDP does not guarantee the order in which assembled UDP packets are received. This + * might not happen often in practice, but in larger network topologies, a UDP + * packet can be received out of sequence. + * 2) UDP does not guard against lost packets - so packets *can* disappear without the sender being + * aware of it. Again, this may not be a concern in practice on small local networks. + * For more information, see http://www.cafeaulait.org/course/week12/35.html + * + * MIT License: + * Copyright (c) 2008 Bjoern Hartmann + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * bjoern@cs.stanford.edu 12/30/2008 + */ + +#ifndef ethernetudp_h +#define ethernetudp_h + +#include + +#define UDP_TX_PACKET_MAX_SIZE 24 + +class EthernetUDP : public UDP { +private: + uint8_t _sock; // socket ID for Wiz5100 + uint16_t _port; // local port to listen on + IPAddress _remoteIP; // remote IP address for the incoming packet whilst it's being processed + uint16_t _remotePort; // remote port for the incoming packet whilst it's being processed + uint16_t _offset; // offset into the packet being sent + uint16_t _remaining; // remaining bytes of incoming packet yet to be processed + +public: + EthernetUDP(); // Constructor + virtual uint8_t begin(uint16_t); // initialize, start listening on specified port. Returns 1 if successful, 0 if there are no sockets available to use + virtual void stop(); // Finish with the UDP socket + + // Sending UDP packets + + // Start building up a packet to send to the remote host specific in ip and port + // Returns 1 if successful, 0 if there was a problem with the supplied IP address or port + virtual int beginPacket(IPAddress ip, uint16_t port); + // Start building up a packet to send to the remote host specific in host and port + // Returns 1 if successful, 0 if there was a problem resolving the hostname or port + virtual int beginPacket(const char *host, uint16_t port); + // Finish off this packet and send it + // Returns 1 if the packet was sent successfully, 0 if there was an error + virtual int endPacket(); + // Write a single byte into the packet + virtual size_t write(uint8_t); + // Write size bytes from buffer into the packet + virtual size_t write(const uint8_t *buffer, size_t size); + + using Print::write; + + // Start processing the next available incoming packet + // Returns the size of the packet in bytes, or 0 if no packets are available + virtual int parsePacket(); + // Number of bytes remaining in the current packet + virtual int available(); + // Read a single byte from the current packet + virtual int read(); + // Read up to len bytes from the current packet and place them into buffer + // Returns the number of bytes read, or 0 if none are available + virtual int read(unsigned char* buffer, size_t len); + // Read up to len characters from the current packet and place them into buffer + // Returns the number of characters read, or 0 if none are available + virtual int read(char* buffer, size_t len) { return read((unsigned char*)buffer, len); }; + // Return the next byte from the current packet without moving on to the next byte + virtual int peek(); + virtual void flush(); // Finish reading the current packet + + // Return the IP address of the host who sent the current incoming packet + virtual IPAddress remoteIP() { return _remoteIP; }; + // Return the port of the host who sent the current incoming packet + virtual uint16_t remotePort() { return _remotePort; }; +}; + +#endif diff --git a/STM32F1/libraries/Ethernet_STM/src/Ethernet_STM.cpp b/STM32F1/libraries/Ethernet_STM/src/Ethernet_STM.cpp new file mode 100644 index 0000000..2661fcf --- /dev/null +++ b/STM32F1/libraries/Ethernet_STM/src/Ethernet_STM.cpp @@ -0,0 +1,181 @@ +/* + modified 12 Aug 2013 + by Soohwan Kim (suhwan@wiznet.co.kr) +*/ +#include "Ethernet_STM.h" +#include "Dhcp.h" + +// XXX: don't make assumptions about the value of MAX_SOCK_NUM. +uint8_t EthernetClass::_state[MAX_SOCK_NUM] = { 0, }; +uint16_t EthernetClass::_server_port[MAX_SOCK_NUM] = { 0, }; + +DhcpClass _dhcp; + +#if defined(WIZ550io_WITH_MACADDRESS) +int EthernetClass::begin(void) +{ + byte mac_address[6] ={0,}; + + // Initialise the basic info + W5100.init(); + W5100.setIPAddress(IPAddress(0,0,0,0).raw_address()); + W5100.getMACAddress(mac_address); + + // Now try to get our config info from a DHCP server + int ret = _dhcp.beginWithDHCP(mac_address); + if(ret == 1) + { + // We've successfully found a DHCP server and got our configuration info, so set things + // accordingly + W5100.setIPAddress(_dhcp.getLocalIp().raw_address()); + W5100.setGatewayIp(_dhcp.getGatewayIp().raw_address()); + W5100.setSubnetMask(_dhcp.getSubnetMask().raw_address()); + _dnsServerAddress = _dhcp.getDnsServerIp(); + } + + return ret; +} + +void EthernetClass::begin(IPAddress local_ip) +{ + // Assume the DNS server will be the machine on the same network as the local IP + // but with last octet being '1' + IPAddress dns_server = local_ip; + dns_server[3] = 1; + begin(local_ip, dns_server); +} + +void EthernetClass::begin(IPAddress local_ip, IPAddress dns_server) +{ + // Assume the gateway will be the machine on the same network as the local IP + // but with last octet being '1' + IPAddress gateway = local_ip; + gateway[3] = 1; + begin(local_ip, dns_server, gateway); +} + +void EthernetClass::begin(IPAddress local_ip, IPAddress dns_server, IPAddress gateway) +{ + IPAddress subnet(255, 255, 255, 0); + begin(local_ip, dns_server, gateway, subnet); +} + +void EthernetClass::begin(IPAddress local_ip, IPAddress dns_server, IPAddress gateway, IPAddress subnet) +{ + W5100.init(); + W5100.setIPAddress(local_ip.raw_address()); + W5100.setGatewayIp(gateway.raw_address()); + W5100.setSubnetMask(subnet.raw_address()); + _dnsServerAddress = dns_server; +} +#else +int EthernetClass::begin(uint8_t *mac_address) +{ + // Initialise the basic info + W5100.init(); + W5100.setMACAddress(mac_address); + W5100.setIPAddress(IPAddress(0,0,0,0).raw_address()); + + // Now try to get our config info from a DHCP server + int ret = _dhcp.beginWithDHCP(mac_address); + if(ret == 1) + { + // We've successfully found a DHCP server and got our configuration info, so set things + // accordingly + W5100.setIPAddress(_dhcp.getLocalIp().raw_address()); + W5100.setGatewayIp(_dhcp.getGatewayIp().raw_address()); + W5100.setSubnetMask(_dhcp.getSubnetMask().raw_address()); + _dnsServerAddress = _dhcp.getDnsServerIp(); + } + + return ret; +} + +void EthernetClass::begin(uint8_t *mac_address, IPAddress local_ip) +{ + // Assume the DNS server will be the machine on the same network as the local IP + // but with last octet being '1' + IPAddress dns_server = local_ip; + dns_server[3] = 1; + begin(mac_address, local_ip, dns_server); +} + +void EthernetClass::begin(uint8_t *mac_address, IPAddress local_ip, IPAddress dns_server) +{ + // Assume the gateway will be the machine on the same network as the local IP + // but with last octet being '1' + IPAddress gateway = local_ip; + gateway[3] = 1; + begin(mac_address, local_ip, dns_server, gateway); +} + +void EthernetClass::begin(uint8_t *mac_address, IPAddress local_ip, IPAddress dns_server, IPAddress gateway) +{ + IPAddress subnet(255, 255, 255, 0); + begin(mac_address, local_ip, dns_server, gateway, subnet); +} + +void EthernetClass::begin(uint8_t *mac, IPAddress local_ip, IPAddress dns_server, IPAddress gateway, IPAddress subnet) +{ + W5100.init(); + W5100.setMACAddress(mac); + W5100.setIPAddress(local_ip.raw_address()); + W5100.setGatewayIp(gateway.raw_address()); + W5100.setSubnetMask(subnet.raw_address()); + _dnsServerAddress = dns_server; +} + +#endif + +int EthernetClass::maintain(){ + int rc = DHCP_CHECK_NONE; + //if(_dhcp != NULL){ + //we have a pointer to dhcp, use it + rc = _dhcp.checkLease(); + switch ( rc ){ + case DHCP_CHECK_NONE: + //nothing done + break; + case DHCP_CHECK_RENEW_OK: + case DHCP_CHECK_REBIND_OK: + //we might have got a new IP. + W5100.setIPAddress(_dhcp.getLocalIp().raw_address()); + W5100.setGatewayIp(_dhcp.getGatewayIp().raw_address()); + W5100.setSubnetMask(_dhcp.getSubnetMask().raw_address()); + _dnsServerAddress = _dhcp.getDnsServerIp(); + break; + default: + //this is actually a error, it will retry though + break; + } + //} + return rc; +} + +IPAddress EthernetClass::localIP() +{ + IPAddress ret; + W5100.getIPAddress(ret.raw_address()); + return ret; +} + +IPAddress EthernetClass::subnetMask() +{ + IPAddress ret; + W5100.getSubnetMask(ret.raw_address()); + return ret; +} + +IPAddress EthernetClass::gatewayIP() +{ + IPAddress ret; + W5100.getGatewayIp(ret.raw_address()); + return ret; +} + +IPAddress EthernetClass::dnsServerIP() +{ + return _dnsServerAddress; +} + +EthernetClass Ethernet; diff --git a/STM32F1/libraries/Ethernet_STM/src/Ethernet_STM.h b/STM32F1/libraries/Ethernet_STM/src/Ethernet_STM.h new file mode 100644 index 0000000..d6b6272 --- /dev/null +++ b/STM32F1/libraries/Ethernet_STM/src/Ethernet_STM.h @@ -0,0 +1,60 @@ +/* + modified 12 Aug 2013 + by Soohwan Kim (suhwan@wiznet.co.kr) +*/ +#ifndef ethernet_h +#define ethernet_h + +#include +#include "utility/w5100.h" +#include "IPAddress.h" +#include "EthernetClient.h" +#include "EthernetServer.h" +#include "Dhcp.h" + + + +class EthernetClass { +private: + IPAddress _dnsServerAddress; + //DhcpClass* _dhcp; +public: + static uint8_t _state[MAX_SOCK_NUM]; + static uint16_t _server_port[MAX_SOCK_NUM]; + +#if defined(WIZ550io_WITH_MACADDRESS) + // Initialize function when use the ioShield serise (included WIZ550io) + // WIZ550io has a MAC address which is written after reset. + // Default IP, Gateway and subnet address are also writen. + // so, It needs some initial time. please refer WIZ550io Datasheet in details. + int begin(void); + void begin(IPAddress local_ip); + void begin(IPAddress local_ip, IPAddress dns_server); + void begin(IPAddress local_ip, IPAddress dns_server, IPAddress gateway); + void begin(IPAddress local_ip, IPAddress dns_server, IPAddress gateway, IPAddress subnet); +#else + // Initialize the Ethernet shield to use the provided MAC address and gain the rest of the + // configuration through DHCP. + // Returns 0 if the DHCP configuration failed, and 1 if it succeeded + int begin(uint8_t *mac_address); + void begin(uint8_t *mac_address, IPAddress local_ip); + void begin(uint8_t *mac_address, IPAddress local_ip, IPAddress dns_server); + void begin(uint8_t *mac_address, IPAddress local_ip, IPAddress dns_server, IPAddress gateway); + void begin(uint8_t *mac_address, IPAddress local_ip, IPAddress dns_server, IPAddress gateway, IPAddress subnet); + +#endif + + int maintain(); + + IPAddress localIP(); + IPAddress subnetMask(); + IPAddress gatewayIP(); + IPAddress dnsServerIP(); + + friend class EthernetClient; + friend class EthernetServer; +}; + +extern EthernetClass Ethernet; + +#endif diff --git a/STM32F1/libraries/Ethernet_STM/src/Twitter.cpp b/STM32F1/libraries/Ethernet_STM/src/Twitter.cpp new file mode 100644 index 0000000..026064b --- /dev/null +++ b/STM32F1/libraries/Ethernet_STM/src/Twitter.cpp @@ -0,0 +1,91 @@ +/* + Twitter.cpp - Arduino library to Post messages to Twitter using OAuth. + Copyright (c) NeoCat 2010-2011. All right reserved. + + This library 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. + */ + +// ver1.2 - Use +// ver1.3 - Support IDE 1.0 + +#include +#include "Twitter.h" + +#define LIB_DOMAIN "arduino-tweet.appspot.com" + +#if defined(ARDUINO) && ARDUINO < 100 +static uint8_t server[] = {0,0,0,0}; // IP address of LIB_DOMAIN +Twitter::Twitter(const char *token) : client(server, 80), token(token) +{ +} +#else +Twitter::Twitter(const char *token) : token(token) +{ +} +#endif + +bool Twitter::post(const char *msg) +{ +#if defined(ARDUINO) && ARDUINO < 100 + DNSError err = EthernetDNS.resolveHostName(LIB_DOMAIN, server); + if (err != DNSSuccess) { + return false; + } +#endif + parseStatus = 0; + statusCode = 0; +#if defined(ARDUINO) && ARDUINO < 100 + if (client.connect()) { +#else + if (client.connect(LIB_DOMAIN, 80)) { +#endif + client.println("POST http://" LIB_DOMAIN "/update HTTP/1.0"); + client.print("Content-Length: "); + client.println(strlen(msg)+strlen(token)+14); + client.println(); + client.print("token="); + client.print(token); + client.print("&status="); + client.println(msg); + } else { + return false; + } + return true; +} + +bool Twitter::checkStatus(Print *debug) +{ + if (!client.connected()) { + if (debug) + while(client.available()) + debug->print((char)client.read()); + client.flush(); + client.stop(); + return false; + } + if (!client.available()) + return true; + char c = client.read(); + if (debug) + debug->print(c); + switch(parseStatus) { + case 0: + if (c == ' ') parseStatus++; break; // skip "HTTP/1.1 " + case 1: + if (c >= '0' && c <= '9') { + statusCode *= 10; + statusCode += c - '0'; + } else { + parseStatus++; + } + } + return true; +} + +int Twitter::wait(Print *debug) +{ + while (checkStatus(debug)); + return statusCode; +} diff --git a/STM32F1/libraries/Ethernet_STM/src/Twitter.h b/STM32F1/libraries/Ethernet_STM/src/Twitter.h new file mode 100644 index 0000000..a0edb14 --- /dev/null +++ b/STM32F1/libraries/Ethernet_STM/src/Twitter.h @@ -0,0 +1,46 @@ +/* + Twitter.cpp - Arduino library to Post messages to Twitter using OAuth. + Copyright (c) NeoCat 2010-2011. All right reserved. + + This library 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. + */ + +// ver1.2 - Use to support IDE 0019 or later +// ver1.3 - Support IDE 1.0 + +#ifndef TWITTER_H +#define TWITTER_H + +#include +#include +#if defined(ARDUINO) && ARDUINO > 18 // Arduino 0019 or later +#include +#endif +#include +#if defined(ARDUINO) && ARDUINO < 100 // earlier than Arduino 1.0 +#include +#endif + +class Twitter +{ +private: + uint8_t parseStatus; + int statusCode; + const char *token; +#if defined(ARDUINO) && ARDUINO < 100 + Client client; +#else + EthernetClient client; +#endif +public: + Twitter(const char *user_and_passwd); + + bool post(const char *msg); + bool checkStatus(Print *debug = NULL); + int wait(Print *debug = NULL); + int status(void) { return statusCode; } +}; + +#endif //TWITTER_H diff --git a/STM32F1/libraries/Ethernet_STM/src/util.h b/STM32F1/libraries/Ethernet_STM/src/util.h new file mode 100644 index 0000000..5042e82 --- /dev/null +++ b/STM32F1/libraries/Ethernet_STM/src/util.h @@ -0,0 +1,13 @@ +#ifndef UTIL_H +#define UTIL_H + +#define htons(x) ( ((x)<<8) | (((x)>>8)&0xFF) ) +#define ntohs(x) htons(x) + +#define htonl(x) ( ((x)<<24 & 0xFF000000UL) | \ + ((x)<< 8 & 0x00FF0000UL) | \ + ((x)>> 8 & 0x0000FF00UL) | \ + ((x)>>24 & 0x000000FFUL) ) +#define ntohl(x) htonl(x) + +#endif diff --git a/STM32F1/libraries/Ethernet_STM/src/utility/socket.cpp b/STM32F1/libraries/Ethernet_STM/src/utility/socket.cpp new file mode 100644 index 0000000..5332981 --- /dev/null +++ b/STM32F1/libraries/Ethernet_STM/src/utility/socket.cpp @@ -0,0 +1,406 @@ +#include "utility/w5100.h" +#include "utility/socket.h" + +static uint16_t local_port; + +/** + * @brief This Socket function initialize the channel in perticular mode, and set the port and wait for W5100 done it. + * @return 1 for success else 0. + */ +uint8_t socket(SOCKET s, uint8_t protocol, uint16_t port, uint8_t flag) +{ + if ((protocol == SnMR::TCP) || (protocol == SnMR::UDP) || (protocol == SnMR::IPRAW) || (protocol == SnMR::MACRAW) || (protocol == SnMR::PPPOE)) + { + close(s); + W5100.writeSnMR(s, protocol | flag); + if (port != 0) { + W5100.writeSnPORT(s, port); + } + else { + local_port++; // if don't set the source port, set local_port number. + W5100.writeSnPORT(s, local_port); + } + + W5100.execCmdSn(s, Sock_OPEN); + + return 1; + } + + return 0; +} + + +/** + * @brief This function close the socket and parameter is "s" which represent the socket number + */ +void close(SOCKET s) +{ + W5100.execCmdSn(s, Sock_CLOSE); + W5100.writeSnIR(s, 0xFF); +} + + +/** + * @brief This function established the connection for the channel in passive (server) mode. This function waits for the request from the peer. + * @return 1 for success else 0. + */ +uint8_t listen(SOCKET s) +{ + if (W5100.readSnSR(s) != SnSR::INIT) + return 0; + W5100.execCmdSn(s, Sock_LISTEN); + return 1; +} + + +/** + * @brief This function established the connection for the channel in Active (client) mode. + * This function waits for the untill the connection is established. + * + * @return 1 for success else 0. + */ +uint8_t connect(SOCKET s, uint8_t * addr, uint16_t port) +{ + if + ( + ((addr[0] == 0xFF) && (addr[1] == 0xFF) && (addr[2] == 0xFF) && (addr[3] == 0xFF)) || + ((addr[0] == 0x00) && (addr[1] == 0x00) && (addr[2] == 0x00) && (addr[3] == 0x00)) || + (port == 0x00) + ) + return 0; + + // set destination IP + W5100.writeSnDIPR(s, addr); + W5100.writeSnDPORT(s, port); + W5100.execCmdSn(s, Sock_CONNECT); + + return 1; +} + + + +/** + * @brief This function used for disconnect the socket and parameter is "s" which represent the socket number + * @return 1 for success else 0. + */ +void disconnect(SOCKET s) +{ + W5100.execCmdSn(s, Sock_DISCON); +} + + +/** + * @brief This function used to send the data in TCP mode + * @return 1 for success else 0. + */ +uint16_t send(SOCKET s, const uint8_t * buf, uint16_t len) +{ + uint8_t status=0; + uint16_t ret=0; + uint16_t freesize=0; + + if (len > W5100.SSIZE) + ret = W5100.SSIZE; // check size not to exceed MAX size. + else + ret = len; + + // if freebuf is available, start. + do + { + freesize = W5100.getTXFreeSize(s); + status = W5100.readSnSR(s); + if ((status != SnSR::ESTABLISHED) && (status != SnSR::CLOSE_WAIT)) + { + ret = 0; + break; + } + } + while (freesize < ret); + + // copy data + W5100.send_data_processing(s, (uint8_t *)buf, ret); + W5100.execCmdSn(s, Sock_SEND); + + /* +2008.01 bj */ + while ( (W5100.readSnIR(s) & SnIR::SEND_OK) != SnIR::SEND_OK ) + { + /* m2008.01 [bj] : reduce code */ + if ( W5100.readSnSR(s) == SnSR::CLOSED ) + { + close(s); + return 0; + } + } + /* +2008.01 bj */ + W5100.writeSnIR(s, SnIR::SEND_OK); + return ret; +} + + +/** + * @brief This function is an application I/F function which is used to receive the data in TCP mode. + * It continues to wait for data as much as the application wants to receive. + * + * @return received data size for success else -1. + */ +int16_t recv(SOCKET s, uint8_t *buf, int16_t len) +{ + // Check how much data is available + int16_t ret = W5100.getRXReceivedSize(s); + if ( ret == 0 ) + { + // No data available. + uint8_t status = W5100.readSnSR(s); + if ( status == SnSR::LISTEN || status == SnSR::CLOSED || status == SnSR::CLOSE_WAIT ) + { + // The remote end has closed its side of the connection, so this is the eof state + ret = 0; + } + else + { + // The connection is still up, but there's no data waiting to be read + ret = -1; + } + } + else if (ret > len) + { + ret = len; + } + + if ( ret > 0 ) + { + W5100.recv_data_processing(s, buf, ret); + W5100.execCmdSn(s, Sock_RECV); + } + return ret; +} + + +/** + * @brief Returns the first byte in the receive queue (no checking) + * + * @return + */ +uint16_t peek(SOCKET s, uint8_t *buf) +{ + W5100.recv_data_processing(s, buf, 1, 1); + + return 1; +} + + +/** + * @brief This function is an application I/F function which is used to send the data for other then TCP mode. + * Unlike TCP transmission, The peer's destination address and the port is needed. + * + * @return This function return send data size for success else -1. + */ +uint16_t sendto(SOCKET s, const uint8_t *buf, uint16_t len, uint8_t *addr, uint16_t port) +{ + uint16_t ret=0; + + if (len > W5100.SSIZE) ret = W5100.SSIZE; // check size not to exceed MAX size. + else ret = len; + + if + ( + ((addr[0] == 0x00) && (addr[1] == 0x00) && (addr[2] == 0x00) && (addr[3] == 0x00)) || + ((port == 0x00)) ||(ret == 0) + ) + { + /* +2008.01 [bj] : added return value */ + ret = 0; + } + else + { + W5100.writeSnDIPR(s, addr); + W5100.writeSnDPORT(s, port); + + // copy data + W5100.send_data_processing(s, (uint8_t *)buf, ret); + W5100.execCmdSn(s, Sock_SEND); + + /* +2008.01 bj */ + while ( (W5100.readSnIR(s) & SnIR::SEND_OK) != SnIR::SEND_OK ) + { + if (W5100.readSnIR(s) & SnIR::TIMEOUT) + { + /* +2008.01 [bj]: clear interrupt */ + W5100.writeSnIR(s, (SnIR::SEND_OK | SnIR::TIMEOUT)); /* clear SEND_OK & TIMEOUT */ + return 0; + } + } + + /* +2008.01 bj */ + W5100.writeSnIR(s, SnIR::SEND_OK); + } + return ret; +} + + +/** + * @brief This function is an application I/F function which is used to receive the data in other then + * TCP mode. This function is used to receive UDP, IP_RAW and MAC_RAW mode, and handle the header as well. + * + * @return This function return received data size for success else -1. + */ +uint16_t recvfrom(SOCKET s, uint8_t *buf, uint16_t len, uint8_t *addr, uint16_t *port) +{ + uint8_t head[8]; + uint16_t data_len=0; + uint16_t ptr=0; + + if ( len > 0 ) + { + ptr = W5100.readSnRX_RD(s); + switch (W5100.readSnMR(s) & 0x07) + { + case SnMR::UDP : + W5100.read_data(s, ptr, head, 0x08); + ptr += 8; + // read peer's IP address, port number. + addr[0] = head[0]; + addr[1] = head[1]; + addr[2] = head[2]; + addr[3] = head[3]; + *port = head[4]; + *port = (*port << 8) + head[5]; + data_len = head[6]; + data_len = (data_len << 8) + head[7]; + + W5100.read_data(s, ptr, buf, data_len); // data copy. + ptr += data_len; + + W5100.writeSnRX_RD(s, ptr); + break; + + case SnMR::IPRAW : + W5100.read_data(s, ptr, head, 0x06); + ptr += 6; + + addr[0] = head[0]; + addr[1] = head[1]; + addr[2] = head[2]; + addr[3] = head[3]; + data_len = head[4]; + data_len = (data_len << 8) + head[5]; + + W5100.read_data(s, ptr, buf, data_len); // data copy. + ptr += data_len; + + W5100.writeSnRX_RD(s, ptr); + break; + + case SnMR::MACRAW: + W5100.read_data(s, ptr, head, 2); + ptr+=2; + data_len = head[0]; + data_len = (data_len<<8) + head[1] - 2; + + W5100.read_data(s, ptr, buf, data_len); + ptr += data_len; + W5100.writeSnRX_RD(s, ptr); + break; + + default : + break; + } + W5100.execCmdSn(s, Sock_RECV); + } + return data_len; +} + +/** + * @brief Wait for buffered transmission to complete. + */ +void flush(SOCKET s) { + // TODO +} + +uint16_t igmpsend(SOCKET s, const uint8_t * buf, uint16_t len) +{ + uint8_t status=0; + uint16_t ret=0; + + if (len > W5100.SSIZE) + ret = W5100.SSIZE; // check size not to exceed MAX size. + else + ret = len; + + if (ret == 0) + return 0; + + W5100.send_data_processing(s, (uint8_t *)buf, ret); + W5100.execCmdSn(s, Sock_SEND); + + while ( (W5100.readSnIR(s) & SnIR::SEND_OK) != SnIR::SEND_OK ) + { + status = W5100.readSnSR(s); + if (W5100.readSnIR(s) & SnIR::TIMEOUT) + { + /* in case of igmp, if send fails, then socket closed */ + /* if you want change, remove this code. */ + close(s); + return 0; + } + } + + W5100.writeSnIR(s, SnIR::SEND_OK); + return ret; +} + +uint16_t bufferData(SOCKET s, uint16_t offset, const uint8_t* buf, uint16_t len) +{ + uint16_t ret =0; + if (len > W5100.getTXFreeSize(s)) + { + ret = W5100.getTXFreeSize(s); // check size not to exceed MAX size. + } + else + { + ret = len; + } + W5100.send_data_processing_offset(s, offset, buf, ret); + return ret; +} + +int startUDP(SOCKET s, uint8_t* addr, uint16_t port) +{ + if + ( + ((addr[0] == 0x00) && (addr[1] == 0x00) && (addr[2] == 0x00) && (addr[3] == 0x00)) || + ((port == 0x00)) + ) + { + return 0; + } + else + { + W5100.writeSnDIPR(s, addr); + W5100.writeSnDPORT(s, port); + return 1; + } +} + +int sendUDP(SOCKET s) +{ + W5100.execCmdSn(s, Sock_SEND); + + /* +2008.01 bj */ + while ( (W5100.readSnIR(s) & SnIR::SEND_OK) != SnIR::SEND_OK ) + { + if (W5100.readSnIR(s) & SnIR::TIMEOUT) + { + /* +2008.01 [bj]: clear interrupt */ + W5100.writeSnIR(s, (SnIR::SEND_OK|SnIR::TIMEOUT)); + return 0; + } + } + + /* +2008.01 bj */ + W5100.writeSnIR(s, SnIR::SEND_OK); + + /* Sent ok */ + return 1; +} + diff --git a/STM32F1/libraries/Ethernet_STM/src/utility/socket.h b/STM32F1/libraries/Ethernet_STM/src/utility/socket.h new file mode 100644 index 0000000..682e847 --- /dev/null +++ b/STM32F1/libraries/Ethernet_STM/src/utility/socket.h @@ -0,0 +1,42 @@ +#ifndef _SOCKET_H_ +#define _SOCKET_H_ + +#include "utility/w5100.h" + +extern uint8_t socket(SOCKET s, uint8_t protocol, uint16_t port, uint8_t flag); // Opens a socket(TCP or UDP or IP_RAW mode) +extern void close(SOCKET s); // Close socket +extern uint8_t connect(SOCKET s, uint8_t * addr, uint16_t port); // Establish TCP connection (Active connection) +extern void disconnect(SOCKET s); // disconnect the connection +extern uint8_t listen(SOCKET s); // Establish TCP connection (Passive connection) +extern uint16_t send(SOCKET s, const uint8_t * buf, uint16_t len); // Send data (TCP) +extern int16_t recv(SOCKET s, uint8_t * buf, int16_t len); // Receive data (TCP) +extern uint16_t peek(SOCKET s, uint8_t *buf); +extern uint16_t sendto(SOCKET s, const uint8_t * buf, uint16_t len, uint8_t * addr, uint16_t port); // Send data (UDP/IP RAW) +extern uint16_t recvfrom(SOCKET s, uint8_t * buf, uint16_t len, uint8_t * addr, uint16_t *port); // Receive data (UDP/IP RAW) +extern void flush(SOCKET s); // Wait for transmission to complete + +extern uint16_t igmpsend(SOCKET s, const uint8_t * buf, uint16_t len); + +// Functions to allow buffered UDP send (i.e. where the UDP datagram is built up over a +// number of calls before being sent +/* + @brief This function sets up a UDP datagram, the data for which will be provided by one + or more calls to bufferData and then finally sent with sendUDP. + @return 1 if the datagram was successfully set up, or 0 if there was an error +*/ +extern int startUDP(SOCKET s, uint8_t* addr, uint16_t port); +/* + @brief This function copies up to len bytes of data from buf into a UDP datagram to be + sent later by sendUDP. Allows datagrams to be built up from a series of bufferData calls. + @return Number of bytes successfully buffered +*/ +uint16_t bufferData(SOCKET s, uint16_t offset, const uint8_t* buf, uint16_t len); +/* + @brief Send a UDP datagram built up from a sequence of startUDP followed by one or more + calls to bufferData. + @return 1 if the datagram was successfully sent, or 0 if there was an error +*/ +int sendUDP(SOCKET s); + +#endif +/* _SOCKET_H_ */ diff --git a/STM32F1/libraries/Ethernet_STM/src/utility/util.h b/STM32F1/libraries/Ethernet_STM/src/utility/util.h new file mode 100644 index 0000000..33d32a9 --- /dev/null +++ b/STM32F1/libraries/Ethernet_STM/src/utility/util.h @@ -0,0 +1,14 @@ +#ifndef UTIL_H +#define UTIL_H + +#define htons(x) ( ((x)<< 8 & 0xFF00) | \ + ((x)>> 8 & 0x00FF) ) +#define ntohs(x) htons(x) + +#define htonl(x) ( ((x)<<24 & 0xFF000000UL) | \ + ((x)<< 8 & 0x00FF0000UL) | \ + ((x)>> 8 & 0x0000FF00UL) | \ + ((x)>>24 & 0x000000FFUL) ) +#define ntohl(x) htonl(x) + +#endif diff --git a/STM32F1/libraries/Ethernet_STM/src/utility/w5100.cpp b/STM32F1/libraries/Ethernet_STM/src/utility/w5100.cpp new file mode 100644 index 0000000..cc01184 --- /dev/null +++ b/STM32F1/libraries/Ethernet_STM/src/utility/w5100.cpp @@ -0,0 +1,268 @@ +/* + * Copyright (c) 2010 by Cristian Maglie + * + * This file is free software; you can redistribute it and/or modify + * it under the terms of either the GNU General Public License version 2 + * or the GNU Lesser General Public License version 2.1, both as + * published by the Free Software Foundation. + */ + +#include +#include +//#include + +#include "utility/w5100.h" + +#if defined(W5100_ETHERNET_SHIELD) + +// W5100 controller instance +W5100Class W5100; + +#define SPI_CS 10 +#define STM32_SPI_CS PA4 + +#define TX_RX_MAX_BUF_SIZE 2048 +#define TX_BUF 0x1100 +#define RX_BUF (TX_BUF + TX_RX_MAX_BUF_SIZE) + +#define TXBUF_BASE 0x4000 +#define RXBUF_BASE 0x6000 + +void W5100Class::init(void) +{ + delay(300); + +#if defined(ARDUINO_ARCH_AVR) + SPI.begin(); + initSS(); +#elif defined (__STM32F1__) + pinMode(STM32_SPI_CS, OUTPUT); + SPI.begin(); + SPI.setBitOrder(MSBFIRST); + SPI.setDataMode(SPI_MODE0); + SPI.setClockDivider(SPI_CLOCK_DIV8); + pinMode(STM32_SPI_CS, OUTPUT); +#else + SPI.begin(SPI_CS); + // Set clock to 4Mhz (W5100 should support up to about 14Mhz) + SPI.setClockDivider(SPI_CS, 21); + SPI.setDataMode(SPI_CS, SPI_MODE0); +#endif + writeMR(1< SSIZE) + { + // Wrap around circular buffer + uint16_t size = SSIZE - offset; + write(dstAddr, data, size); + write(SBASE[s], data + size, len - size); + } + else { + write(dstAddr, data, len); + } + + ptr += len; + writeSnTX_WR(s, ptr); +} + + +void W5100Class::recv_data_processing(SOCKET s, uint8_t *data, uint16_t len, uint8_t peek) +{ + uint16_t ptr; + ptr = readSnRX_RD(s); + read_data(s, ptr, data, len); + if (!peek) + { + ptr += len; + writeSnRX_RD(s, ptr); + } +} + +void W5100Class::read_data(SOCKET s, volatile uint16_t src, volatile uint8_t *dst, uint16_t len) +{ + uint16_t size; + uint16_t src_mask; + uint16_t src_ptr; + + src_mask = src & RMASK; + src_ptr = RBASE[s] + src_mask; + + if( (src_mask + len) > RSIZE ) + { + size = RSIZE - src_mask; + read(src_ptr, (uint8_t *)dst, size); + dst += size; + read(RBASE[s], (uint8_t *) dst, len - size); + } + else + read(src_ptr, (uint8_t *) dst, len); +} + + +uint8_t W5100Class::write(uint16_t _addr, uint8_t _data) +{ +#if defined(ARDUINO_ARCH_AVR ) + setSS(); + SPI.transfer(0xF0); + SPI.transfer(_addr >> 8); + SPI.transfer(_addr & 0xFF); + SPI.transfer(_data); + resetSS(); +#elif defined(__STM32F1__) + digitalWrite(STM32_SPI_CS, LOW); + SPI.transfer(0xF0); + SPI.transfer(_addr >> 8); + SPI.transfer(_addr & 0xFF); + SPI.transfer(_data); + digitalWrite(STM32_SPI_CS, HIGH); +#else + SPI.transfer(SPI_CS, 0xF0, SPI_CONTINUE); + SPI.transfer(SPI_CS, _addr >> 8, SPI_CONTINUE); + SPI.transfer(SPI_CS, _addr & 0xFF, SPI_CONTINUE); + SPI.transfer(SPI_CS, _data); +#endif + return 1; +} + +uint16_t W5100Class::write(uint16_t _addr, const uint8_t *_buf, uint16_t _len) +{ + for (uint16_t i=0; i<_len; i++) + { +#if defined(ARDUINO_ARCH_AVR) + setSS(); + SPI.transfer(0xF0); + SPI.transfer(_addr >> 8); + SPI.transfer(_addr & 0xFF); + _addr++; + SPI.transfer(_buf[i]); + resetSS(); +#elif defined(__STM32F1__) + digitalWrite(STM32_SPI_CS, LOW); + SPI.transfer( 0xF0); + SPI.transfer( _addr >> 8); + SPI.transfer( _addr & 0xFF); + _addr++; + SPI.transfer( _buf[i]); + digitalWrite(STM32_SPI_CS, HIGH); +#else + SPI.transfer(SPI_CS, 0xF0, SPI_CONTINUE); + SPI.transfer(SPI_CS, _addr >> 8, SPI_CONTINUE); + SPI.transfer(SPI_CS, _addr & 0xFF, SPI_CONTINUE); + SPI.transfer(SPI_CS, _buf[i]); + _addr++; +#endif + } + return _len; +} + +uint8_t W5100Class::read(uint16_t _addr) +{ +#if defined(ARDUINO_ARCH_AVR) + setSS(); + SPI.transfer(0x0F); + SPI.transfer(_addr >> 8); + SPI.transfer(_addr & 0xFF); + uint8_t _data = SPI.transfer(0); + resetSS(); +#elif defined(__STM32F1__) + digitalWrite(STM32_SPI_CS, LOW); + SPI.transfer(0x0F); + SPI.transfer( _addr >> 8); + SPI.transfer(_addr & 0xFF); + uint8_t _data = SPI.transfer(0); + digitalWrite(STM32_SPI_CS, HIGH); +#else + SPI.transfer(SPI_CS, 0x0F, SPI_CONTINUE); + SPI.transfer(SPI_CS, _addr >> 8, SPI_CONTINUE); + SPI.transfer(SPI_CS, _addr & 0xFF, SPI_CONTINUE); + uint8_t _data = SPI.transfer(SPI_CS, 0); +#endif + return _data; +} + +uint16_t W5100Class::read(uint16_t _addr, uint8_t *_buf, uint16_t _len) +{ + for (uint16_t i=0; i<_len; i++) + { +#if defined(ARDUINO_ARCH_AVR) + setSS(); + SPI.transfer(0x0F); + SPI.transfer(_addr >> 8); + SPI.transfer(_addr & 0xFF); + _addr++; + _buf[i] = SPI.transfer(0); + resetSS(); +#elif defined(__STM32F1__) + digitalWrite(STM32_SPI_CS, LOW); + SPI.transfer(0x0F); + SPI.transfer(_addr >> 8); + SPI.transfer(_addr & 0xFF); + _addr++; + _buf[i] = SPI.transfer(0); + digitalWrite(STM32_SPI_CS, HIGH); +#else + SPI.transfer(SPI_CS, 0x0F, SPI_CONTINUE); + SPI.transfer(SPI_CS, _addr >> 8, SPI_CONTINUE); + SPI.transfer(SPI_CS, _addr & 0xFF, SPI_CONTINUE); + _buf[i] = SPI.transfer(SPI_CS, 0); + _addr++; +#endif + } + return _len; +} + +void W5100Class::execCmdSn(SOCKET s, SockCMD _cmd) { + // Send command to socket + writeSnCR(s, _cmd); + // Wait for command to complete + while (readSnCR(s)) + ; +} + +#endif diff --git a/STM32F1/libraries/Ethernet_STM/src/utility/w5100.h b/STM32F1/libraries/Ethernet_STM/src/utility/w5100.h new file mode 100644 index 0000000..c4233b5 --- /dev/null +++ b/STM32F1/libraries/Ethernet_STM/src/utility/w5100.h @@ -0,0 +1,424 @@ +/* + * Copyright (c) 2013 by WIZnet + * + * This file is free software; you can redistribute it and/or modify + * it under the terms of either the GNU General Public License version 2 + * or the GNU Lesser General Public License version 2.1, both as + * published by the Free Software Foundation. + */ + +#ifndef W5100_H_INCLUDED +#define W5100_H_INCLUDED + +#include + +typedef uint8_t SOCKET; + +//#define W5100_ETHERNET_SHIELD // Arduino Ethenret Shield and Compatibles ... +//#define W5200_ETHERNET_SHIELD // WIZ820io, W5200 Ethernet Shield +#define W5500_ETHERNET_SHIELD // WIZ550io, ioShield series of WIZnet + +#if defined(W5500_ETHERNET_SHIELD) +//#define WIZ550io_WITH_MACADDRESS // Use assigned MAC address of WIZ550io +#include "utility/w5500.h" +#endif + +#if defined(W5200_ETHERNET_SHIELD) +#include "utility/w5200.h" +#endif + +#if defined(W5100_ETHERNET_SHIELD) +#define MAX_SOCK_NUM 4 + +#define IDM_OR 0x8000 +#define IDM_AR0 0x8001 +#define IDM_AR1 0x8002 +#define IDM_DR 0x8003 +/* +class MR { +public: + static const uint8_t RST = 0x80; + static const uint8_t PB = 0x10; + static const uint8_t PPPOE = 0x08; + static const uint8_t LB = 0x04; + static const uint8_t AI = 0x02; + static const uint8_t IND = 0x01; +}; +*/ +/* +class IR { +public: + static const uint8_t CONFLICT = 0x80; + static const uint8_t UNREACH = 0x40; + static const uint8_t PPPoE = 0x20; + static const uint8_t SOCK0 = 0x01; + static const uint8_t SOCK1 = 0x02; + static const uint8_t SOCK2 = 0x04; + static const uint8_t SOCK3 = 0x08; + static inline uint8_t SOCK(SOCKET ch) { return (0x01 << ch); }; +}; +*/ + +class SnMR { +public: + static const uint8_t CLOSE = 0x00; + static const uint8_t TCP = 0x01; + static const uint8_t UDP = 0x02; + static const uint8_t IPRAW = 0x03; + static const uint8_t MACRAW = 0x04; + static const uint8_t PPPOE = 0x05; + static const uint8_t ND = 0x20; + static const uint8_t MULTI = 0x80; +}; + +enum SockCMD { + Sock_OPEN = 0x01, + Sock_LISTEN = 0x02, + Sock_CONNECT = 0x04, + Sock_DISCON = 0x08, + Sock_CLOSE = 0x10, + Sock_SEND = 0x20, + Sock_SEND_MAC = 0x21, + Sock_SEND_KEEP = 0x22, + Sock_RECV = 0x40 +}; + +/*class SnCmd { +public: + static const uint8_t OPEN = 0x01; + static const uint8_t LISTEN = 0x02; + static const uint8_t CONNECT = 0x04; + static const uint8_t DISCON = 0x08; + static const uint8_t CLOSE = 0x10; + static const uint8_t SEND = 0x20; + static const uint8_t SEND_MAC = 0x21; + static const uint8_t SEND_KEEP = 0x22; + static const uint8_t RECV = 0x40; +}; +*/ + +class SnIR { +public: + static const uint8_t SEND_OK = 0x10; + static const uint8_t TIMEOUT = 0x08; + static const uint8_t RECV = 0x04; + static const uint8_t DISCON = 0x02; + static const uint8_t CON = 0x01; +}; + +class SnSR { +public: + static const uint8_t CLOSED = 0x00; + static const uint8_t INIT = 0x13; + static const uint8_t LISTEN = 0x14; + static const uint8_t SYNSENT = 0x15; + static const uint8_t SYNRECV = 0x16; + static const uint8_t ESTABLISHED = 0x17; + static const uint8_t FIN_WAIT = 0x18; + static const uint8_t CLOSING = 0x1A; + static const uint8_t TIME_WAIT = 0x1B; + static const uint8_t CLOSE_WAIT = 0x1C; + static const uint8_t LAST_ACK = 0x1D; + static const uint8_t UDP = 0x22; + static const uint8_t IPRAW = 0x32; + static const uint8_t MACRAW = 0x42; + static const uint8_t PPPOE = 0x5F; +}; + +class IPPROTO { +public: + static const uint8_t IP = 0; + static const uint8_t ICMP = 1; + static const uint8_t IGMP = 2; + static const uint8_t GGP = 3; + static const uint8_t TCP = 6; + static const uint8_t PUP = 12; + static const uint8_t UDP = 17; + static const uint8_t IDP = 22; + static const uint8_t ND = 77; + static const uint8_t RAW = 255; +}; + +class W5100Class { + +public: + void init(); + + /** + * @brief This function is being used for copy the data form Receive buffer of the chip to application buffer. + * + * It calculate the actual physical address where one has to read + * the data from Receive buffer. Here also take care of the condition while it exceed + * the Rx memory uper-bound of socket. + */ + void read_data(SOCKET s, volatile uint16_t src, volatile uint8_t * dst, uint16_t len); + + /** + * @brief This function is being called by send() and sendto() function also. + * + * This function read the Tx write pointer register and after copy the data in buffer update the Tx write pointer + * register. User should read upper byte first and lower byte later to get proper value. + */ + void send_data_processing(SOCKET s, const uint8_t *data, uint16_t len); + /** + * @brief A copy of send_data_processing that uses the provided ptr for the + * write offset. Only needed for the "streaming" UDP API, where + * a single UDP packet is built up over a number of calls to + * send_data_processing_ptr, because TX_WR doesn't seem to get updated + * correctly in those scenarios + * @param ptr value to use in place of TX_WR. If 0, then the value is read + * in from TX_WR + * @return New value for ptr, to be used in the next call + */ +// FIXME Update documentation + void send_data_processing_offset(SOCKET s, uint16_t data_offset, const uint8_t *data, uint16_t len); + + /** + * @brief This function is being called by recv() also. + * + * This function read the Rx read pointer register + * and after copy the data from receive buffer update the Rx write pointer register. + * User should read upper byte first and lower byte later to get proper value. + */ + void recv_data_processing(SOCKET s, uint8_t *data, uint16_t len, uint8_t peek = 0); + + inline void setGatewayIp(uint8_t *_addr); + inline void getGatewayIp(uint8_t *_addr); + + inline void setSubnetMask(uint8_t *_addr); + inline void getSubnetMask(uint8_t *_addr); + + inline void setMACAddress(uint8_t * addr); + inline void getMACAddress(uint8_t * addr); + + inline void setIPAddress(uint8_t * addr); + inline void getIPAddress(uint8_t * addr); + + inline void setRetransmissionTime(uint16_t timeout); + inline void setRetransmissionCount(uint8_t _retry); + + void execCmdSn(SOCKET s, SockCMD _cmd); + + uint16_t getTXFreeSize(SOCKET s); + uint16_t getRXReceivedSize(SOCKET s); + + + // W5100 Registers + // --------------- +private: + static uint8_t write(uint16_t _addr, uint8_t _data); + static uint16_t write(uint16_t addr, const uint8_t *buf, uint16_t len); + static uint8_t read(uint16_t addr); + static uint16_t read(uint16_t addr, uint8_t *buf, uint16_t len); + +#define __GP_REGISTER8(name, address) \ + static inline void write##name(uint8_t _data) { \ + write(address, _data); \ + } \ + static inline uint8_t read##name() { \ + return read(address); \ + } +#define __GP_REGISTER16(name, address) \ + static void write##name(uint16_t _data) { \ + write(address, _data >> 8); \ + write(address+1, _data & 0xFF); \ + } \ + static uint16_t read##name() { \ + uint16_t res = read(address); \ + res = (res << 8) + read(address + 1); \ + return res; \ + } +#define __GP_REGISTER_N(name, address, size) \ + static uint16_t write##name(uint8_t *_buff) { \ + return write(address, _buff, size); \ + } \ + static uint16_t read##name(uint8_t *_buff) { \ + return read(address, _buff, size); \ + } + +public: + __GP_REGISTER8 (MR, 0x0000); // Mode + __GP_REGISTER_N(GAR, 0x0001, 4); // Gateway IP address + __GP_REGISTER_N(SUBR, 0x0005, 4); // Subnet mask address + __GP_REGISTER_N(SHAR, 0x0009, 6); // Source MAC address + __GP_REGISTER_N(SIPR, 0x000F, 4); // Source IP address + __GP_REGISTER8 (IR, 0x0015); // Interrupt + __GP_REGISTER8 (IMR, 0x0016); // Interrupt Mask + __GP_REGISTER16(RTR, 0x0017); // Timeout address + __GP_REGISTER8 (RCR, 0x0019); // Retry count + __GP_REGISTER8 (RMSR, 0x001A); // Receive memory size + __GP_REGISTER8 (TMSR, 0x001B); // Transmit memory size + __GP_REGISTER8 (PATR, 0x001C); // Authentication type address in PPPoE mode + __GP_REGISTER8 (PTIMER, 0x0028); // PPP LCP Request Timer + __GP_REGISTER8 (PMAGIC, 0x0029); // PPP LCP Magic Number + __GP_REGISTER_N(UIPR, 0x002A, 4); // Unreachable IP address in UDP mode + __GP_REGISTER16(UPORT, 0x002E); // Unreachable Port address in UDP mode + +#undef __GP_REGISTER8 +#undef __GP_REGISTER16 +#undef __GP_REGISTER_N + + // W5100 Socket registers + // ---------------------- +private: + static inline uint8_t readSn(SOCKET _s, uint16_t _addr); + static inline uint8_t writeSn(SOCKET _s, uint16_t _addr, uint8_t _data); + static inline uint16_t readSn(SOCKET _s, uint16_t _addr, uint8_t *_buf, uint16_t len); + static inline uint16_t writeSn(SOCKET _s, uint16_t _addr, uint8_t *_buf, uint16_t len); + + static const uint16_t CH_BASE = 0x0400; + static const uint16_t CH_SIZE = 0x0100; + +#define __SOCKET_REGISTER8(name, address) \ + static inline void write##name(SOCKET _s, uint8_t _data) { \ + writeSn(_s, address, _data); \ + } \ + static inline uint8_t read##name(SOCKET _s) { \ + return readSn(_s, address); \ + } +#define __SOCKET_REGISTER16(name, address) \ + static void write##name(SOCKET _s, uint16_t _data) { \ + writeSn(_s, address, _data >> 8); \ + writeSn(_s, address+1, _data & 0xFF); \ + } \ + static uint16_t read##name(SOCKET _s) { \ + uint16_t res = readSn(_s, address); \ + uint16_t res2 = readSn(_s,address + 1); \ + res = res << 8; \ + res2 = res2 & 0xFF; \ + res = res | res2; \ + return res; \ + } +#define __SOCKET_REGISTER_N(name, address, size) \ + static uint16_t write##name(SOCKET _s, uint8_t *_buff) { \ + return writeSn(_s, address, _buff, size); \ + } \ + static uint16_t read##name(SOCKET _s, uint8_t *_buff) { \ + return readSn(_s, address, _buff, size); \ + } + +public: + __SOCKET_REGISTER8(SnMR, 0x0000) // Mode + __SOCKET_REGISTER8(SnCR, 0x0001) // Command + __SOCKET_REGISTER8(SnIR, 0x0002) // Interrupt + __SOCKET_REGISTER8(SnSR, 0x0003) // Status + __SOCKET_REGISTER16(SnPORT, 0x0004) // Source Port + __SOCKET_REGISTER_N(SnDHAR, 0x0006, 6) // Destination Hardw Addr + __SOCKET_REGISTER_N(SnDIPR, 0x000C, 4) // Destination IP Addr + __SOCKET_REGISTER16(SnDPORT, 0x0010) // Destination Port + __SOCKET_REGISTER16(SnMSSR, 0x0012) // Max Segment Size + __SOCKET_REGISTER8(SnPROTO, 0x0014) // Protocol in IP RAW Mode + __SOCKET_REGISTER8(SnTOS, 0x0015) // IP TOS + __SOCKET_REGISTER8(SnTTL, 0x0016) // IP TTL + __SOCKET_REGISTER16(SnTX_FSR, 0x0020) // TX Free Size + __SOCKET_REGISTER16(SnTX_RD, 0x0022) // TX Read Pointer + __SOCKET_REGISTER16(SnTX_WR, 0x0024) // TX Write Pointer + __SOCKET_REGISTER16(SnRX_RSR, 0x0026) // RX Free Size + __SOCKET_REGISTER16(SnRX_RD, 0x0028) // RX Read Pointer + __SOCKET_REGISTER16(SnRX_WR, 0x002A) // RX Write Pointer (supported?) + +#undef __SOCKET_REGISTER8 +#undef __SOCKET_REGISTER16 +#undef __SOCKET_REGISTER_N + + +private: + static const uint8_t RST = 7; // Reset BIT + + static const int SOCKETS = 4; + static const uint16_t SMASK = 0x07FF; // Tx buffer MASK + static const uint16_t RMASK = 0x07FF; // Rx buffer MASK +public: + static const uint16_t SSIZE = 2048; // Max Tx buffer size +private: + static const uint16_t RSIZE = 2048; // Max Rx buffer size + uint16_t SBASE[SOCKETS]; // Tx buffer base address + uint16_t RBASE[SOCKETS]; // Rx buffer base address + +private: +#if defined(ARDUINO_ARCH_AVR) +#if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) || defined(__AVR_ATmega1284P__) + inline static void initSS() { DDRB |= _BV(4); }; + inline static void setSS() { PORTB &= ~_BV(4); }; + inline static void resetSS() { PORTB |= _BV(4); }; +#elif defined(__AVR_ATmega32U4__) + inline static void initSS() { DDRB |= _BV(6); }; + inline static void setSS() { PORTB &= ~_BV(6); }; + inline static void resetSS() { PORTB |= _BV(6); }; +#elif defined(__AVR_AT90USB1286__) || defined(__AVR_AT90USB646__) || defined(__AVR_AT90USB162__) + inline static void initSS() { DDRB |= _BV(0); }; + inline static void setSS() { PORTB &= ~_BV(0); }; + inline static void resetSS() { PORTB |= _BV(0); }; +#elif defined(REL_GR_KURUMI) || defined(REL_GR_KURUMI_PROTOTYPE) + inline static void initSS() { pinMode(SS, OUTPUT); \ + digitalWrite(SS, HIGH); }; + inline static void setSS() { digitalWrite(SS, LOW); }; + inline static void resetSS() { digitalWrite(SS, HIGH); }; +#else + inline static void initSS() { DDRB |= _BV(2); }; + inline static void setSS() { PORTB &= ~_BV(2); }; + inline static void resetSS() { PORTB |= _BV(2); }; +#endif +#endif // ARDUINO_ARCH_AVR +}; + +extern W5100Class W5100; + +uint8_t W5100Class::readSn(SOCKET _s, uint16_t _addr) { + return read(CH_BASE + _s * CH_SIZE + _addr); +} + +uint8_t W5100Class::writeSn(SOCKET _s, uint16_t _addr, uint8_t _data) { + return write(CH_BASE + _s * CH_SIZE + _addr, _data); +} + +uint16_t W5100Class::readSn(SOCKET _s, uint16_t _addr, uint8_t *_buf, uint16_t _len) { + return read(CH_BASE + _s * CH_SIZE + _addr, _buf, _len); +} + +uint16_t W5100Class::writeSn(SOCKET _s, uint16_t _addr, uint8_t *_buf, uint16_t _len) { + return write(CH_BASE + _s * CH_SIZE + _addr, _buf, _len); +} + +void W5100Class::getGatewayIp(uint8_t *_addr) { + readGAR(_addr); +} + +void W5100Class::setGatewayIp(uint8_t *_addr) { + writeGAR(_addr); +} + +void W5100Class::getSubnetMask(uint8_t *_addr) { + readSUBR(_addr); +} + +void W5100Class::setSubnetMask(uint8_t *_addr) { + writeSUBR(_addr); +} + +void W5100Class::getMACAddress(uint8_t *_addr) { + readSHAR(_addr); +} + +void W5100Class::setMACAddress(uint8_t *_addr) { + writeSHAR(_addr); +} + +void W5100Class::getIPAddress(uint8_t *_addr) { + readSIPR(_addr); +} + +void W5100Class::setIPAddress(uint8_t *_addr) { + writeSIPR(_addr); +} + +void W5100Class::setRetransmissionTime(uint16_t _timeout) { + writeRTR(_timeout); +} + +void W5100Class::setRetransmissionCount(uint8_t _retry) { + writeRCR(_retry); +} +#endif + +#endif diff --git a/STM32F1/libraries/Ethernet_STM/src/utility/w5200.cpp b/STM32F1/libraries/Ethernet_STM/src/utility/w5200.cpp new file mode 100644 index 0000000..99650cd --- /dev/null +++ b/STM32F1/libraries/Ethernet_STM/src/utility/w5200.cpp @@ -0,0 +1,303 @@ +/* + * Copyright (c) 2013 by WIZnet + * + * This file is free software; you can redistribute it and/or modify + * it under the terms of either the GNU General Public License version 2 + * or the GNU Lesser General Public License version 2.1, both as + * published by the Free Software Foundation. + */ + +#include +#include +#include "utility/w5100.h" + +#if defined(W5200_ETHERNET_SHIELD) +// W5200 controller instance +W5200Class W5100; + +#define SPI_CS 10 +#define STM32_SPI_CS PA4 + +#define TX_RX_MAX_BUF_SIZE 2048 +#define TX_BUF 0x1100 +#define RX_BUF (TX_BUF + TX_RX_MAX_BUF_SIZE) + + +#define TXBUF_BASE 0x8000 +#define RXBUF_BASE 0xC000 + +void W5200Class::init(void) +{ + delay(300); + +#if defined(ARDUINO_ARCH_AVR) + SPI.begin(); + initSS(); +#elif defined (__STM32F1__) + pinMode(STM32_SPI_CS, OUTPUT); + SPI.begin(); + SPI.setBitOrder(MSBFIRST); + SPI.setDataMode(SPI_MODE0); + SPI.setClockDivider(SPI_CLOCK_DIV4); + pinMode(STM32_SPI_CS, OUTPUT); +#else + SPI.begin(SPI_CS); + // Set clock to 4Mhz (W5100 should support up to about 14Mhz) +// SPI.setClockDivider(SPI_CS, 21); +// SPI.setClockDivider(SPI_CS, 6); // 14 Mhz, ok +// SPI.setClockDivider(SPI_CS, 3); // 28 Mhz, ok + SPI.setClockDivider(SPI_CS, 2); // 42 Mhz, ok + SPI.setDataMode(SPI_CS, SPI_MODE0); +#endif + + writeMR(1< SSIZE) + { + // Wrap around circular buffer + uint16_t size = SSIZE - offset; + write(dstAddr, data, size); + write(SBASE[s], data + size, len - size); + } + else { + write(dstAddr, data, len); + } + + ptr += len; + writeSnTX_WR(s, ptr); +} + + +void W5200Class::recv_data_processing(SOCKET s, uint8_t *data, uint16_t len, uint8_t peek) +{ + uint16_t ptr; + ptr = readSnRX_RD(s); + read_data(s, ptr, data, len); + if (!peek) + { + ptr += len; + writeSnRX_RD(s, ptr); + } +} + +void W5200Class::read_data(SOCKET s, volatile uint16_t src, volatile uint8_t *dst, uint16_t len) +{ + uint16_t size; + uint16_t src_mask; + uint16_t src_ptr; + + src_mask = src & RMASK; + src_ptr = RBASE[s] + src_mask; + + if( (src_mask + len) > RSIZE ) + { + size = RSIZE - src_mask; + read(src_ptr, (uint8_t *)dst, size); + dst += size; + read(RBASE[s], (uint8_t *) dst, len - size); + } + else + read(src_ptr, (uint8_t *) dst, len); +} + + +uint8_t W5200Class::write(uint16_t _addr, uint8_t _data) +{ +#if defined(ARDUINO_ARCH_AVR) + setSS(); + SPI.transfer(_addr >> 8); + SPI.transfer(_addr & 0xFF); + SPI.transfer(0x80); + SPI.transfer(0x01); + SPI.transfer(_data); + resetSS(); +#elif defined(__STM32F1__) + digitalWrite(STM32_SPI_CS, LOW); + SPI.transfer(_addr >> 8); + SPI.transfer(_addr & 0xFF); + SPI.transfer(0x80); + SPI.transfer(0x01); + SPI.transfer(_data); + digitalWrite(STM32_SPI_CS, HIGH); +#else + SPI.transfer(SPI_CS, _addr >> 8, SPI_CONTINUE); + SPI.transfer(SPI_CS, _addr & 0xFF, SPI_CONTINUE); + SPI.transfer(SPI_CS, 0x80, SPI_CONTINUE); + SPI.transfer(SPI_CS, 0x01, SPI_CONTINUE); + SPI.transfer(SPI_CS, _data); +#endif + + return 1; +} + +uint16_t W5200Class::write(uint16_t _addr, const uint8_t *_buf, uint16_t _len) +{ + if (_len == 0) //Fix: a write request with _len == 0 hangs the W5200 + return 0; + +#if defined(ARDUINO_ARCH_AVR) + setSS(); + SPI.transfer(_addr >> 8); + SPI.transfer(_addr & 0xFF); + SPI.transfer((0x80 | ((_len & 0x7F00) >> 8))); + SPI.transfer(_len & 0x00FF); + + for (uint16_t i=0; i<_len; i++) + { + SPI.transfer(_buf[i]); + } + resetSS(); +#elif defined(__STM32F1__) + digitalWrite(STM32_SPI_CS, LOW); + SPI.transfer( _addr >> 8); + SPI.transfer( _addr & 0xFF); + SPI.transfer(0x80 | ((_len & 0x7F00) >> 8)); + SPI.transfer(_len & 0x00FF); + + for (uint16_t i=0; i<(_len-1); i++) + { + SPI.transfer(_buf[i]); + } + SPI.transfer(_buf[_len-1]); + digitalWrite(STM32_SPI_CS, HIGH); +#else + SPI.transfer(SPI_CS, _addr >> 8, SPI_CONTINUE); + SPI.transfer(SPI_CS, _addr & 0xFF, SPI_CONTINUE); + SPI.transfer(SPI_CS, (0x80 | ((_len & 0x7F00) >> 8)), SPI_CONTINUE); + SPI.transfer(SPI_CS, _len & 0x00FF, SPI_CONTINUE); + + for (uint16_t i=0; i<(_len-1); i++) + { + SPI.transfer(SPI_CS, _buf[i], SPI_CONTINUE); + } + SPI.transfer(SPI_CS, _buf[_len-1]); + +#endif + + return _len; +} + +uint8_t W5200Class::read(uint16_t _addr) +{ + +#if defined(ARDUINO_ARCH_AVR) + setSS(); + SPI.transfer(_addr >> 8); + SPI.transfer(_addr & 0xFF); + SPI.transfer(0x00); + SPI.transfer(0x01); + uint8_t _data = SPI.transfer(0); + resetSS(); +#elif defined(__STM32F1__) + SPI.transfer(_addr >> 8); + SPI.transfer(_addr & 0xFF); + SPI.transfer(0x00); + SPI.transfer(0x01); + uint8_t _data = SPI.transfer(0); +#else + SPI.transfer(SPI_CS, _addr >> 8, SPI_CONTINUE); + SPI.transfer(SPI_CS, _addr & 0xFF, SPI_CONTINUE); + SPI.transfer(SPI_CS, 0x00, SPI_CONTINUE); + SPI.transfer(SPI_CS, 0x01, SPI_CONTINUE); + uint8_t _data = SPI.transfer(SPI_CS, 0); +#endif + return _data; +} + +uint16_t W5200Class::read(uint16_t _addr, uint8_t *_buf, uint16_t _len) +{ + +#if defined(ARDUINO_ARCH_AVR) + setSS(); + SPI.transfer(_addr >> 8); + SPI.transfer(_addr & 0xFF); + SPI.transfer((0x00 | ((_len & 0x7F00) >> 8))); + SPI.transfer(_len & 0x00FF); + + for (uint16_t i=0; i<_len; i++) + { + _buf[i] = SPI.transfer(0); + + } + resetSS(); +#elif defined(__STM32F1__) + SPI.transfer(_addr >> 8); + SPI.transfer(_addr & 0xFF); + SPI.transfer(0x00 | ((_len & 0x7F00) >> 8)); + SPI.transfer(_len & 0x00FF); + for (uint16_t i=0; i<(_len-1); i++) + { + _buf[i] = SPI.transfer(0); + } + _buf[_len-1] = SPI.transfer(0); +#else + SPI.transfer(SPI_CS, _addr >> 8, SPI_CONTINUE); + SPI.transfer(SPI_CS, _addr & 0xFF, SPI_CONTINUE); + SPI.transfer(SPI_CS, (0x00 | ((_len & 0x7F00) >> 8)), SPI_CONTINUE); + SPI.transfer(SPI_CS, _len & 0x00FF, SPI_CONTINUE); + for (uint16_t i=0; i<(_len-1); i++) + { + _buf[i] = SPI.transfer(SPI_CS, 0, SPI_CONTINUE); + } + _buf[_len-1] = SPI.transfer(SPI_CS, 0); + +#endif + return _len; +} + +void W5200Class::execCmdSn(SOCKET s, SockCMD _cmd) { + // Send command to socket + writeSnCR(s, _cmd); + // Wait for command to complete + while (readSnCR(s)) + ; +} +#endif diff --git a/STM32F1/libraries/Ethernet_STM/src/utility/w5200.h b/STM32F1/libraries/Ethernet_STM/src/utility/w5200.h new file mode 100644 index 0000000..f40e224 --- /dev/null +++ b/STM32F1/libraries/Ethernet_STM/src/utility/w5200.h @@ -0,0 +1,400 @@ +/* + * Copyright (c) 2013 by WIZnet + * + * This file is free software; you can redistribute it and/or modify + * it under the terms of either the GNU General Public License version 2 + * or the GNU Lesser General Public License version 2.1, both as + * published by the Free Software Foundation. + */ + +#ifndef W5200_H_INCLUDED +#define W5200_H_INCLUDED + +//#include +//#include + +#define MAX_SOCK_NUM 8 +//typedef uint8_t SOCKET; +/* +class MR { +public: + static const uint8_t RST = 0x80; + static const uint8_t PB = 0x10; + static const uint8_t PPPOE = 0x08; + static const uint8_t LB = 0x04; + static const uint8_t AI = 0x02; + static const uint8_t IND = 0x01; +}; +*/ +/* +class IR { +public: + static const uint8_t CONFLICT = 0x80; + static const uint8_t UNREACH = 0x40; + static const uint8_t PPPoE = 0x20; + static const uint8_t SOCK0 = 0x01; + static const uint8_t SOCK1 = 0x02; + static const uint8_t SOCK2 = 0x04; + static const uint8_t SOCK3 = 0x08; + static inline uint8_t SOCK(SOCKET ch) { return (0x01 << ch); }; +}; +*/ + +class SnMR { +public: + static const uint8_t CLOSE = 0x00; + static const uint8_t TCP = 0x01; + static const uint8_t UDP = 0x02; + static const uint8_t IPRAW = 0x03; + static const uint8_t MACRAW = 0x04; + static const uint8_t PPPOE = 0x05; + static const uint8_t ND = 0x20; + static const uint8_t MULTI = 0x80; +}; + +enum SockCMD { + Sock_OPEN = 0x01, + Sock_LISTEN = 0x02, + Sock_CONNECT = 0x04, + Sock_DISCON = 0x08, + Sock_CLOSE = 0x10, + Sock_SEND = 0x20, + Sock_SEND_MAC = 0x21, + Sock_SEND_KEEP = 0x22, + Sock_RECV = 0x40 +}; + +/*class SnCmd { +public: + static const uint8_t OPEN = 0x01; + static const uint8_t LISTEN = 0x02; + static const uint8_t CONNECT = 0x04; + static const uint8_t DISCON = 0x08; + static const uint8_t CLOSE = 0x10; + static const uint8_t SEND = 0x20; + static const uint8_t SEND_MAC = 0x21; + static const uint8_t SEND_KEEP = 0x22; + static const uint8_t RECV = 0x40; +}; +*/ + +class SnIR { +public: + static const uint8_t SEND_OK = 0x10; + static const uint8_t TIMEOUT = 0x08; + static const uint8_t RECV = 0x04; + static const uint8_t DISCON = 0x02; + static const uint8_t CON = 0x01; +}; + +class SnSR { +public: + static const uint8_t CLOSED = 0x00; + static const uint8_t INIT = 0x13; + static const uint8_t LISTEN = 0x14; + static const uint8_t SYNSENT = 0x15; + static const uint8_t SYNRECV = 0x16; + static const uint8_t ESTABLISHED = 0x17; + static const uint8_t FIN_WAIT = 0x18; + static const uint8_t CLOSING = 0x1A; + static const uint8_t TIME_WAIT = 0x1B; + static const uint8_t CLOSE_WAIT = 0x1C; + static const uint8_t LAST_ACK = 0x1D; + static const uint8_t UDP = 0x22; + static const uint8_t IPRAW = 0x32; + static const uint8_t MACRAW = 0x42; + static const uint8_t PPPOE = 0x5F; +}; + +class IPPROTO { +public: + static const uint8_t IP = 0; + static const uint8_t ICMP = 1; + static const uint8_t IGMP = 2; + static const uint8_t GGP = 3; + static const uint8_t TCP = 6; + static const uint8_t PUP = 12; + static const uint8_t UDP = 17; + static const uint8_t IDP = 22; + static const uint8_t ND = 77; + static const uint8_t RAW = 255; +}; + +class W5200Class { + +public: + void init(); + + /** + * @brief This function is being used for copy the data form Receive buffer of the chip to application buffer. + * + * It calculate the actual physical address where one has to read + * the data from Receive buffer. Here also take care of the condition while it exceed + * the Rx memory uper-bound of socket. + */ + void read_data(SOCKET s, volatile uint16_t src, volatile uint8_t * dst, uint16_t len); + + /** + * @brief This function is being called by send() and sendto() function also. + * + * This function read the Tx write pointer register and after copy the data in buffer update the Tx write pointer + * register. User should read upper byte first and lower byte later to get proper value. + */ + void send_data_processing(SOCKET s, const uint8_t *data, uint16_t len); + /** + * @brief A copy of send_data_processing that uses the provided ptr for the + * write offset. Only needed for the "streaming" UDP API, where + * a single UDP packet is built up over a number of calls to + * send_data_processing_ptr, because TX_WR doesn't seem to get updated + * correctly in those scenarios + * @param ptr value to use in place of TX_WR. If 0, then the value is read + * in from TX_WR + * @return New value for ptr, to be used in the next call + */ +// FIXME Update documentation + void send_data_processing_offset(SOCKET s, uint16_t data_offset, const uint8_t *data, uint16_t len); + + /** + * @brief This function is being called by recv() also. + * + * This function read the Rx read pointer register + * and after copy the data from receive buffer update the Rx write pointer register. + * User should read upper byte first and lower byte later to get proper value. + */ + void recv_data_processing(SOCKET s, uint8_t *data, uint16_t len, uint8_t peek = 0); + + inline void setGatewayIp(uint8_t *_addr); + inline void getGatewayIp(uint8_t *_addr); + + inline void setSubnetMask(uint8_t *_addr); + inline void getSubnetMask(uint8_t *_addr); + + inline void setMACAddress(uint8_t * addr); + inline void getMACAddress(uint8_t * addr); + + inline void setIPAddress(uint8_t * addr); + inline void getIPAddress(uint8_t * addr); + + inline void setRetransmissionTime(uint16_t timeout); + inline void setRetransmissionCount(uint8_t _retry); + + void execCmdSn(SOCKET s, SockCMD _cmd); + + uint16_t getTXFreeSize(SOCKET s); + uint16_t getRXReceivedSize(SOCKET s); + + + // W5100 Registers + // --------------- +private: + static uint8_t write(uint16_t _addr, uint8_t _data); + static uint16_t write(uint16_t addr, const uint8_t *buf, uint16_t len); + static uint8_t read(uint16_t addr); + static uint16_t read(uint16_t addr, uint8_t *buf, uint16_t len); + +#define __GP_REGISTER8(name, address) \ + static inline void write##name(uint8_t _data) { \ + write(address, _data); \ + } \ + static inline uint8_t read##name() { \ + return read(address); \ + } +#define __GP_REGISTER16(name, address) \ + static void write##name(uint16_t _data) { \ + write(address, _data >> 8); \ + write(address+1, _data & 0xFF); \ + } \ + static uint16_t read##name() { \ + uint16_t res = read(address); \ + res = (res << 8) + read(address + 1); \ + return res; \ + } +#define __GP_REGISTER_N(name, address, size) \ + static uint16_t write##name(uint8_t *_buff) { \ + return write(address, _buff, size); \ + } \ + static uint16_t read##name(uint8_t *_buff) { \ + return read(address, _buff, size); \ + } + +public: + __GP_REGISTER8 (MR, 0x0000); // Mode + __GP_REGISTER_N(GAR, 0x0001, 4); // Gateway IP address + __GP_REGISTER_N(SUBR, 0x0005, 4); // Subnet mask address + __GP_REGISTER_N(SHAR, 0x0009, 6); // Source MAC address + __GP_REGISTER_N(SIPR, 0x000F, 4); // Source IP address + __GP_REGISTER8 (IR, 0x0015); // Interrupt + __GP_REGISTER8 (IMR, 0x0016); // Interrupt Mask + __GP_REGISTER16(RTR, 0x0017); // Timeout address + __GP_REGISTER8 (RCR, 0x0019); // Retry count + __GP_REGISTER8 (PATR, 0x001C); // Authentication type address in PPPoE mode + __GP_REGISTER8 (PTIMER, 0x0028); // PPP LCP Request Timer + __GP_REGISTER8 (PMAGIC, 0x0029); // PPP LCP Magic Number + +#undef __GP_REGISTER8 +#undef __GP_REGISTER16 +#undef __GP_REGISTER_N + + // W5100 Socket registers + // ---------------------- +private: + static inline uint8_t readSn(SOCKET _s, uint16_t _addr); + static inline uint8_t writeSn(SOCKET _s, uint16_t _addr, uint8_t _data); + static inline uint16_t readSn(SOCKET _s, uint16_t _addr, uint8_t *_buf, uint16_t len); + static inline uint16_t writeSn(SOCKET _s, uint16_t _addr, uint8_t *_buf, uint16_t len); + + + static const uint16_t CH_BASE = 0x4000; + static const uint16_t CH_SIZE = 0x0100; + +#define __SOCKET_REGISTER8(name, address) \ + static inline void write##name(SOCKET _s, uint8_t _data) { \ + writeSn(_s, address, _data); \ + } \ + static inline uint8_t read##name(SOCKET _s) { \ + return readSn(_s, address); \ + } +#define __SOCKET_REGISTER16(name, address) \ + static void write##name(SOCKET _s, uint16_t _data) { \ + writeSn(_s, address, _data >> 8); \ + writeSn(_s, address+1, _data & 0xFF); \ + } \ + static uint16_t read##name(SOCKET _s) { \ + uint16_t res = readSn(_s, address); \ + uint16_t res2 = readSn(_s,address + 1); \ + res = res << 8; \ + res2 = res2 & 0xFF; \ + res = res | res2; \ + return res; \ + } +#define __SOCKET_REGISTER_N(name, address, size) \ + static uint16_t write##name(SOCKET _s, uint8_t *_buff) { \ + return writeSn(_s, address, _buff, size); \ + } \ + static uint16_t read##name(SOCKET _s, uint8_t *_buff) { \ + return readSn(_s, address, _buff, size); \ + } + +public: + __SOCKET_REGISTER8(SnMR, 0x0000) // Mode + __SOCKET_REGISTER8(SnCR, 0x0001) // Command + __SOCKET_REGISTER8(SnIR, 0x0002) // Interrupt + __SOCKET_REGISTER8(SnSR, 0x0003) // Status + __SOCKET_REGISTER16(SnPORT, 0x0004) // Source Port + __SOCKET_REGISTER_N(SnDHAR, 0x0006, 6) // Destination Hardw Addr + __SOCKET_REGISTER_N(SnDIPR, 0x000C, 4) // Destination IP Addr + __SOCKET_REGISTER16(SnDPORT, 0x0010) // Destination Port + __SOCKET_REGISTER16(SnMSSR, 0x0012) // Max Segment Size + __SOCKET_REGISTER8(SnPROTO, 0x0014) // Protocol in IP RAW Mode + __SOCKET_REGISTER8(SnTOS, 0x0015) // IP TOS + __SOCKET_REGISTER8(SnTTL, 0x0016) // IP TTL + __SOCKET_REGISTER16(SnTX_FSR, 0x0020) // TX Free Size + __SOCKET_REGISTER16(SnTX_RD, 0x0022) // TX Read Pointer + __SOCKET_REGISTER16(SnTX_WR, 0x0024) // TX Write Pointer + __SOCKET_REGISTER16(SnRX_RSR, 0x0026) // RX Free Size + __SOCKET_REGISTER16(SnRX_RD, 0x0028) // RX Read Pointer + __SOCKET_REGISTER16(SnRX_WR, 0x002A) // RX Write Pointer (supported?) + +#undef __SOCKET_REGISTER8 +#undef __SOCKET_REGISTER16 +#undef __SOCKET_REGISTER_N + + +private: + static const uint8_t RST = 7; // Reset BIT + static const int SOCKETS = 8; + static const uint16_t SMASK = 0x07FF; // Tx buffer MASK + static const uint16_t RMASK = 0x07FF; // Rx buffer MASK +public: + static const uint16_t SSIZE = 2048; // Max Tx buffer size +private: + static const uint16_t RSIZE = 2048; // Max Rx buffer size + uint16_t SBASE[SOCKETS]; // Tx buffer base address + uint16_t RBASE[SOCKETS]; // Rx buffer base address + +private: +#if defined(ARDUINO_ARCH_AVR) +#if defined(REL_GR_KURUMI) || defined(REL_GR_KURUMI_PROTOTYPE) + inline static void initSS() { pinMode(SS, OUTPUT); \ + digitalWrite(SS, HIGH); }; + inline static void setSS() { digitalWrite(SS, LOW); }; + inline static void resetSS() { digitalWrite(SS, HIGH); }; +#elif defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) || defined(__AVR_ATmega1284P__) + inline static void initSS() { DDRB |= _BV(4); }; + inline static void setSS() { PORTB &= ~_BV(4); }; + inline static void resetSS() { PORTB |= _BV(4); }; +#elif defined(__AVR_ATmega32U4__) + inline static void initSS() { DDRB |= _BV(6); }; + inline static void setSS() { PORTB &= ~_BV(6); }; + inline static void resetSS() { PORTB |= _BV(6); }; +#elif defined(__AVR_AT90USB1286__) || defined(__AVR_AT90USB646__) || defined(__AVR_AT90USB162__) + inline static void initSS() { DDRB |= _BV(0); }; + inline static void setSS() { PORTB &= ~_BV(0); }; + inline static void resetSS() { PORTB |= _BV(0); }; +#else + inline static void initSS() { DDRB |= _BV(2); }; + inline static void setSS() { PORTB &= ~_BV(2); }; + inline static void resetSS() { PORTB |= _BV(2); }; +#endif +#endif // ARDUINO_ARCH_AVR +}; + +extern W5200Class W5100; + +uint8_t W5200Class::readSn(SOCKET _s, uint16_t _addr) { + return read(CH_BASE + _s * CH_SIZE + _addr); +} + +uint8_t W5200Class::writeSn(SOCKET _s, uint16_t _addr, uint8_t _data) { + return write(CH_BASE + _s * CH_SIZE + _addr, _data); +} + +uint16_t W5200Class::readSn(SOCKET _s, uint16_t _addr, uint8_t *_buf, uint16_t _len) { + return read(CH_BASE + _s * CH_SIZE + _addr, _buf, _len); +} + +uint16_t W5200Class::writeSn(SOCKET _s, uint16_t _addr, uint8_t *_buf, uint16_t _len) { + return write(CH_BASE + _s * CH_SIZE + _addr, _buf, _len); +} + +void W5200Class::getGatewayIp(uint8_t *_addr) { + readGAR(_addr); +} + +void W5200Class::setGatewayIp(uint8_t *_addr) { + writeGAR(_addr); +} + +void W5200Class::getSubnetMask(uint8_t *_addr) { + readSUBR(_addr); +} + +void W5200Class::setSubnetMask(uint8_t *_addr) { + writeSUBR(_addr); +} + +void W5200Class::getMACAddress(uint8_t *_addr) { + readSHAR(_addr); +} + +void W5200Class::setMACAddress(uint8_t *_addr) { + writeSHAR(_addr); +} + +void W5200Class::getIPAddress(uint8_t *_addr) { + readSIPR(_addr); +} + +void W5200Class::setIPAddress(uint8_t *_addr) { + writeSIPR(_addr); +} + +void W5200Class::setRetransmissionTime(uint16_t _timeout) { + writeRTR(_timeout); +} + +void W5200Class::setRetransmissionCount(uint8_t _retry) { + writeRCR(_retry); +} + +#endif diff --git a/STM32F1/libraries/Ethernet_STM/src/utility/w5500.cpp b/STM32F1/libraries/Ethernet_STM/src/utility/w5500.cpp new file mode 100644 index 0000000..d80bd06 --- /dev/null +++ b/STM32F1/libraries/Ethernet_STM/src/utility/w5500.cpp @@ -0,0 +1,241 @@ +/* + * Copyright (c) 2010 by WIZnet + * + * This file is free software; you can redistribute it and/or modify + * it under the terms of either the GNU General Public License version 2 + * or the GNU Lesser General Public License version 2.1, both as + * published by the Free Software Foundation. + */ + +#include +#include + +#include "utility/w5100.h" +#if defined(W5500_ETHERNET_SHIELD) + +// W5500 controller instance +W5500Class W5100; + +#define SPI_CS 10 +#define STM32_SPI_CS PA4 + +void W5500Class::init(void) +{ + delay(1000); + +#if defined(ARDUINO_ARCH_AVR) + initSS(); + SPI.begin(); +#elif defined (__STM32F1__) + pinMode(STM32_SPI_CS, OUTPUT); + SPI.begin(); + SPI.setBitOrder(MSBFIRST); + SPI.setDataMode(SPI_MODE0); + SPI.setClockDivider(SPI_CLOCK_DIV4); + pinMode(STM32_SPI_CS, OUTPUT); +#else + SPI.begin(SPI_CS); + // Set clock to 4Mhz (W5100 should support up to about 14Mhz) +// SPI.setClockDivider(SPI_CS, 21); +// SPI.setClockDivider(SPI_CS, 6); // 14 Mhz, ok +// SPI.setClockDivider(SPI_CS, 3); // 28 Mhz, ok + SPI.setClockDivider(SPI_CS, 2); // 42 Mhz, ok + SPI.setDataMode(SPI_CS, SPI_MODE0); +#endif + write(0x00, 0x05, 128); // Software reset the W5500 chip + for (int i=0; i> 8); + SPI.transfer(_addr & 0xFF); + SPI.transfer(_cb); + SPI.transfer(_data); + resetSS(); +#elif defined(__STM32F1__) + digitalWrite(STM32_SPI_CS, LOW); + SPI.transfer(_addr >> 8); + SPI.transfer(_addr & 0xFF); + SPI.transfer(_cb); + SPI.transfer(_data); + digitalWrite(STM32_SPI_CS, HIGH); +#else + SPI.transfer(SPI_CS, _addr >> 8, SPI_CONTINUE); + SPI.transfer(SPI_CS, _addr & 0xFF, SPI_CONTINUE); + SPI.transfer(SPI_CS, _cb, SPI_CONTINUE); + SPI.transfer(SPI_CS, _data); +#endif + return 1; +} + +uint16_t W5500Class::write(uint16_t _addr, uint8_t _cb, const uint8_t *_buf, uint16_t _len) +{ +#if defined(ARDUINO_ARCH_AVR) + setSS(); + SPI.transfer(_addr >> 8); + SPI.transfer(_addr & 0xFF); + SPI.transfer(_cb); + for (uint16_t i=0; i<_len; i++){ + SPI.transfer(_buf[i]); + } + resetSS(); +#elif defined(__STM32F1__) + digitalWrite(STM32_SPI_CS, LOW); + SPI.transfer( _addr >> 8); + SPI.transfer( _addr & 0xFF); + SPI.transfer(_cb); + for (uint16_t i=0; i<_len; i++){ + SPI.transfer(_buf[i]); + } + digitalWrite(STM32_SPI_CS, HIGH); +#else + uint16_t i; + SPI.transfer(SPI_CS, _addr >> 8, SPI_CONTINUE); + SPI.transfer(SPI_CS, _addr & 0xFF, SPI_CONTINUE); + SPI.transfer(SPI_CS, _cb, SPI_CONTINUE); + for (i=0; i<_len-1; i++){ + SPI.transfer(SPI_CS, _buf[i], SPI_CONTINUE); + } + SPI.transfer(SPI_CS, _buf[i]); + +#endif + return _len; +} + +uint8_t W5500Class::read(uint16_t _addr, uint8_t _cb) +{ +#if defined(ARDUINO_ARCH_AVR) + setSS(); + SPI.transfer(_addr >> 8); + SPI.transfer(_addr & 0xFF); + SPI.transfer(_cb); + uint8_t _data = SPI.transfer(0); + resetSS(); +#elif defined(__STM32F1__) + digitalWrite(STM32_SPI_CS, LOW); + SPI.transfer( _addr >> 8); + SPI.transfer(_addr & 0xFF); + SPI.transfer(_cb); + uint8_t _data = SPI.transfer(0); + digitalWrite(STM32_SPI_CS, HIGH); +#else + SPI.transfer(SPI_CS, _addr >> 8, SPI_CONTINUE); + SPI.transfer(SPI_CS, _addr & 0xFF, SPI_CONTINUE); + SPI.transfer(SPI_CS, _cb, SPI_CONTINUE); + uint8_t _data = SPI.transfer(SPI_CS, 0); +#endif + return _data; +} + +uint16_t W5500Class::read(uint16_t _addr, uint8_t _cb, uint8_t *_buf, uint16_t _len) +{ +#if defined(ARDUINO_ARCH_AVR) + setSS(); + SPI.transfer(_addr >> 8); + SPI.transfer(_addr & 0xFF); + SPI.transfer(_cb); + for (uint16_t i=0; i<_len; i++){ + _buf[i] = SPI.transfer(0); + } + resetSS(); +#elif defined(__STM32F1__) + digitalWrite(STM32_SPI_CS, LOW); + SPI.transfer(_addr >> 8); + SPI.transfer(_addr & 0xFF); + SPI.transfer(_cb); + for (uint16_t i=0; i<_len; i++){ + _buf[i] = SPI.transfer(0); + } + digitalWrite(STM32_SPI_CS, HIGH); +#else + uint16_t i; + SPI.transfer(SPI_CS, _addr >> 8, SPI_CONTINUE); + SPI.transfer(SPI_CS, _addr & 0xFF, SPI_CONTINUE); + SPI.transfer(SPI_CS, _cb, SPI_CONTINUE); + for (i=0; i<_len-1; i++){ + _buf[i] = SPI.transfer(SPI_CS, 0, SPI_CONTINUE); + } + _buf[_len-1] = SPI.transfer(SPI_CS, 0); + + +#endif + return _len; +} + +void W5500Class::execCmdSn(SOCKET s, SockCMD _cmd) { + // Send command to socket + writeSnCR(s, _cmd); + // Wait for command to complete + while (readSnCR(s)) + ; +} +#endif diff --git a/STM32F1/libraries/Ethernet_STM/src/utility/w5500.h b/STM32F1/libraries/Ethernet_STM/src/utility/w5500.h new file mode 100644 index 0000000..0dbdfe3 --- /dev/null +++ b/STM32F1/libraries/Ethernet_STM/src/utility/w5500.h @@ -0,0 +1,447 @@ +/* +* Copyright (c) 2010 by WIZnet + * + * This file is free software; you can redistribute it and/or modify + * it under the terms of either the GNU General Public License version 2 + * or the GNU Lesser General Public License version 2.1, both as + * published by the Free Software Foundation. + */ + +#ifndef W5500_H_INCLUDED +#define W5500_H_INCLUDED + +/** Total RAM buffer is 16 kBytes for Transmitter and 16 kBytes for receiver for 1 Socket. + * The Total W5500 RAM buffer is 32 kBytes (16 + 16). + * If you use more Sockets then the RAM buffer must be split. + * For example: if you use 2 Sockets then all socket must use upto 16 kBytes in total RAM. + * So, we have: + * + * #define MAX_SOCK_NUM 2 // Select two Sockets. + * #define RXBUF_SIZE 8 // The Receiver buffer size will be 8 kBytes + * #define TXBUF_SIZE 8 // The Transmitter buffer size will be 8 kBytes + * + * In total we use (2 Sockets)*(8 kBytes) for transmitter + (2 Sockets)*(8 kBytes) for receiver = 32 kBytes. + * + * I would prefer to use only 1 Socket with 16 kBytes RAM buffer for transmitter and 16 kByte for receiver buffer. + * + * #define MAX_SOCK_NUM 1 // Select only one Socket + * #define RXBUF_SIZE 16 // Select 16 kBytes Receiver RAM buffer + * #define TXBUF_SIZE 16 // Select 16 kBytes Transmitter RAM buffer + * + * (c) 02 September 2015 By Vassilis Serasidis + * + */ + +#define MAX_SOCK_NUM 8 // Select the number of Sockets (1-8) +#define RXBUF_SIZE 2 // Select the Receiver buffer size (1 - 16 kBytes) +#define TXBUF_SIZE 2 // Select the Transmitter buffer size (1 - 16 kBytes) + +/* +class MR { +public: + static const uint8_t RST = 0x80; + static const uint8_t PB = 0x10; + static const uint8_t PPPOE = 0x08; + static const uint8_t LB = 0x04; + static const uint8_t AI = 0x02; + static const uint8_t IND = 0x01; +}; +*/ +/* +class IR { +public: + static const uint8_t CONFLICT = 0x80; + static const uint8_t UNREACH = 0x40; + static const uint8_t PPPoE = 0x20; + static const uint8_t SOCK0 = 0x01; + static const uint8_t SOCK1 = 0x02; + static const uint8_t SOCK2 = 0x04; + static const uint8_t SOCK3 = 0x08; + static inline uint8_t SOCK(SOCKET ch) { return (0x01 << ch); }; +}; +*/ + +class SnMR { +public: + static const uint8_t CLOSE = 0x00; + static const uint8_t TCP = 0x01; + static const uint8_t UDP = 0x02; + static const uint8_t IPRAW = 0x03; + static const uint8_t MACRAW = 0x04; + static const uint8_t PPPOE = 0x05; + static const uint8_t ND = 0x20; + static const uint8_t MULTI = 0x80; +}; + +enum SockCMD { + Sock_OPEN = 0x01, + Sock_LISTEN = 0x02, + Sock_CONNECT = 0x04, + Sock_DISCON = 0x08, + Sock_CLOSE = 0x10, + Sock_SEND = 0x20, + Sock_SEND_MAC = 0x21, + Sock_SEND_KEEP = 0x22, + Sock_RECV = 0x40 +}; + +/*class SnCmd { +public: + static const uint8_t OPEN = 0x01; + static const uint8_t LISTEN = 0x02; + static const uint8_t CONNECT = 0x04; + static const uint8_t DISCON = 0x08; + static const uint8_t CLOSE = 0x10; + static const uint8_t SEND = 0x20; + static const uint8_t SEND_MAC = 0x21; + static const uint8_t SEND_KEEP = 0x22; + static const uint8_t RECV = 0x40; +}; +*/ + +class SnIR { +public: + static const uint8_t SEND_OK = 0x10; + static const uint8_t TIMEOUT = 0x08; + static const uint8_t RECV = 0x04; + static const uint8_t DISCON = 0x02; + static const uint8_t CON = 0x01; +}; + +class SnSR { +public: + static const uint8_t CLOSED = 0x00; + static const uint8_t INIT = 0x13; + static const uint8_t LISTEN = 0x14; + static const uint8_t SYNSENT = 0x15; + static const uint8_t SYNRECV = 0x16; + static const uint8_t ESTABLISHED = 0x17; + static const uint8_t FIN_WAIT = 0x18; + static const uint8_t CLOSING = 0x1A; + static const uint8_t TIME_WAIT = 0x1B; + static const uint8_t CLOSE_WAIT = 0x1C; + static const uint8_t LAST_ACK = 0x1D; + static const uint8_t UDP = 0x22; + static const uint8_t IPRAW = 0x32; + static const uint8_t MACRAW = 0x42; + static const uint8_t PPPOE = 0x5F; +}; + +class IPPROTO { +public: + static const uint8_t IP = 0; + static const uint8_t ICMP = 1; + static const uint8_t IGMP = 2; + static const uint8_t GGP = 3; + static const uint8_t TCP = 6; + static const uint8_t PUP = 12; + static const uint8_t UDP = 17; + static const uint8_t IDP = 22; + static const uint8_t ND = 77; + static const uint8_t RAW = 255; +}; + +class W5500Class { + +public: + void init(); + + /** + * @brief This function is being used for copy the data form Receive buffer of the chip to application buffer. + * + * It calculate the actual physical address where one has to read + * the data from Receive buffer. Here also take care of the condition while it exceed + * the Rx memory uper-bound of socket. + */ + void read_data(SOCKET s, volatile uint16_t src, volatile uint8_t * dst, uint16_t len); + + /** + * @brief This function is being called by send() and sendto() function also. + * + * This function read the Tx write pointer register and after copy the data in buffer update the Tx write pointer + * register. User should read upper byte first and lower byte later to get proper value. + */ + void send_data_processing(SOCKET s, const uint8_t *data, uint16_t len); + /** + * @brief A copy of send_data_processing that uses the provided ptr for the + * write offset. Only needed for the "streaming" UDP API, where + * a single UDP packet is built up over a number of calls to + * send_data_processing_ptr, because TX_WR doesn't seem to get updated + * correctly in those scenarios + * @param ptr value to use in place of TX_WR. If 0, then the value is read + * in from TX_WR + * @return New value for ptr, to be used in the next call + */ + // FIXME Update documentation + void send_data_processing_offset(SOCKET s, uint16_t data_offset, const uint8_t *data, uint16_t len); + + /** + * @brief This function is being called by recv() also. + * + * This function read the Rx read pointer register + * and after copy the data from receive buffer update the Rx write pointer register. + * User should read upper byte first and lower byte later to get proper value. + */ + void recv_data_processing(SOCKET s, uint8_t *data, uint16_t len, uint8_t peek = 0); + + inline void setGatewayIp(uint8_t *_addr); + inline void getGatewayIp(uint8_t *_addr); + + inline void setSubnetMask(uint8_t *_addr); + inline void getSubnetMask(uint8_t *_addr); + + inline void setMACAddress(uint8_t * addr); + inline void getMACAddress(uint8_t * addr); + + inline void setIPAddress(uint8_t * addr); + inline void getIPAddress(uint8_t * addr); + + inline void setRetransmissionTime(uint16_t timeout); + inline void setRetransmissionCount(uint8_t _retry); + + inline void setPHYCFGR(uint8_t _val); + inline uint8_t getPHYCFGR(); + + void execCmdSn(SOCKET s, SockCMD _cmd); + + uint16_t getTXFreeSize(SOCKET s); + uint16_t getRXReceivedSize(SOCKET s); + + + // W5500 Registers + // --------------- +private: + static uint8_t write(uint16_t _addr, uint8_t _cb, uint8_t _data); + static uint16_t write(uint16_t _addr, uint8_t _cb, const uint8_t *buf, uint16_t len); + static uint8_t read(uint16_t _addr, uint8_t _cb ); + static uint16_t read(uint16_t _addr, uint8_t _cb, uint8_t *buf, uint16_t len); + +#define __GP_REGISTER8(name, address) \ + static inline void write##name(uint8_t _data) { \ + write(address, 0x04, _data); \ + } \ + static inline uint8_t read##name() { \ + return read(address, 0x00); \ + } +#define __GP_REGISTER16(name, address) \ + static void write##name(uint16_t _data) { \ + write(address, 0x04, _data >> 8); \ + write(address+1, 0x04, _data & 0xFF); \ + } \ + static uint16_t read##name() { \ + uint16_t res = read(address, 0x00); \ + res = (res << 8) + read(address + 1, 0x00); \ + return res; \ + } +#define __GP_REGISTER_N(name, address, size) \ + static uint16_t write##name(uint8_t *_buff) { \ + return write(address, 0x04, _buff, size); \ + } \ + static uint16_t read##name(uint8_t *_buff) { \ + return read(address, 0x00, _buff, size); \ + } + +public: + __GP_REGISTER8 (MR, 0x0000); // Mode + __GP_REGISTER_N(GAR, 0x0001, 4); // Gateway IP address + __GP_REGISTER_N(SUBR, 0x0005, 4); // Subnet mask address + __GP_REGISTER_N(SHAR, 0x0009, 6); // Source MAC address + __GP_REGISTER_N(SIPR, 0x000F, 4); // Source IP address + __GP_REGISTER8 (IR, 0x0015); // Interrupt + __GP_REGISTER8 (IMR, 0x0016); // Interrupt Mask + __GP_REGISTER16(RTR, 0x0019); // Timeout address + __GP_REGISTER8 (RCR, 0x001B); // Retry count + __GP_REGISTER_N(UIPR, 0x0028, 4); // Unreachable IP address in UDP mode + __GP_REGISTER16(UPORT, 0x002C); // Unreachable Port address in UDP mode + __GP_REGISTER8 (PHYCFGR, 0x002E); // PHY Configuration register, default value: 0b 1011 1xxx + + +#undef __GP_REGISTER8 +#undef __GP_REGISTER16 +#undef __GP_REGISTER_N + + // W5500 Socket registers + // ---------------------- +private: + static inline uint8_t readSn(SOCKET _s, uint16_t _addr); + static inline uint8_t writeSn(SOCKET _s, uint16_t _addr, uint8_t _data); + static inline uint16_t readSn(SOCKET _s, uint16_t _addr, uint8_t *_buf, uint16_t len); + static inline uint16_t writeSn(SOCKET _s, uint16_t _addr, uint8_t *_buf, uint16_t len); + + //static const uint16_t CH_BASE = 0x0000; + //static const uint16_t CH_SIZE = 0x0000; + +#define __SOCKET_REGISTER8(name, address) \ + static inline void write##name(SOCKET _s, uint8_t _data) { \ + writeSn(_s, address, _data); \ + } \ + static inline uint8_t read##name(SOCKET _s) { \ + return readSn(_s, address); \ + } +#if defined(REL_GR_KURUMI) || defined(REL_GR_KURUMI_PROTOTYPE) +#define __SOCKET_REGISTER16(name, address) \ + static void write##name(SOCKET _s, uint16_t _data) { \ + writeSn(_s, address, _data >> 8); \ + writeSn(_s, address+1, _data & 0xFF); \ + } \ + static uint16_t read##name(SOCKET _s) { \ + uint16_t res = readSn(_s, address); \ + uint16_t res2 = readSn(_s,address + 1); \ + res = res << 8; \ + res2 = res2 & 0xFF; \ + res = res | res2; \ + return res; \ + } +#else +#define __SOCKET_REGISTER16(name, address) \ + static void write##name(SOCKET _s, uint16_t _data) { \ + writeSn(_s, address, _data >> 8); \ + writeSn(_s, address+1, _data & 0xFF); \ + } \ + static uint16_t read##name(SOCKET _s) { \ + uint16_t res = readSn(_s, address); \ + res = (res << 8) + readSn(_s, address + 1); \ + return res; \ + } +#endif +#define __SOCKET_REGISTER_N(name, address, size) \ + static uint16_t write##name(SOCKET _s, uint8_t *_buff) { \ + return writeSn(_s, address, _buff, size); \ + } \ + static uint16_t read##name(SOCKET _s, uint8_t *_buff) { \ + return readSn(_s, address, _buff, size); \ + } + +public: + __SOCKET_REGISTER8(SnMR, 0x0000) // Mode + __SOCKET_REGISTER8(SnCR, 0x0001) // Command + __SOCKET_REGISTER8(SnIR, 0x0002) // Interrupt + __SOCKET_REGISTER8(SnSR, 0x0003) // Status + __SOCKET_REGISTER16(SnPORT, 0x0004) // Source Port + __SOCKET_REGISTER_N(SnDHAR, 0x0006, 6) // Destination Hardw Addr + __SOCKET_REGISTER_N(SnDIPR, 0x000C, 4) // Destination IP Addr + __SOCKET_REGISTER16(SnDPORT, 0x0010) // Destination Port + __SOCKET_REGISTER16(SnMSSR, 0x0012) // Max Segment Size + __SOCKET_REGISTER8(SnPROTO, 0x0014) // Protocol in IP RAW Mode + __SOCKET_REGISTER8(SnTOS, 0x0015) // IP TOS + __SOCKET_REGISTER8(SnTTL, 0x0016) // IP TTL + __SOCKET_REGISTER16(SnTX_FSR, 0x0020) // TX Free Size + __SOCKET_REGISTER16(SnTX_RD, 0x0022) // TX Read Pointer + __SOCKET_REGISTER16(SnTX_WR, 0x0024) // TX Write Pointer + __SOCKET_REGISTER16(SnRX_RSR, 0x0026) // RX Free Size + __SOCKET_REGISTER16(SnRX_RD, 0x0028) // RX Read Pointer + __SOCKET_REGISTER16(SnRX_WR, 0x002A) // RX Write Pointer (supported?) + +#undef __SOCKET_REGISTER8 +#undef __SOCKET_REGISTER16 +#undef __SOCKET_REGISTER_N + + +private: + static const uint8_t RST = 7; // Reset BIT + static const int SOCKETS = 8; + +public: + static const uint16_t SSIZE = 2048; // Max Tx buffer size +private: + static const uint16_t RSIZE = 2048; // Max Rx buffer size + +private: +#if defined(ARDUINO_ARCH_AVR) +#if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) || defined(__AVR_ATmega1284P__) + inline static void initSS() { DDRB |= _BV(4); }; + inline static void setSS() { PORTB &= ~_BV(4); }; + inline static void resetSS() { PORTB |= _BV(4); }; +#elif defined(__AVR_ATmega32U4__) + inline static void initSS() { DDRB |= _BV(6); }; + inline static void setSS() { PORTB &= ~_BV(6); }; + inline static void resetSS() { PORTB |= _BV(6); }; +#elif defined(__AVR_AT90USB1286__) || defined(__AVR_AT90USB646__) || defined(__AVR_AT90USB162__) + inline static void initSS() { DDRB |= _BV(0); }; + inline static void setSS() { PORTB &= ~_BV(0); }; + inline static void resetSS() { PORTB |= _BV(0); }; +#elif defined(REL_GR_KURUMI) || defined(REL_GR_KURUMI_PROTOTYPE) + inline static void initSS() { pinMode(SS, OUTPUT); \ + digitalWrite(SS, HIGH); }; + inline static void setSS() { digitalWrite(SS, LOW); }; + inline static void resetSS() { digitalWrite(SS, HIGH); }; +#else + inline static void initSS() { DDRB |= _BV(2); }; + inline static void setSS() { PORTB &= ~_BV(2); }; + inline static void resetSS() { PORTB |= _BV(2); }; +#endif +#endif // ARDUINO_ARCH_AVR +}; + +extern W5500Class W5100; + +uint8_t W5500Class::readSn(SOCKET _s, uint16_t _addr) { + uint8_t cntl_byte = (_s<<5)+0x08; + return read(_addr, cntl_byte); +} + +uint8_t W5500Class::writeSn(SOCKET _s, uint16_t _addr, uint8_t _data) { + uint8_t cntl_byte = (_s<<5)+0x0C; + return write(_addr, cntl_byte, _data); +} + +uint16_t W5500Class::readSn(SOCKET _s, uint16_t _addr, uint8_t *_buf, uint16_t _len) { + uint8_t cntl_byte = (_s<<5)+0x08; + return read(_addr, cntl_byte, _buf, _len ); +} + +uint16_t W5500Class::writeSn(SOCKET _s, uint16_t _addr, uint8_t *_buf, uint16_t _len) { + uint8_t cntl_byte = (_s<<5)+0x0C; + return write(_addr, cntl_byte, _buf, _len); +} + +void W5500Class::getGatewayIp(uint8_t *_addr) { + readGAR(_addr); +} + +void W5500Class::setGatewayIp(uint8_t *_addr) { + writeGAR(_addr); +} + +void W5500Class::getSubnetMask(uint8_t *_addr) { + readSUBR(_addr); +} + +void W5500Class::setSubnetMask(uint8_t *_addr) { + writeSUBR(_addr); +} + +void W5500Class::getMACAddress(uint8_t *_addr) { + readSHAR(_addr); +} + +void W5500Class::setMACAddress(uint8_t *_addr) { + writeSHAR(_addr); +} + +void W5500Class::getIPAddress(uint8_t *_addr) { + readSIPR(_addr); +} + +void W5500Class::setIPAddress(uint8_t *_addr) { + writeSIPR(_addr); +} + +void W5500Class::setRetransmissionTime(uint16_t _timeout) { + writeRTR(_timeout); +} + +void W5500Class::setRetransmissionCount(uint8_t _retry) { + writeRCR(_retry); +} + +void W5500Class::setPHYCFGR(uint8_t _val) { + writePHYCFGR(_val); +} + +uint8_t W5500Class::getPHYCFGR() { +// readPHYCFGR(); + return read(0x002E, 0x00); +} + +#endif