diff --git a/README.md b/README.md
index 006ea4e..8ac7d1d 100644
--- a/README.md
+++ b/README.md
@@ -9,4 +9,4 @@ Copy the content of this library in the "Arduino/libraries/SPIFlash" folder.
To find your Arduino folder go to File>Preferences in the Arduino IDE.
-See [this tutorial](http://learn.adafruit.com/arduino-tips-tricks-and-techniques/arduino-libraries) on Arduino libraries.
+See [this tutorial](http://learn.adafruit.com/arduino-tips-tricks-and-techniques/arduino-libraries) on Arduino libraries.
\ No newline at end of file
diff --git a/SPIFlash.cpp b/SPIFlash.cpp
index ca006cb..28536bf 100644
--- a/SPIFlash.cpp
+++ b/SPIFlash.cpp
@@ -14,6 +14,11 @@
#include
+/// IMPORTANT: NAND FLASH memory requires erase before write, because
+/// it can only transition from 1s to 0s and only the erase command can reset all 0s to 1s
+/// See http://en.wikipedia.org/wiki/Flash_memory
+/// The smallest range that can be erased is a sector (4K, 32K, 64K); there is also a chip erase command
+
/// Constructor. JedecID is optional but recommended, since this will ensure that the device is present and has a valid response
/// get this from the datasheet of your flash chip
/// Example for Atmel-Adesto 4Mbit AT25DF041A: 0x1F44 (page 27: http://www.adestotech.com/sites/default/files/datasheets/doc3668.pdf)
@@ -184,7 +189,17 @@ void SPIFlash::blockErase32K(long addr) {
unselect();
}
+void SPIFlash::sleep() {
+ command(SPIFLASH_SLEEP); // Block Erase
+ unselect();
+}
+
+void SPIFlash::wakeup() {
+ command(SPIFLASH_WAKE); // Block Erase
+ unselect();
+}
+
/// cleanup
void SPIFlash::end() {
SPI.end();
-}
+}
\ No newline at end of file
diff --git a/SPIFlash.h b/SPIFlash.h
index 354e408..5432ce3 100644
--- a/SPIFlash.h
+++ b/SPIFlash.h
@@ -24,23 +24,28 @@
#include
+/// IMPORTANT: NAND FLASH memory requires erase before write, because
+/// it can only transition from 1s to 0s and only the erase command can reset all 0s to 1s
+/// See http://en.wikipedia.org/wiki/Flash_memory
+/// The smallest range that can be erased is a sector (4K, 32K, 64K); there is also a chip erase command
+
/// Standard SPI flash commands
/// Assuming the WP pin is pulled up (to disable hardware write protection)
/// To use any write commands the WEL bit in the status register must be set to 1.
/// This is accomplished by sending a 0x06 command before any such write/erase command.
-/// The WEL bit in the status register resets to the logical “0” state after a
-/// device power-up or reset. In addition, the WEL bit will be reset to the logical “0” state automatically under the following conditions:
-/// • Write Disable operation completes successfully
-/// • Write Status Register operation completes successfully or aborts
-/// • Protect Sector operation completes successfully or aborts
-/// • Unprotect Sector operation completes successfully or aborts
-/// • Byte/Page Program operation completes successfully or aborts
-/// • Sequential Program Mode reaches highest unprotected memory location
-/// • Sequential Program Mode reaches the end of the memory array
-/// • Sequential Program Mode aborts
-/// • Block Erase operation completes successfully or aborts
-/// • Chip Erase operation completes successfully or aborts
-/// • Hold condition aborts
+/// The WEL bit in the status register resets to the logical 0 state after a
+/// device power-up or reset. In addition, the WEL bit will be reset to the logical 0 state automatically under the following conditions:
+/// Write Disable operation completes successfully
+/// Write Status Register operation completes successfully or aborts
+/// Protect Sector operation completes successfully or aborts
+/// Unprotect Sector operation completes successfully or aborts
+/// Byte/Page Program operation completes successfully or aborts
+/// Sequential Program Mode reaches highest unprotected memory location
+/// Sequential Program Mode reaches the end of the memory array
+/// Sequential Program Mode aborts
+/// Block Erase operation completes successfully or aborts
+/// Chip Erase operation completes successfully or aborts
+/// Hold condition aborts
#define SPIFLASH_WRITEENABLE 0x06 // write enable
#define SPIFLASH_WRITEDISABLE 0x04 // write disable
@@ -76,6 +81,8 @@ public:
void blockErase4K(long address);
void blockErase32K(long address);
word readDeviceId();
+ void sleep();
+ void wakeup();
void end();
protected:
void select();
@@ -84,4 +91,4 @@ protected:
uint16_t _jedecID;
};
-#endif
+#endif
\ No newline at end of file
diff --git a/WirelessHEX.cpp b/WirelessHEX.cpp
deleted file mode 100644
index 107d31e..0000000
--- a/WirelessHEX.cpp
+++ /dev/null
@@ -1,407 +0,0 @@
-/*
- * Copyright (c) 2013 by Felix Rusu
- * Library for facilitating wireless programming using an RFM12B radio (get library at: https://github.com/LowPowerLab/RFM12B)
- * and the SPI Flash memory library for arduino/moteino (get library at: TODO).
- * DEPENDS ON the two libraries mentioned above
- * Install all three of these libraries in your Arduino/libraries folder ([Arduino > Preferences] for location of Arduino folder)
- *
- * 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
-
-/// Checks whether the last message received was a wireless programming request handshake
-/// If so it will start the handshake protocol, receive the new HEX image and
-/// store it on the external flash chip, then reboot
-/// Assumes radio has been initialized and has just received a message (is not in SLEEP mode, and you called CRCPass())
-/// Assumes flash is an external SPI flash memory chip that has been initialized
-void CheckForWirelessHEX(RFM12B radio, SPIFlash flash, boolean DEBUG)
-{
- //special FLASH command, enter a FLASH image exchange sequence
- if (*radio.DataLen >= 4 && radio.Data[0]=='F' && radio.Data[1]=='L' && radio.Data[2]=='X' && radio.Data[3]=='?')
- {
- byte remoteID = radio.GetSender();
- if (*radio.DataLen == 7 && radio.Data[4]=='E' && radio.Data[5]=='O' && radio.Data[6]=='F')
- { //sender must have not received EOF ACK so just resend
- radio.Send(remoteID, "FLX?OK",6);
- }
- else if (HandleWirelessHEXData(radio, remoteID, flash, DEBUG))
- {
- if (DEBUG) Serial.print("FLASH IMG TRANSMISSION SUCCESS!\n");
- resetUsingWatchdog(DEBUG);
- }
- else
- {
- if (DEBUG) Serial.print("Timeout, erasing written data ... ");
- flash.blockErase32K(0); //clear any written data
- if (DEBUG) Serial.println("DONE");
- }
- }
-}
-
-boolean HandleWirelessHEXData(RFM12B radio, byte remoteID, SPIFlash flash, boolean DEBUG) {
- uint8_t c;
- long now=0;
- uint16_t tmp,seq=0,len;
- char buffer[16];
- int timeout = 3000; //3s for flash data
- uint16_t bytesFlashed=10;
-
- radio.SendACK("FLX?OK",6); //ACK the HANDSHAKE
- if (DEBUG) Serial.println("FLX?OK (ACK sent)");
-
- //first clear the fist 32k block (dedicated to a new FLASH image)
- flash.blockErase32K(0);
- flash.writeBytes(0,"FLXIMG:", 7);
- flash.writeByte(9,':');
- now=millis();
-
- while(1)
- {
- if (radio.ReceiveComplete() && radio.CRCPass() && radio.GetSender() == remoteID)
- {
- byte dataLen = *radio.DataLen;
-
- if (dataLen >= 4 && radio.Data[0]=='F' && radio.Data[1]=='L' && radio.Data[2]=='X')
- {
- if (radio.Data[3]==':' && dataLen >= 7) //FLX:_:_
- {
- byte index=3;
- tmp = 0;
-
- //read packet SEQ
- for (byte i = 4; i<8; i++) //up to 4 characters for seq number
- {
- index++;
- if (radio.Data[i] >=48 && radio.Data[i]<=57)
- tmp = tmp*10+radio.Data[i]-48;
- else if (radio.Data[i]==':')
- {
- if (i==4)
- return false;
- else break;
- }
- }
-
- if (DEBUG) {
- Serial.print("radio [");
- Serial.print(dataLen);
- Serial.print("] > ");
- PrintHex83((byte*)radio.Data, dataLen);
- }
-
- if (radio.Data[index++] != ':') return false;
- now = millis(); //got "good" packet
-
- if (tmp==seq)
- {
- for(byte i=index;i31744) {
- if (DEBUG) Serial.println("IMG exceeds 31k");
-
- return false; //just return, let MAIN timeout
- }
- radio.SendACK("FLX?OK",6);
- if (DEBUG) Serial.println("FLX?OK");
-
- //save # of bytes written
- flash.writeByte(7,(bytesFlashed-10)>>8);
- flash.writeByte(8,(bytesFlashed-10));
- flash.writeByte(9,':');
- return true;
- }
- }
- }
- #ifdef LED //blink!
- pinMode(LED,OUTPUT); digitalWrite(LED,HIGH); delay(1); digitalWrite(LED,LOW);
- #endif
- }
-
- //abort FLASH sequence if no valid packet received for a long time
- if (millis()-now > timeout)
- {
- return false;
- }
- }
-}
-
-// reads a line feed (\n) terminated line from the serial stream
-// returns # of bytes read, up to 255
-// timeout in ms, will timeout and return after so long
-byte readSerialLine(char* input, char endOfLineChar, byte maxLength, uint16_t timeout)
-{
- byte inputLen = 0;
- Serial.setTimeout(timeout);
- inputLen = Serial.readBytesUntil(endOfLineChar, input, maxLength);
- input[inputLen]=0;//null-terminate it
- Serial.setTimeout(0);
- //Serial.println();
- return inputLen;
-}
-
-/// returns TRUE if a HEX file transmission was detected and it was actually transmitted successfully
-boolean CheckForSerialHEX(byte* input, byte inputLen, RFM12B radio, byte targetID, uint16_t TIMEOUT, uint16_t ACKTIMEOUT, boolean DEBUG)
-{
- if (inputLen == 4 && input[0]=='F' && input[1]=='L' && input[2]=='X' && input[3]=='?') {
- if (HandleSerialHandshake(radio, targetID, false, TIMEOUT, ACKTIMEOUT, DEBUG))
- {
- Serial.println("FLX?OK"); //signal serial handshake back to host script
- if (HandleSerialHEXData(radio, targetID, TIMEOUT, ACKTIMEOUT, DEBUG))
- {
- Serial.println("FLX?OK"); //signal EOF serial handshake back to host script
- if (DEBUG) Serial.println("FLASH IMG TRANSMISSION SUCCESS");
- return true;
- }
- if (DEBUG) Serial.println("FLASH IMG TRANSMISSION FAIL");
- return false;
- }
- }
- return false;
-}
-
-boolean HandleSerialHandshake(RFM12B radio, byte targetID, boolean isEOF, uint16_t TIMEOUT, uint16_t ACKTIMEOUT, boolean DEBUG)
-{
- //temp
- //return true;
-
- byte retries = 3;
- long now = millis();
-
- while (millis()-now= 6) { //FLX:9:
- if (input[0]=='F' && input[1]=='L' && input[2]=='X')
- {
- if (input[3]==':')
- {
- byte index = 3;
- for (byte i = 4; i<8; i++) //up to 4 characters for seq number
- {
- index++;
- if (input[i] >=48 && input[i]<=57)
- tmp = tmp*10+input[i]-48;
- else if (input[i]==':')
- {
- if (i==4)
- return false;
- else break;
- }
- }
- //Serial.print("input[index] = ");Serial.print("[");Serial.print(index);Serial.print("]=");Serial.println(input[index]);
- if (input[index++] != ':') return false;
- now = millis(); //got good packet
-
- byte hexDataLen = validateHEXData(input+index, inputLen-index);
- if (hexDataLen>0)
- {
- if (tmp==seq) //only read data when packet number is the next expected SEQ number
- {
- byte sendBufLen = prepareSendBuffer(input+index+8, sendBuf, hexDataLen, seq); //extract HEX data from input to BYTE data into sendBuf (go from 2 HEX bytes to 1 byte), +8 will jump over the header directly to the HEX raw data
- //Serial.print("PREP ");Serial.print(sendBufLen); Serial.print(" > "); PrintHex83(sendBuf, sendBufLen);
-
- //SEND RADIO DATA
- if (sendHEXPacket(radio, remoteID, sendBuf, sendBufLen, seq, TIMEOUT, ACKTIMEOUT, DEBUG))
- {
- sprintf((char*)sendBuf, "FLX:%u:OK",seq);
- Serial.println((char*)sendBuf); //response to host (python?)
- seq++;
- }
- else return false;
- }
- }
- else Serial.println("FLX:INV");
- }
- if (inputLen==7 && input[3]=='?' && input[4]=='E' && input[5]=='O' && input[6]=='F')
- {
- //SEND RADIO EOF
- return HandleSerialHandshake(radio, targetID, true, TIMEOUT, ACKTIMEOUT, DEBUG);
- }
- }
- }
-
- //abort FLASH sequence if no valid packet received for a long time
-timeoutcheck:
- if (millis()-now > TIMEOUT)
- {
- Serial.print("Timeout receiving FLASH image from SERIAL, aborting...");
- //send abort msg or just let node timeout as well?
- return false;
- }
- }
- return true;
-}
-
-//returns length of HEX data bytes if everything is valid
-//returns 0 if any validation failed
-byte validateHEXData(void* data, byte length)
-{
- //assuming 1 byte record length, 2 bytes address, 1 byte record type, N data bytes, 1 CRC byte
- char* input = (char*)data;
- if (length <12 || length%2!=0) return 0; //shortest possible intel data HEX record is 12 bytes
- //Serial.print("VAL > "); Serial.println((char*)input);
-
- uint16_t checksum=0;
- //check valid HEX data and CRC
- for (byte i=0; i=48 && input[i]<=57) || (input[i] >=65 && input[i]<=70))) //0-9,A-F
- return 0;
- if (i%2 && i=65?MSB-55:MSB-48)*16 + (LSB>=65?LSB-55:LSB-48);
-}
-
-//return the SEQ of the ACK received, or -1 if invalid
-boolean sendHEXPacket(RFM12B radio, byte targetID, byte* sendBuf, byte hexDataLen, uint16_t seq, uint16_t TIMEOUT, uint16_t ACKTIMEOUT, boolean DEBUG)
-{
- long now = millis();
-
- while(1) {
- if (DEBUG) { Serial.print("RFTX > "); PrintHex83(sendBuf, hexDataLen); }
- radio.Send(targetID, sendBuf, hexDataLen, true);
-
- if (waitForAck(radio, ACKTIMEOUT))
- {
- byte ackLen = *radio.DataLen;
-
- if (DEBUG) { Serial.print("RFACK > "); Serial.print(ackLen); Serial.print(" > "); PrintHex83((byte*)radio.Data, ackLen); }
-
- if (ackLen >= 8 && radio.Data[0]=='F' && radio.Data[1]=='L' && radio.Data[2]=='X' &&
- radio.Data[3]==':' && radio.Data[ackLen-3]==':' &&
- radio.Data[ackLen-2]=='O' && radio.Data[ackLen-1]=='K')
- {
- uint16_t tmp=0;
- sscanf((const char*)radio.Data, "FLX:%u:OK", &tmp);
- return tmp == seq;
- }
- }
-
- if (millis()-now > TIMEOUT)
- {
- Serial.println("Timeout waiting for packet ACK, aborting FLASH operation ...");
- break; //abort FLASH sequence if no valid ACK was received for a long time
- }
- }
- return false;
-}
-
-// wait a few milliseconds for proper ACK to me, return true if indeed received
-boolean waitForAck(RFM12B radio, uint16_t ACKTIMEOUT)
-{
- long now = millis();
- while (millis() - now <= ACKTIMEOUT) {
- if (radio.ACKReceived(radio.GetSender()))
- return true;
- }
- return false;
-}
-
-void PrintHex83(uint8_t *data, uint8_t length) // prints 8-bit data in hex
-{
- char tmp[length*2+1];
- byte first ;
- int j=0;
- for (uint8_t i=0; i> 4) | 48;
- if (first > 57) tmp[j] = first + (byte)39;
- else tmp[j] = first ;
- j++;
-
- first = (data[i] & 0x0F) | 48;
- if (first > 57) tmp[j] = first + (byte)39;
- else tmp[j] = first;
- j++;
- }
- tmp[length*2] = 0;
- Serial.println(tmp);
-}
-
-/// Use watchdog to reset
-void resetUsingWatchdog(boolean DEBUG)
-{
- //wdt_disable();
- if (DEBUG) Serial.print("REBOOTING");
- wdt_enable(WDTO_15MS);
- while(1) if (DEBUG) Serial.print('.');
-}
diff --git a/WirelessHEX.h b/WirelessHEX.h
deleted file mode 100644
index c94e62b..0000000
--- a/WirelessHEX.h
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * Copyright (c) 2013 by Felix Rusu
- * Library for facilitating wireless programming using an RFM12B radio (get library at: http://github.com/LowPowerLab/RFM12B)
- * and the SPI Flash memory library for arduino/moteino (get library at: http://github.com/LowPowerLab/SPIFlash)
- * DEPENDS ON the two libraries mentioned above, and comes bundled with the SPIFlash library (above link)
- * Install all three of these libraries in your Arduino/libraries folder ([Arduino > Preferences] for location of Arduino folder)
- *
- * 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 _WirelessHEX_H_
-#define _WirelessHEX_H_
-#define LED 9 //LED on digital pin 9
-
-#ifndef DEFAULT_TIMEOUT
- #define DEFAULT_TIMEOUT 3000
-#endif
-
-#ifndef ACK_TIMEOUT
- #define ACK_TIMEOUT 20
-#endif
-
-#include
-#include
-
-//functions used in the REMOTE node
-void CheckForWirelessHEX(RFM12B radio, SPIFlash flash, boolean DEBUG=false);
-void resetUsingWatchdog(boolean DEBUG=false);
-boolean HandleWirelessHEXData(RFM12B radio, byte remoteID, SPIFlash flash, boolean DEBUG=false);
-
-//functions used in the MAIN node
-boolean CheckForSerialHEX(byte* input, byte inputLen, RFM12B radio, byte targetID, uint16_t TIMEOUT=DEFAULT_TIMEOUT, uint16_t ACKTIMEOUT=ACK_TIMEOUT, boolean DEBUG=false);
-boolean HandleSerialHandshake(RFM12B radio, byte targetID, boolean isEOF, uint16_t TIMEOUT=DEFAULT_TIMEOUT, uint16_t ACKTIMEOUT=ACK_TIMEOUT, boolean DEBUG=false);
-boolean HandleSerialHEXData(RFM12B radio, byte targetID, uint16_t TIMEOUT=DEFAULT_TIMEOUT, uint16_t ACKTIMEOUT=ACK_TIMEOUT, boolean DEBUG=false);
-boolean waitForAck(RFM12B radio, uint16_t ACKTIMEOUT=ACK_TIMEOUT);
-
-byte validateHEXData(void* data, byte length);
-byte prepareSendBuffer(char* hexdata, byte*buf, byte length, uint16_t seq);
-boolean sendHEXPacket(RFM12B radio, byte remoteID, byte* sendBuf, byte hexDataLen, uint16_t seq, uint16_t TIMEOUT=DEFAULT_TIMEOUT, uint16_t ACKTIMEOUT=ACK_TIMEOUT, boolean DEBUG=false);
-byte BYTEfromHEX(char MSB, char LSB);
-byte readSerialLine(char* input, char endOfLineChar=10, byte maxLength=64, uint16_t timeout=1000);
-void PrintHex83(byte* data, byte length);
-
-#endif
diff --git a/keywords.txt b/keywords.txt
index c0c3a30..6c6903c 100644
--- a/keywords.txt
+++ b/keywords.txt
@@ -1,5 +1,4 @@
-SPIFlash KEYWORD1
-WirelessHEX KEYWORD1
+SPIFlash KEYWORD1
initialize KEYWORD2
command KEYWORD2
readStatus KEYWORD2
@@ -12,11 +11,6 @@ chipErase KEYWORD2
blockErase4K KEYWORD2
blockErase32K KEYWORD2
readDeviceId KEYWORD2
-end KEYWORD2
-CheckForWirelessHEX KEYWORD2
-HandleWirelessHEXData KEYWORD2
-readSerialLine KEYWORD2
-BYTEfromHEX KEYWORD2
-waitForAck KEYWORD2
-PrintHex83 KEYWORD2
-resetUsingWatchdog KEYWORD2
+sleep KEYWORD2
+wakeup KEYWORD2
+end KEYWORD2
\ No newline at end of file