From fac2f3f530eed4e509e65103a7d09116c3944ead Mon Sep 17 00:00:00 2001
From: Pkarc <pkarc@2stripes.org>
Date: Sat, 17 Dec 2011 01:31:12 -0500
Subject: [PATCH 01/10] Implements "much easier to use" as KarlP said in his
 blog, and some functions to get only the relatively "important data bytes

---
 mrf24j.cpp | 138 ++++++++++++++++++++++++++++++++++++++++++++++-------
 1 file changed, 121 insertions(+), 17 deletions(-)

diff --git a/mrf24j.cpp b/mrf24j.cpp
index 38f113c..4cd09b4 100644
--- a/mrf24j.cpp
+++ b/mrf24j.cpp
@@ -1,13 +1,31 @@
 /**
  * mrf24j.cpp, Karl Palsson, 2011, karlp@tweak.net.au
- * modifed bsd license / apache license
+ * modified bsd license / apache license
  */
 
-#include "WProgram.h"
+//#include "WProgram.h" //already in mrf24j.h
 #include "mrf24j.h"
 
 
+// aMaxPHYPacketSize = 127, from the 802.15.4-2006 standard.
+static uint8_t rx_buf[127];
 
+// essential for obtaining the data frame only
+static int bytes_MHR = 9; // header length = 2 Frame control + 1 sequence number + 2 panid + 2 shortAddr Destination + 2 shortAddr Source
+static int bytes_FCS = 2; // FCS length = 2
+static int bytes_nodata = bytes_MHR + bytes_FCS; // no_data bytes in PHY payload,  header length + FCS
+
+volatile uint8_t flag_got_rx;
+volatile uint8_t flag_got_tx;
+
+static rx_info_t rx_info;
+static tx_info_t tx_info;
+
+
+/**
+ * Constructor MRF24J Object.
+ * @param pin_reset, @param pin_chip_select, @param pin_interrupt
+ */
 Mrf24j::Mrf24j(int pin_reset, int pin_chip_select, int pin_interrupt) {
     _pin_reset = pin_reset;
     _pin_cs = pin_chip_select;
@@ -17,10 +35,9 @@ Mrf24j::Mrf24j(int pin_reset, int pin_chip_select, int pin_interrupt) {
     pinMode(_pin_cs, OUTPUT);
     pinMode(_pin_int, INPUT);
 
+    SPI.setBitOrder(MSBFIRST) ;
+    SPI.setDataMode(SPI_MODE0);
     SPI.begin();
-    // arguably should not be here...
-    reset();
-    init();
 }
 
 void Mrf24j::reset(void) {
@@ -34,7 +51,7 @@ byte Mrf24j::read_short(byte address) {
     digitalWrite(_pin_cs, LOW);
     // 0 top for short addressing, 0 bottom for read
     SPI.transfer(address<<1 & 0b01111110);
-    byte ret = SPI.transfer(0x0);
+    byte ret = SPI.transfer(0x00);
     digitalWrite(_pin_cs, HIGH);
     return ret;
 }
@@ -53,7 +70,7 @@ byte Mrf24j::read_long(word address) {
 
 void Mrf24j::write_short(byte address, byte data) {
     digitalWrite(_pin_cs, LOW);
-    // 0 for top address, 1 bottom for write
+    // 0 for top short address, 1 bottom for write
     SPI.transfer((address<<1 & 0b01111110) | 0x01);
     SPI.transfer(data);
     digitalWrite(_pin_cs, HIGH);
@@ -93,15 +110,16 @@ word Mrf24j::address16_read(void) {
  * Simple send 16, with acks, not much of anything.. assumes src16 and local pan only.
  * @param data
  */
-void Mrf24j::send16(word dest16, byte len, char * data) {
-
+void Mrf24j::send16(word dest16, char * data) {
+    byte len = strlen(data); // get the length of the char* array
     int i = 0;
-    write_long(i++, 9);  // header length
-    write_long(i++, 9+2+len); //+2 is because module seems to ignore 2 bytes after the header?!
+    write_long(i++, 9); // header length
+    write_long(i++, 9+len);  // data payload length 0x001
+    //write_long(i++, 9+2+len); //+2 is because module seems to ignore 2 bytes after the header?!. becose 2 FCS bytes appended by TXMAC
 
-// 0 | pan compression | ack | no security | no data pending | data frame[3 bits]
+    // 0 | pan compression | ack | no security | no data pending | data frame[3 bits]
     write_long(i++, 0b01100001); // first byte of Frame Control
-// 16 bit source, 802.15.4 (2003), 16 bit dest,
+    // 16 bit source, 802.15.4 (2003), 16 bit dest,
     write_long(i++, 0b10001000); // second byte of frame control
     write_long(i++, 1);  // sequence number 1
 
@@ -116,7 +134,7 @@ void Mrf24j::send16(word dest16, byte len, char * data) {
     write_long(i++, src16 & 0xff); // src16 low
     write_long(i++, src16 >> 8); // src16 high
 
-    i+=2;  // All testing seems to indicate that the next two bytes are ignored.
+    //i+=2;  // All testing seems to indicate that the next two bytes are ignored. again 2 bytes on FCS appended by TXMAC
     for (int q = 0; q < len; q++) {
         write_long(i++, data[q]);
     }
@@ -136,13 +154,13 @@ void Mrf24j::set_channel(byte channel) {
 }
 
 void Mrf24j::init(void) {
-/*
- // Seems a bit ridiculous when I use reset pin anyway
+    /*
+    // Seems a bit ridiculous when I use reset pin anyway
     write_short(MRF_SOFTRST, 0x7); // from manual
     while (read_short(MRF_SOFTRST) & 0x7 != 0) {
         ; // wait for soft reset to finish
     }
-*/
+    */
     write_short(MRF_PACON2, 0x98); // – Initialize FIFOEN = 1 and TXONTS = 0x6.
     write_short(MRF_TXSTBL, 0x95); // – Initialize RFSTBL = 0x9.
 
@@ -163,11 +181,81 @@ void Mrf24j::init(void) {
     set_channel(12);
     // max power is by default.. just leave it...
     //Set transmitter power - See “REGISTER 2-62: RF CONTROL 3 REGISTER (ADDRESS: 0x203)”.
+    write_long(MRF_RFCON3, 0x00); // transmitter max power
+    write_long(MRF_TESTMODE, 0x07); // Enables PA/LNA on MRF24J40MB module, otherwise, comment this line.
+
     write_short(MRF_RFCTL, 0x04); //  – Reset RF state machine.
     write_short(MRF_RFCTL, 0x00); // part 2
     delay(1); // delay at least 192usec
 }
 
+/**
+ * Call this from within an interrupt handler connected to the MRFs output
+ * interrupt pin.  It handles reading in any data from the module, and letting it
+ * continue working.
+ * Only the most recent data is ever kept.
+ */
+void Mrf24j::interrupt_handler(void) {
+    uint8_t last_interrupt = read_short(MRF_INTSTAT);
+    if (last_interrupt & MRF_I_RXIF) {
+        flag_got_rx++;
+        // read out the packet data...
+        noInterrupts();
+        rx_disable();
+        uint8_t frame_length = read_long(0x300);  // read start of rxfifo for, has 2 bytes more added by FCS. frame_length = m + n + 2
+
+        /*
+        * Uncomment this block, if you want all PHY Payload bytes in the rx_buf buffer
+        *
+        // buffer all bytes in PHY Payload
+        int rb_ptr = 0;
+        for (int i = 0; i < frame_length; i++) { // from 0x301 to (0x301 + frame_length -1)
+            rx_buf[rb_ptr++] = read_long(0x301 + i);
+        }
+        */
+
+        // buffer data bytes
+        int rd_ptr = 0;
+        for (int i = 0; i < rx_datalength(); i++) { // from (0x301 + bytes_MHR) to (0x301 + frame_length - bytes_nodata - 1)
+            rx_info.rx_data[rd_ptr++] = read_long(0x301 + bytes_MHR + i);
+        }
+
+        rx_info.frame_length = frame_length;
+        rx_info.lqi = read_long(0x301 + frame_length); // same as datasheet 0x301 + (m + n + 2) <-- frame_length
+        rx_info.rssi = read_long(0x301 + frame_length + 1); // same as datasheet 0x301 + (m + n + 3) <-- frame_length + 1
+
+        rx_enable();
+        interrupts();
+    }
+    if (last_interrupt & MRF_I_TXNIF) {
+        flag_got_tx++;
+        uint8_t tmp = read_short(MRF_TXSTAT);
+        // 1 means it failed, we want 1 to mean it worked.
+        tx_info.tx_ok = !(tmp & ~(1 << TXNSTAT));
+        tx_info.retries = tmp >> 6;
+        tx_info.channel_busy = (tmp & (1 << CCAFAIL));
+    }
+}
+
+
+/**
+ * Call this function periodically, it will invoke your nominated handlers
+ */
+void Mrf24j::check_flags(void (*rx_handler)(void), void (*tx_handler)(void)){
+    // TODO - we could check whether the flags are > 1 here, indicating data was lost?
+    if (flag_got_rx) {
+        flag_got_rx = 0;
+        rx_handler();
+    }
+    if (flag_got_tx) {
+        flag_got_tx = 0;
+        tx_handler();
+    }
+}
+
+/**
+ * Set RX mode to promiscuous, or normal
+ */
 void Mrf24j::set_promiscuous(boolean enabled) {
     if (enabled) {
         write_short(MRF_RXMCR, 0x01);
@@ -176,6 +264,22 @@ void Mrf24j::set_promiscuous(boolean enabled) {
     }
 }
 
+rx_info_t * Mrf24j::get_rxinfo(void) {
+    return &rx_info;
+}
+
+tx_info_t * Mrf24j::get_txinfo(void) {
+    return &tx_info;
+}
+
+uint8_t * Mrf24j::get_rxbuf(void) {
+    return rx_buf;
+}
+
+int Mrf24j::rx_datalength(void) {
+    return rx_info.frame_length - bytes_nodata;
+}
+
 void Mrf24j::rx_flush(void) {
     write_short(MRF_RXFLUSH, 0x01);
 }

From 45fe53697945acfe624c46264fddb26a28fd614a Mon Sep 17 00:00:00 2001
From: Pkarc <pkarc@2stripes.org>
Date: Sat, 17 Dec 2011 01:31:52 -0500
Subject: [PATCH 02/10] Implements "much easier to use" as KarlP said in his
 blog, and some functions to get only the relatively "important data bytes

---
 mrf24j.h | 90 ++++++++++++++++++++++++++++++++++++--------------------
 1 file changed, 58 insertions(+), 32 deletions(-)

diff --git a/mrf24j.h b/mrf24j.h
index dc55949..a4550fb 100644
--- a/mrf24j.h
+++ b/mrf24j.h
@@ -1,4 +1,4 @@
-/* 
+/*
  * File:   mrf24j.h
  * copyright Karl Palsson, karlp@tweak.net.au, 2011
  * modified BSD License / apache license
@@ -7,7 +7,11 @@
 #ifndef LIB_MRF24J_H
 #define LIB_MRF24J_H
 
-#include "WProgram.h"
+#if defined(ARDUINO) && ARDUINO >= 100 // Arduino IDE version >= 1.0
+    #include "Arduino.h"
+#else // older Arduino IDE versions
+    #include "WProgram.h"
+#endif
 #include "SPI.h"
 
 
@@ -143,52 +147,74 @@
 #define MRF_I_RXIF  0b00001000
 #define MRF_I_TXNIF 0b00000001
 
+typedef struct _rx_info_t{
+    uint8_t frame_length;
+    uint8_t rx_data[116]; //max data length = (127 aMaxPHYPacketSize - 2 Frame control - 1 sequence number - 2 panid - 2 shortAddr Destination - 2 shortAddr Source - 2 FCS)
+    uint8_t lqi;
+    uint8_t rssi;
+} rx_info_t;
+
+/**
+ * Based on the TXSTAT register, but "better"
+ */
+typedef struct _tx_info_t{
+    uint8_t tx_ok:1;
+    uint8_t retries:2;
+    uint8_t channel_busy:1;
+} tx_info_t;
 
 class Mrf24j
 {
+    public:
+        Mrf24j(int pin_reset, int pin_chip_select, int pin_interrupt);
+        void reset(void);
+        void init(void);
 
-public:
-Mrf24j(int pin_reset, int pin_chip_select, int pin_interrupt);
-void reset(void);
-void init(void);
+        byte read_short(byte address);
+        byte read_long(word address);
 
-byte read_short(byte address);
-byte read_long(word address);
+        void write_short(byte address, byte data);
+        void write_long(word address, byte data);
 
-void write_short(byte address, byte data);
-void write_long(word address, byte data);
+        word get_pan(void);
+        void set_pan(word panid);
 
-word get_pan(void);
-void set_pan(word panid);
+        void address16_write(word address16);
+        word address16_read(void);
 
-void address16_write(word address16);
-word address16_read(void);
+        void set_interrupts(void);
 
-void set_interrupts(void);
+        void set_promiscuous(boolean enabled);
 
-void set_promiscuous(boolean enabled);
+        /**
+         * Set the channel, using 802.15.4 channel numbers (11..26)
+         */
+        void set_channel(byte channel);
 
-/**
- * Set the channel, using 802.15.4 channel numbers (11..26)
- */
-void set_channel(byte channel);
+        void rx_enable(void);
+        void rx_disable(void);
 
-void rx_enable(void);
-void rx_disable(void);
+        /** If you want to throw away rx data */
+        void rx_flush(void);
 
-/** If you want to throw away rx data */
-void rx_flush(void);
+        rx_info_t * get_rxinfo(void);
 
-void send16(word dest16, byte len, char * data);
+        tx_info_t * get_txinfo(void);
 
-private:
-    int _pin_reset;
-    int _pin_cs;
-    int _pin_int;
+        uint8_t * get_rxbuf(void);
 
+        int rx_datalength(void);
 
+        void send16(word dest16, char * data);
+
+        void interrupt_handler(void);
+
+        void check_flags(void (*rx_handler)(void), void (*tx_handler)(void));
+
+    private:
+        int _pin_reset;
+        int _pin_cs;
+        int _pin_int;
 };
 
-#endif  /* LIB_MRF24J_H */
-
-
+#endif  /* LIB_MRF24J_H */
\ No newline at end of file

From b60c20a61d61d73deeb7be551ee65423ec278371 Mon Sep 17 00:00:00 2001
From: Pkarc <pkarc@2stripes.org>
Date: Sat, 17 Dec 2011 01:33:24 -0500
Subject: [PATCH 03/10] Implements "much easier to use" as KarlP said in his
 blog, and some functions to get only the relatively "important data bytes

---
 examples/Basic_TwoWay/Basic_TwoWay.pde | 93 ++++++++++----------------
 1 file changed, 36 insertions(+), 57 deletions(-)

diff --git a/examples/Basic_TwoWay/Basic_TwoWay.pde b/examples/Basic_TwoWay/Basic_TwoWay.pde
index f77dcd7..03c39ac 100644
--- a/examples/Basic_TwoWay/Basic_TwoWay.pde
+++ b/examples/Basic_TwoWay/Basic_TwoWay.pde
@@ -10,8 +10,8 @@
 #include <mrf24j.h>
 
 const int pin_reset = 6;
-const int pin_cs = 7;
-const int pin_interrupt = 5;
+const int pin_cs = 10; // default CS pin on ATMEGA8
+const int pin_interrupt = 2; // default interrupt pin on ATMEGA8
 
 Mrf24j mrf(pin_reset, pin_cs, pin_interrupt);
 
@@ -20,75 +20,54 @@ long tx_interval = 1000;
 
 void setup() {
   Serial.begin(9600);
-
+  
+  mrf.reset();
+  mrf.init();
+  
   mrf.set_pan(0xcafe);
   // This is _our_ address
   mrf.address16_write(0x6001); 
-
+  
   // uncomment if you want to receive any packet on this channel
-  // mrf.set_promiscuous(true);
-
-  attachInterrupt(0, interrupt_routine, CHANGE);   
+  //mrf.set_promiscuous(true);
+  
+  attachInterrupt(0, interrupt_routine, CHANGE); // interrupt 0 equivalent to pin 2 on ATMEGA8
   last_time = millis();
+  interrupts();
 }
 
-volatile uint8_t gotrx;
-volatile uint8_t txok;
-
 void interrupt_routine() {
-    // read and clear from the radio
-    byte last_interrupt = mrf.read_short(MRF_INTSTAT);
-    if (last_interrupt & MRF_I_RXIF) {
-        gotrx = 1;
-    }
-    if (last_interrupt & MRF_I_TXNIF) {
-        txok = 1;
-    }
+    mrf.interrupt_handler(); // mrf24 object interrupt routine
 }
 
 void loop() {
-    int tmp;
-    interrupts();
+    mrf.check_flags(&handle_rx, &handle_tx);
     unsigned long current_time = millis();
     if (current_time - last_time > tx_interval) {
         last_time = current_time;
         Serial.println("txxxing...");
-        mrf.send16(0x4202, 4, "abcd");
+        mrf.send16(0x4202, "abcd");
     }
-    if (txok) {
-        txok = 0;
-        Serial.print("tx went ok:");
-        tmp = mrf.read_short(MRF_TXSTAT);
-        Serial.print(tmp);
-        if (!(tmp & ~(1<<TXNSTAT))) {  // 1 = failed
-            Serial.print("...And we got an ACK");
-        } else {
-            Serial.print("retried ");
-            Serial.print(tmp >> 6, HEX);
-        }
-        Serial.println();
-    }
-    if (gotrx) {
-        gotrx = 0;
-        noInterrupts();
-        mrf.rx_disable();
-
-        byte frame_length = mrf.read_long(0x300);  // read start of rxfifo
-        Serial.print("received a packet ");Serial.print(frame_length, DEC);Serial.println(" bytes long");
-        Serial.println("Packet data:");
-        for (int i = 1; i <= frame_length; i++) {
-            tmp = mrf.read_long(0x300 + i);
-            Serial.print(tmp, HEX);
-        }
-        Serial.print("\r\nLQI/RSSI=");
-        byte lqi = mrf.read_long(0x300 + frame_length + 1);
-        byte rssi = mrf.read_long(0x300 + frame_length + 2);
-        Serial.print(lqi, HEX);
-        Serial.println(rssi, HEX);
-
-        mrf.rx_enable();
-        interrupts();
-
-    }
-  
 }
+
+void handle_rx() {
+    Serial.print("received a packet ");Serial.print(mrf.get_rxinfo()->frame_length, DEC);Serial.println(" bytes long");
+    
+    Serial.println("Packet data:");
+    for (int i = 0; i < mrf.rx_datalength(); i++) {
+        Serial.write(mrf.get_rxinfo()->rx_data[i]);
+    }
+    
+    Serial.print("\r\nLQI/RSSI=");
+    Serial.print(mrf.get_rxinfo()->lqi, DEC);
+    Serial.print("/");
+    Serial.println(mrf.get_rxinfo()->rssi, DEC);
+}
+
+void handle_tx() {
+    if (mrf.get_txinfo()->tx_ok) {
+        Serial.println("TX went ok, got ack");
+    } else {
+        Serial.print("TX failed after ");Serial.print(mrf.get_txinfo()->retries);Serial.println(" retries\n");
+    }
+}
\ No newline at end of file

From ecf1342ec8f267a79aa331da3fa0bf96473ac007 Mon Sep 17 00:00:00 2001
From: Pkarc <pkarc@2stripes.org>
Date: Sat, 17 Dec 2011 01:33:54 -0500
Subject: [PATCH 04/10] Implements "much easier to use" as KarlP said in his
 blog, and some functions to get only the relatively "important data bytes

---
 examples/RX_only/RX_only.pde | 62 ++++++++++++++----------------------
 1 file changed, 24 insertions(+), 38 deletions(-)

diff --git a/examples/RX_only/RX_only.pde b/examples/RX_only/RX_only.pde
index 07d598c..624dc2c 100644
--- a/examples/RX_only/RX_only.pde
+++ b/examples/RX_only/RX_only.pde
@@ -10,8 +10,8 @@
 #include <mrf24j.h>
 
 const int pin_reset = 6;
-const int pin_cs = 7;
-const int pin_interrupt = 5;
+const int pin_cs = 10; // default CS pin on ATMEGA8
+const int pin_interrupt = 2; // default interrupt pin on ATMEGA8
 
 Mrf24j mrf(pin_reset, pin_cs, pin_interrupt);
 
@@ -26,46 +26,32 @@ void setup() {
   // uncomment if you want to receive any packet on this channel
   // mrf.set_promiscuous(true);
 
-  attachInterrupt(0, interrupt_routine, CHANGE);   
+  attachInterrupt(0, interrupt_routine, CHANGE); // interrupt 0 equivalent to pin 2 on ATMEGA8
+  interrupts();
 }
 
-volatile uint8_t gotrx;
-
 void interrupt_routine() {
-    // read and clear from the radio
-    byte last_interrupt = mrf.read_short(MRF_INTSTAT);
-    if (last_interrupt & MRF_I_RXIF) {
-        gotrx = 1;
-    }
+  mrf.interrupt_handler();
 }
 
 void loop() {
-    int tmp;
-    interrupts();
-    if (gotrx) {
-        gotrx = 0;
-        noInterrupts();
-        mrf.rx_disable();
-
-        // read start of rxfifo
-        byte frame_length = mrf.read_long(0x300);
-        Serial.print("received a packet ");
-        Serial.print(frame_length, DEC);
-        Serial.println(" bytes long");
-
-        Serial.println("Packet data:");
-        for (int i = 1; i <= frame_length; i++) {
-            tmp = mrf.read_long(0x300 + i);
-            Serial.print(tmp, HEX);
-        }
-
-        Serial.print("\r\nLQI/RSSI=");
-        byte lqi = mrf.read_long(0x300 + frame_length + 1);
-        byte rssi = mrf.read_long(0x300 + frame_length + 2);
-        Serial.print(lqi, HEX);
-        Serial.println(rssi, HEX);
-
-        mrf.rx_enable();
-        interrupts();
-    }
+    mrf.check_flags(&handle_rx, &handle_tx);
 }
+
+void handle_rx() {
+    Serial.print("received a packet ");Serial.print(mrf.get_rxinfo()->frame_length, DEC);Serial.println(" bytes long");
+    
+    Serial.println("Packet data:");
+    for (int i = 0; i < mrf.rx_datalength(); i++) {
+        Serial.write(mrf.get_rxinfo()->rx_data[i]);
+    }
+    
+    Serial.print("\r\nLQI/RSSI=");
+    Serial.print(mrf.get_rxinfo()->lqi, DEC);
+    Serial.print("/");
+    Serial.println(mrf.get_rxinfo()->rssi, DEC);
+}
+
+void handle_tx() {
+    // code to transmit, nothing to do
+}
\ No newline at end of file

From 693b3bfed3bf6d9a99a5081b8147fad41d870f96 Mon Sep 17 00:00:00 2001
From: Pkarc <pkarc@2stripes.org>
Date: Sat, 17 Dec 2011 01:34:31 -0500
Subject: [PATCH 05/10] Implements "much easier to use" as KarlP said in his
 blog, and some functions to get only the relatively "important data bytes

---
 examples/TX_only/TX_only.pde | 32 ++++++++++++++++++--------------
 1 file changed, 18 insertions(+), 14 deletions(-)

diff --git a/examples/TX_only/TX_only.pde b/examples/TX_only/TX_only.pde
index 89c12a2..324b629 100644
--- a/examples/TX_only/TX_only.pde
+++ b/examples/TX_only/TX_only.pde
@@ -10,8 +10,8 @@
 #include <mrf24j.h>
 
 const int pin_reset = 6;
-const int pin_cs = 7;
-const int pin_interrupt = 5;
+const int pin_cs = 10; // default CS pin on ATMEGA8
+const int pin_interrupt = 2; // default interrupt pin on ATMEGA8
 
 Mrf24j mrf(pin_reset, pin_cs, pin_interrupt);
 
@@ -25,30 +25,34 @@ void setup() {
   // This is _our_ address
   mrf.address16_write(0x6001); 
 
-  attachInterrupt(0, interrupt_routine, CHANGE);   
+  attachInterrupt(0, interrupt_routine, CHANGE);   // interrupt 0 equivalent to pin 2 on ATMEGA8
 
   last_time = millis();
   interrupts();
 }
 
 void interrupt_routine() {
-    // read and clear interrupt flags from the radio
-    byte last_interrupt = mrf.read_short(MRF_INTSTAT);
-    // we don't care about the rx acks, but we need them to be flushed so it can keep receiving
-    if (last_interrupt & MRF_I_RXIF) {
-        mrf.rx_flush();
-    }
+    mrf.interrupt_handler(); // mrf24 object interrupt routine
 }
 
-
 void loop() {
-    int tmp;
+    mrf.check_flags(&handle_rx, &handle_tx);
     unsigned long current_time = millis();
     if (current_time - last_time > tx_interval) {
         last_time = current_time;
         Serial.println("txxxing...");
-        char * msg = "hello world";
-        mrf.send16(0x4202, strlen(msg), msg);
+        mrf.send16(0x4202, "abcd");
     }
-  
 }
+
+void handle_rx() {
+    // data to receive, nothing to do
+}
+
+void handle_tx() {
+    if (mrf.get_txinfo()->tx_ok) {
+        Serial.println("TX went ok, got ack");
+    } else {
+        Serial.print("TX failed after ");Serial.print(mrf.get_txinfo()->retries);Serial.println(" retries\n");
+    }
+}
\ No newline at end of file

From e5957bc11748236d1fa12a1334be58cd056a36c2 Mon Sep 17 00:00:00 2001
From: Pkarc <pkarc@2stripes.org>
Date: Sat, 17 Dec 2011 14:23:12 -0500
Subject: [PATCH 06/10] Added some config/init time options.

---
 mrf24j.cpp | 76 ++++++++++++++++++++++++++++++++++++++----------------
 1 file changed, 54 insertions(+), 22 deletions(-)

diff --git a/mrf24j.cpp b/mrf24j.cpp
index 4cd09b4..1e5d325 100644
--- a/mrf24j.cpp
+++ b/mrf24j.cpp
@@ -3,18 +3,21 @@
  * modified bsd license / apache license
  */
 
-//#include "WProgram.h" //already in mrf24j.h
 #include "mrf24j.h"
 
-
 // aMaxPHYPacketSize = 127, from the 802.15.4-2006 standard.
 static uint8_t rx_buf[127];
 
 // essential for obtaining the data frame only
-static int bytes_MHR = 9; // header length = 2 Frame control + 1 sequence number + 2 panid + 2 shortAddr Destination + 2 shortAddr Source
+// bytes_MHR = 2 Frame control + 1 sequence number + 2 panid + 2 shortAddr Destination + 2 shortAddr Source
+static int bytes_MHR = 9;
 static int bytes_FCS = 2; // FCS length = 2
 static int bytes_nodata = bytes_MHR + bytes_FCS; // no_data bytes in PHY payload,  header length + FCS
 
+static int ignoreBytes = 0; // bytes to ignore, some modules behaviour.
+
+static boolean bufPHY = false; // flag to buffer all bytes in PHY Payload, or not
+
 volatile uint8_t flag_got_rx;
 volatile uint8_t flag_got_tx;
 
@@ -113,9 +116,10 @@ word Mrf24j::address16_read(void) {
 void Mrf24j::send16(word dest16, char * data) {
     byte len = strlen(data); // get the length of the char* array
     int i = 0;
-    write_long(i++, 9); // header length
-    write_long(i++, 9+len);  // data payload length 0x001
-    //write_long(i++, 9+2+len); //+2 is because module seems to ignore 2 bytes after the header?!. becose 2 FCS bytes appended by TXMAC
+    write_long(i++, bytes_MHR); // header length
+    // +ignoreBytes is because some module seems to ignore 2 bytes after the header?!.
+    // default: ignoreBytes = 0;
+    write_long(i++, bytes_MHR+ignoreBytes+len);
 
     // 0 | pan compression | ack | no security | no data pending | data frame[3 bits]
     write_long(i++, 0b01100001); // first byte of Frame Control
@@ -134,7 +138,9 @@ void Mrf24j::send16(word dest16, char * data) {
     write_long(i++, src16 & 0xff); // src16 low
     write_long(i++, src16 >> 8); // src16 high
 
-    //i+=2;  // All testing seems to indicate that the next two bytes are ignored. again 2 bytes on FCS appended by TXMAC
+    // All testing seems to indicate that the next two bytes are ignored.
+    //2 bytes on FCS appended by TXMAC
+    i+=ignoreBytes;
     for (int q = 0; q < len; q++) {
         write_long(i++, data[q]);
     }
@@ -180,10 +186,7 @@ void Mrf24j::init(void) {
     set_interrupts();
     set_channel(12);
     // max power is by default.. just leave it...
-    //Set transmitter power - See “REGISTER 2-62: RF CONTROL 3 REGISTER (ADDRESS: 0x203)”.
-    write_long(MRF_RFCON3, 0x00); // transmitter max power
-    write_long(MRF_TESTMODE, 0x07); // Enables PA/LNA on MRF24J40MB module, otherwise, comment this line.
-
+    // Set transmitter power - See “REGISTER 2-62: RF CONTROL 3 REGISTER (ADDRESS: 0x203)”.
     write_short(MRF_RFCTL, 0x04); //  – Reset RF state machine.
     write_short(MRF_RFCTL, 0x00); // part 2
     delay(1); // delay at least 192usec
@@ -202,27 +205,29 @@ void Mrf24j::interrupt_handler(void) {
         // read out the packet data...
         noInterrupts();
         rx_disable();
-        uint8_t frame_length = read_long(0x300);  // read start of rxfifo for, has 2 bytes more added by FCS. frame_length = m + n + 2
+        // read start of rxfifo for, has 2 bytes more added by FCS. frame_length = m + n + 2
+        uint8_t frame_length = read_long(0x300);
 
-        /*
-        * Uncomment this block, if you want all PHY Payload bytes in the rx_buf buffer
-        *
         // buffer all bytes in PHY Payload
-        int rb_ptr = 0;
-        for (int i = 0; i < frame_length; i++) { // from 0x301 to (0x301 + frame_length -1)
-            rx_buf[rb_ptr++] = read_long(0x301 + i);
+        if(bufPHY){
+            int rb_ptr = 0;
+            for (int i = 0; i < frame_length; i++) { // from 0x301 to (0x301 + frame_length -1)
+                rx_buf[rb_ptr++] = read_long(0x301 + i);
+            }
         }
-        */
 
         // buffer data bytes
         int rd_ptr = 0;
-        for (int i = 0; i < rx_datalength(); i++) { // from (0x301 + bytes_MHR) to (0x301 + frame_length - bytes_nodata - 1)
+        // from (0x301 + bytes_MHR) to (0x301 + frame_length - bytes_nodata - 1)
+        for (int i = 0; i < rx_datalength(); i++) {
             rx_info.rx_data[rd_ptr++] = read_long(0x301 + bytes_MHR + i);
         }
 
         rx_info.frame_length = frame_length;
-        rx_info.lqi = read_long(0x301 + frame_length); // same as datasheet 0x301 + (m + n + 2) <-- frame_length
-        rx_info.rssi = read_long(0x301 + frame_length + 1); // same as datasheet 0x301 + (m + n + 3) <-- frame_length + 1
+        // same as datasheet 0x301 + (m + n + 2) <-- frame_length
+        rx_info.lqi = read_long(0x301 + frame_length);
+        // same as datasheet 0x301 + (m + n + 3) <-- frame_length + 1
+        rx_info.rssi = read_long(0x301 + frame_length + 1);
 
         rx_enable();
         interrupts();
@@ -280,6 +285,33 @@ int Mrf24j::rx_datalength(void) {
     return rx_info.frame_length - bytes_nodata;
 }
 
+void Mrf24j::set_ignoreBytes(int ib) {
+    // some modules behaviour
+    ignoreBytes = ib;
+}
+
+/**
+ * Set bufPHY flag to buffer all bytes in PHY Payload, or not
+ */
+void Mrf24j::set_bufferPHY(boolean bp) {
+    bufPHY = bp;
+}
+
+boolean Mrf24j::get_bufferPHY(void) {
+    return bufPHY;
+}
+
+/**
+ * Set PA/LNA external control
+ */
+void Mrf24j::set_palna(boolean enabled) {
+    if (enabled) {
+        write_long(MRF_TESTMODE, 0x07); // Enable PA/LNA on MRF24J40MB module.
+    }else{
+        write_long(MRF_TESTMODE, 0x00); // Disable PA/LNA on MRF24J40MB module.
+    }
+}
+
 void Mrf24j::rx_flush(void) {
     write_short(MRF_RXFLUSH, 0x01);
 }

From 22973b801b316f3a6353bc036555660b8c67356b Mon Sep 17 00:00:00 2001
From: Pkarc <pkarc@2stripes.org>
Date: Sat, 17 Dec 2011 14:23:38 -0500
Subject: [PATCH 07/10] Added some config/init time options.

---
 mrf24j.h | 16 +++++++++++++++-
 1 file changed, 15 insertions(+), 1 deletion(-)

diff --git a/mrf24j.h b/mrf24j.h
index a4550fb..a06589b 100644
--- a/mrf24j.h
+++ b/mrf24j.h
@@ -205,6 +205,20 @@ class Mrf24j
 
         int rx_datalength(void);
 
+        void set_ignoreBytes(int ib);
+
+        /**
+         * Set bufPHY flag to buffer all bytes in PHY Payload, or not
+         */
+        void set_bufferPHY(boolean bp);
+
+        boolean get_bufferPHY(void);
+
+        /**
+         * Set PA/LNA external control
+         */
+        void set_palna(boolean enabled);
+
         void send16(word dest16, char * data);
 
         void interrupt_handler(void);
@@ -217,4 +231,4 @@ class Mrf24j
         int _pin_int;
 };
 
-#endif  /* LIB_MRF24J_H */
\ No newline at end of file
+#endif  /* LIB_MRF24J_H */

From d154274100e6bd7a7785f19de7a07d0f6a31dc84 Mon Sep 17 00:00:00 2001
From: Pkarc <pkarc@2stripes.org>
Date: Sat, 17 Dec 2011 14:38:21 -0500
Subject: [PATCH 08/10] Added some config/init time options

---
 examples/Basic_TwoWay/Basic_TwoWay.pde | 23 ++++++++++++++++++-----
 1 file changed, 18 insertions(+), 5 deletions(-)

diff --git a/examples/Basic_TwoWay/Basic_TwoWay.pde b/examples/Basic_TwoWay/Basic_TwoWay.pde
index 03c39ac..7f7b52b 100644
--- a/examples/Basic_TwoWay/Basic_TwoWay.pde
+++ b/examples/Basic_TwoWay/Basic_TwoWay.pde
@@ -10,8 +10,8 @@
 #include <mrf24j.h>
 
 const int pin_reset = 6;
-const int pin_cs = 10; // default CS pin on ATMEGA8
-const int pin_interrupt = 2; // default interrupt pin on ATMEGA8
+const int pin_cs = 10; // default CS pin on ATmega8/168/328
+const int pin_interrupt = 2; // default interrupt pin on ATmega8/168/328
 
 Mrf24j mrf(pin_reset, pin_cs, pin_interrupt);
 
@@ -27,11 +27,17 @@ void setup() {
   mrf.set_pan(0xcafe);
   // This is _our_ address
   mrf.address16_write(0x6001); 
-  
+
   // uncomment if you want to receive any packet on this channel
   //mrf.set_promiscuous(true);
   
-  attachInterrupt(0, interrupt_routine, CHANGE); // interrupt 0 equivalent to pin 2 on ATMEGA8
+  // uncomment if you want to enable PA/LNA external control
+  //mrf.set_palna(true);
+  
+  // uncomment if you want to buffer all PHY Payload
+  //mrf.set_bufferPHY(true);
+
+  attachInterrupt(0, interrupt_routine, CHANGE); // interrupt 0 equivalent to pin 2(INT0) on ATmega8/168/328
   last_time = millis();
   interrupts();
 }
@@ -53,7 +59,14 @@ void loop() {
 void handle_rx() {
     Serial.print("received a packet ");Serial.print(mrf.get_rxinfo()->frame_length, DEC);Serial.println(" bytes long");
     
-    Serial.println("Packet data:");
+    if(mrf.get_bufferPHY()){
+      Serial.println("Packet data (PHY Payload):");
+      for (int i = 0; i < mrf.get_rxinfo()->frame_length; i++) {
+          Serial.print(mrf.get_rxbuf()[i]);
+      }
+    }
+    
+    Serial.println("\r\nASCII data (relevant data):");
     for (int i = 0; i < mrf.rx_datalength(); i++) {
         Serial.write(mrf.get_rxinfo()->rx_data[i]);
     }

From fe59becbba52cf34bbbdc5d0224205b24727ad5c Mon Sep 17 00:00:00 2001
From: Pkarc <pkarc@2stripes.org>
Date: Sat, 17 Dec 2011 14:42:19 -0500
Subject: [PATCH 09/10] Added some config/init time options

---
 examples/RX_only/RX_only.pde | 31 +++++++++++++++++++++++--------
 1 file changed, 23 insertions(+), 8 deletions(-)

diff --git a/examples/RX_only/RX_only.pde b/examples/RX_only/RX_only.pde
index 624dc2c..67d3807 100644
--- a/examples/RX_only/RX_only.pde
+++ b/examples/RX_only/RX_only.pde
@@ -10,28 +10,36 @@
 #include <mrf24j.h>
 
 const int pin_reset = 6;
-const int pin_cs = 10; // default CS pin on ATMEGA8
-const int pin_interrupt = 2; // default interrupt pin on ATMEGA8
+const int pin_cs = 10; // default CS pin on ATmega8/168/328
+const int pin_interrupt = 2; // default interrupt pin on ATmega8/168/328
 
 Mrf24j mrf(pin_reset, pin_cs, pin_interrupt);
 
 void setup() {
   Serial.begin(9600);
-
+  
+  mrf.reset();
+  mrf.init();
+  
   mrf.set_pan(0xcafe);
   // This is _our_ address
   mrf.address16_write(0x6001); 
-  mrf.set_channel(12);
 
   // uncomment if you want to receive any packet on this channel
-  // mrf.set_promiscuous(true);
+  //mrf.set_promiscuous(true);
+  
+  // uncomment if you want to enable PA/LNA external control
+  //mrf.set_palna(true);
+  
+  // uncomment if you want to buffer all PHY Payload
+  //mrf.set_bufferPHY(true);
 
-  attachInterrupt(0, interrupt_routine, CHANGE); // interrupt 0 equivalent to pin 2 on ATMEGA8
+  attachInterrupt(0, interrupt_routine, CHANGE); // interrupt 0 equivalent to pin 2(INT0) on ATmega8/168/328
   interrupts();
 }
 
 void interrupt_routine() {
-  mrf.interrupt_handler();
+  mrf.interrupt_handler(); // mrf24 object interrupt routine
 }
 
 void loop() {
@@ -41,7 +49,14 @@ void loop() {
 void handle_rx() {
     Serial.print("received a packet ");Serial.print(mrf.get_rxinfo()->frame_length, DEC);Serial.println(" bytes long");
     
-    Serial.println("Packet data:");
+    if(mrf.get_bufferPHY()){
+      Serial.println("Packet data (PHY Payload):");
+      for (int i = 0; i < mrf.get_rxinfo()->frame_length; i++) {
+          Serial.print(mrf.get_rxbuf()[i]);
+      }
+    }
+    
+    Serial.println("\r\nASCII data (relevant data):");
     for (int i = 0; i < mrf.rx_datalength(); i++) {
         Serial.write(mrf.get_rxinfo()->rx_data[i]);
     }

From 1a92fdfc8eb778703ba4f1d4faed74b921732c10 Mon Sep 17 00:00:00 2001
From: Pkarc <pkarc@2stripes.org>
Date: Sat, 17 Dec 2011 14:44:18 -0500
Subject: [PATCH 10/10] Added some config/init time options

---
 examples/TX_only/TX_only.pde | 21 ++++++++++-----------
 1 file changed, 10 insertions(+), 11 deletions(-)

diff --git a/examples/TX_only/TX_only.pde b/examples/TX_only/TX_only.pde
index 324b629..314f51a 100644
--- a/examples/TX_only/TX_only.pde
+++ b/examples/TX_only/TX_only.pde
@@ -10,8 +10,8 @@
 #include <mrf24j.h>
 
 const int pin_reset = 6;
-const int pin_cs = 10; // default CS pin on ATMEGA8
-const int pin_interrupt = 2; // default interrupt pin on ATMEGA8
+const int pin_cs = 10; // default CS pin on ATmega8/168/328
+const int pin_interrupt = 2; // default interrupt pin on ATmega8/168/328
 
 Mrf24j mrf(pin_reset, pin_cs, pin_interrupt);
 
@@ -20,13 +20,18 @@ long tx_interval = 1000;
 
 void setup() {
   Serial.begin(9600);
-
+  
+  mrf.reset();
+  mrf.init();
+  
   mrf.set_pan(0xcafe);
   // This is _our_ address
   mrf.address16_write(0x6001); 
+  
+  // uncomment if you want to enable PA/LNA external control
+  //mrf.set_palna(true);
 
-  attachInterrupt(0, interrupt_routine, CHANGE);   // interrupt 0 equivalent to pin 2 on ATMEGA8
-
+  attachInterrupt(0, interrupt_routine, CHANGE); // interrupt 0 equivalent to pin 2(INT0) on ATmega8/168/328
   last_time = millis();
   interrupts();
 }
@@ -37,12 +42,6 @@ void interrupt_routine() {
 
 void loop() {
     mrf.check_flags(&handle_rx, &handle_tx);
-    unsigned long current_time = millis();
-    if (current_time - last_time > tx_interval) {
-        last_time = current_time;
-        Serial.println("txxxing...");
-        mrf.send16(0x4202, "abcd");
-    }
 }
 
 void handle_rx() {