From fac2f3f530eed4e509e65103a7d09116c3944ead Mon Sep 17 00:00:00 2001 From: Pkarc 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 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 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 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<> 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 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 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 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 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 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 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 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 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 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 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 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 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() {