(myKeyBuffer), myKeyLength) > -1) {
+ // We found animation
+ DEBUG_PRINTLN_TXT("Found animation");
+ myReadStatus = 20; // End search, we found our animation
+ }else{
+ DEBUG_PRINTLN_TXT("No animation found");
+ if (_animationEndPos > _animationStartPos ) {
+ // Goto next frame
+ myProjectFile.seek(_animationEndPos);
+ myReadStatus = 0;
+ }
+ }
+
+ // clear buffer
+ myIntBufferLength = 0;
+ }
+ break;
+ case 6:
+ if( myC == lc_newline ) { // uncomplete keyline or no animation found
+ // check for values
+ if ( _animationEndPos > 0 && _animationStartPos > 0 && _animationSpeed > 0 ) {
+ DEBUG_PRINTLN_TXT("Anim key found");
+ }else{
+ DEBUG_PRINTLN_TXT("--keyline failed--");
+ // Reset everything
+ myReadStatus = 0;
+ myKeyLength = 0;
+ myIntBufferLength = 0;
+ clearSavedAnimation();
+ }
+ }
+ break;
+ }
+ }
+ }
+ myProjectFile.close();
+}
+
+boolean readAnimationSD() {
+ unsigned char myC;
+ unsigned char myBytes = 0;
+ // Read SD Card
+ File myProjectFile = SD.open(ANIM_FILE_NAME, FILE_READ);
+ // Goto start position
+ if ( myProjectFile.available() ) {
+ unsigned long _animationPos = _animationStartPos + _animationActFrame * 65; // startPos + offset
+ if ( _animationPos < _animationEndPos ) {
+ myProjectFile.seek(_animationPos);
+ }else{
+ _animationActFrame = 0; // Start at the first frame again
+ myProjectFile.seek(_animationStartPos);
+ }
+ }
+ // Read one frame
+ while ( myProjectFile.available() && myBytes < 64 ) {
+ myC = myProjectFile.read();
+ myReceiveBuffer[myBytes] = myC;
+ myBytes++;
+ }
+
+ // close the file:
+ myProjectFile.close();
+
+ // If we have complete frame, return true
+ if ( myBytes > 63 ) {
+ // read successfull
+ _animationActFrame++;
+ return true;
+ }else{
+ return false;
+ }
+}
+
+unsigned long byte2Long(unsigned char* byteArray) {
+ // little endian conversion
+ unsigned long retval;
+ retval = (unsigned long) byteArray[3] << 24 | (unsigned long) byteArray[2] << 16;
+ retval |= (unsigned long) byteArray[1] << 8 | byteArray[0];
+ return retval;
+}
+void writeAnimationSDCard(EthernetClient client) {
+ // Send answer
+ unsigned char readBuffer[4];
+ // First 10 bytes is a key, following by the length
+ readBuffer[0] = myReadBuffer[10];
+ readBuffer[1] = myReadBuffer[11];
+ readBuffer[2] = myReadBuffer[12];
+ readBuffer[3] = myReadBuffer[13];
+ unsigned long fileSize = byte2Long(readBuffer);
+
+// DEBUG_PRINT_TXT("fileSizeBuffer: ");
+ for (unsigned char i=0; i<4; i++ ) {
+ client.write(readBuffer[i]);
+// DEBUG_PRINT(readBuffer[i]);
+ }
+ client.write(lc_return);
+ client.write(lc_newline);
+// DEBUG_PRINTLN_TXT(" ");
+
+
+
+// DEBUG_PRINT_TXT("Filesize expected:");
+// DEBUG_PRINTLN(fileSize);
+
+ // Blocking mode to write receiving data to file
+ if (client) {
+ // Remove file if exists
+ if ( SD.exists(ANIM_FILE_NAME) ) {
+ SD.remove(ANIM_FILE_NAME);
+ }
+
+ File myProjectFile = SD.open(ANIM_FILE_NAME, FILE_WRITE);
+ unsigned long receivedBytes = 0;
+
+ if (myProjectFile) {
+ while (client.connected() && receivedBytes < fileSize) {
+ if (client.available()) {
+ unsigned char c = client.read();
+ //writing bytes
+ myProjectFile.write(c);
+ receivedBytes++;
+ }
+ }
+ }
+/*
+ if ( receivedBytes == fileSize ) {
+ DEBUG_PRINTLN_TXT("Complete data received\n");
+ }else{
+ DEBUG_PRINTLN_TXT("Data incomplete\n");
+ }
+ DEBUG_PRINT_TXT("Expected:");
+ DEBUG_PRINTLN(fileSize);
+ DEBUG_PRINT_TXT("Received:");
+ DEBUG_PRINTLN(receivedBytes);
+*/
+ myProjectFile.close();
+ }
+}
+
+void displaySavedAnimation() {
+ if ( _animationLength > 0 ) { // Animation was set
+ unsigned long currentMillis = millis();
+ // Display animation set over the network
+ if ( currentMillis < _animationLength ) { // __animationLength = startTime + animLengthTime
+ if ( _animationStartPos > 0 && _animationEndPos > 0 && _animationSpeed > 0){ // validity check
+ if ( _animationEndPos > _animationStartPos ) {
+ //DEBUG_PRINTLN_TXT("Setting mode to 2");
+ setServerMode(2); // Switch the server mode
+ if ( currentMillis - _previousMillis >= _animationSpeed ) { // Sent data with the set speed
+ // save the last time you sent frame
+ _previousMillis = currentMillis;
+ // Fill Buffer
+ if ( true == readAnimationSD() ) {
+ // Send buffered frame
+ sendBufferedFrame();
+ }
+ }
+ }
+ }
+ }else{
+ // End the stream mode
+ setServerMode(0);
+ }
+ }
+}
+
+void keepAliveFrame() {
+ // Check if we need to send a keep alive frame
+ if ( millis() - _lastTimeFrameSent > MY_STREAM_KEEPALIVE_TIME ) {
+ // Send buffered frame
+ sendBufferedFrame();
+ }
+}
+
+// --------- MAIN ---------- //
+
+void setup() {
+ // put your setup code here, to run once:
+ Wire.begin();
+
+#ifdef DEBUG
+ Serial.begin(9600);
+#endif
+ DEBUG_PRINTLN_TXT("Sender1");
+
+ DEBUG_PRINTLN_TXT("Init SD card...");
+ // On the Ethernet Shield, CS is pin 4. It's set as an output by default.
+ // Note that even if it's not used as the CS pin, the hardware SS pin
+ // (10 on most Arduino boards, 53 on the Mega) must be left as an output
+ // or the SD library functions will not work.
+ // disable w5100 SPI
+ //pinMode(10, OUTPUT);
+ //digitalWrite(10,HIGH);
+
+ if (!SD.begin(4)) {
+ DEBUG_PRINTLN_TXT("init failed!");
+ // TODO: deny some functions
+ }else{
+ DEBUG_PRINTLN_TXT("init done.");
+ }
+
+ // start the Ethernet connection:
+ Ethernet.begin(mac, ip, gateway, subnet);
+
+// ----------------------
+// Sorry, but had to drop DHCP support due to missing memory
+// If you have a MEGA, feel free to use it
+/* if (Ethernet.begin(mac) == 0) {
+ DEBUG_PRINTLN_TXT("Failed to configure Ethernet using DHCP");
+ DEBUG_PRINTLN_TXT("Using defaults 192.168.1.79");
+ // initialize the ethernet device not using DHCP:
+ Ethernet.begin(mac, ip, gateway, subnet);
+ }
+*/
+// -----------------------
+
+#ifdef DEBUG
+ // print your local IP address:
+ DEBUG_PRINTLN_TXT("My IP: ");
+ for (byte thisByte = 0; thisByte < 4; thisByte++) {
+ // print the value of each byte of the IP address:
+ DEBUG_PRINT2(Ethernet.localIP()[thisByte], DEC);
+ DEBUG_PRINT(".");
+ }
+ DEBUG_PRINTLN_TXT("");
+#endif
+
+ // Print free memory
+ //DEBUG_PRINT("freeMemory()=");
+ //DEBUG_PRINTLN(freeMemory());
+}
+
+
+void loop() {
+ // Process Server requests
+ // listen for incoming clients
+ EthernetClient client = server.available();
+
+ if (client) { // Client connected and sending data
+ DEBUG_PRINTLN_TXT("Client attached");
+ // Init status
+ unsigned char readState = 0;
+ unsigned char lastChar = 0; // Make sure you never check for 0-value !!!
+ int bufferSize = 0;
+ // If we receive data, interrupt other states
+ setServerMode(0);
+
+ // Read incoming data
+ while (client.connected()) {
+ if (client.available()) {
+ // get incoming byte
+ unsigned char c = client.read();
+
+ // check for server mode
+ switch (serverMode) {
+ case 0:
+ // Checking incoming requests
+ readState = checkRequest(c, readState);
+
+ // Processing if request is recognized
+ if ( readState == 7 ) { // HTTP GET recognized
+ processRequest(client);
+ // process only one time
+ readState = 0;
+ myReadBufferCount = 0;
+ }
+ break;
+
+ case 1:
+ // Streaming frames
+ bufferSize = sendFrameCached(c, bufferSize);
+
+ // Check for streaming end
+ if ( c == lc_S && lastChar == lc_s ) { // "sS" received
+ //sendEndFrameStream();
+ setServerMode(0);
+ bufferSize = 0;
+ }
+
+ break;
+ }
+
+ // if we got whole HTTP Head and still waiting for commands,
+ // send HTTP answer
+ if ( serverMode == 0 && c == lc_newline && lastChar == lc_return ) { // \r\n was send
+ // send a standard http response header
+ //client.println(F("HTTP/1.1 200 OK\nContent-Type: text/html\r\n\nRainbowduino Webserver
Rainbowduino Webserver 1.0
Functions:
Blink:
| |
Frametest
| |
Streamtest
| |
Print file to serial
| |
"));
+ client.println(F("HTTP/1.1 200 OK"));
+ // Close the connection
+ client.stop();
+ }
+
+ lastChar = c;
+ }
+
+ // If we are in the streaming mode and don't receive any frames,
+ // check for timeout
+ if ( serverMode == 1 ) {
+ // keep the connection to the Rainbowduino alive
+ keepAliveFrame();
+ }
+ }
+
+ // give web browser time to receive the data
+ delay(1);
+ // close the connection
+ client.stop();
+ }
+
+ if ( serverMode == 1 && client == false) {
+ // If client closed the connection and we are still in the
+ // stream mode, reset to normal operation
+ setServerMode(0);
+ }
+
+ // ------------------------------------------------//
+ // Display Animation
+ displaySavedAnimation();
+
+}
diff --git a/bin/Cube4Fun.zip b/bin/Cube4Fun.zip
index 9570aff..928e32e 100644
Binary files a/bin/Cube4Fun.zip and b/bin/Cube4Fun.zip differ