Merge pull request #1 from pkarc/master
Nice Work! New features of this merge: * Simpler use, more internals hidden from view * Support for MRF24J40MB modules with power amp * Optional support for (broken?) devices with extra FCS bytes (MRF module listening to a series 1 xbee for instance)
This commit is contained in:
commit
445ae63ed6
|
@ -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/168/328
|
||||
const int pin_interrupt = 2; // default interrupt pin on ATmega8/168/328
|
||||
|
||||
Mrf24j mrf(pin_reset, pin_cs, pin_interrupt);
|
||||
|
||||
|
@ -20,75 +20,67 @@ 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);
|
||||
//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);
|
||||
attachInterrupt(0, interrupt_routine, CHANGE); // interrupt 0 equivalent to pin 2(INT0) on ATmega8/168/328
|
||||
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");
|
||||
|
||||
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]);
|
||||
}
|
||||
|
||||
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");
|
||||
}
|
||||
}
|
|
@ -10,62 +10,63 @@
|
|||
#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/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);
|
||||
attachInterrupt(0, interrupt_routine, CHANGE); // interrupt 0 equivalent to pin 2(INT0) on ATmega8/168/328
|
||||
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(); // mrf24 object interrupt routine
|
||||
}
|
||||
|
||||
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");
|
||||
|
||||
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]);
|
||||
}
|
||||
|
||||
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
|
||||
}
|
|
@ -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/168/328
|
||||
const int pin_interrupt = 2; // default interrupt pin on ATmega8/168/328
|
||||
|
||||
Mrf24j mrf(pin_reset, pin_cs, pin_interrupt);
|
||||
|
||||
|
@ -20,35 +20,38 @@ 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);
|
||||
|
||||
attachInterrupt(0, interrupt_routine, CHANGE); // interrupt 0 equivalent to pin 2(INT0) on ATmega8/168/328
|
||||
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;
|
||||
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.check_flags(&handle_rx, &handle_tx);
|
||||
}
|
||||
|
||||
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");
|
||||
}
|
||||
}
|
172
mrf24j.cpp
172
mrf24j.cpp
|
@ -1,13 +1,34 @@
|
|||
/**
|
||||
* mrf24j.cpp, Karl Palsson, 2011, karlp@tweak.net.au
|
||||
* modifed bsd license / apache license
|
||||
* modified bsd license / apache license
|
||||
*/
|
||||
|
||||
#include "WProgram.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
|
||||
// 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;
|
||||
|
||||
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 +38,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 +54,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 +73,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 +113,17 @@ 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++, 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]
|
||||
// 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 +138,9 @@ 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.
|
||||
// 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]);
|
||||
}
|
||||
|
@ -136,13 +160,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.
|
||||
|
||||
|
@ -162,12 +186,81 @@ 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)”.
|
||||
// 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
|
||||
}
|
||||
|
||||
/**
|
||||
* 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();
|
||||
// read start of rxfifo for, has 2 bytes more added by FCS. frame_length = m + n + 2
|
||||
uint8_t frame_length = read_long(0x300);
|
||||
|
||||
// buffer all bytes in PHY Payload
|
||||
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;
|
||||
// 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;
|
||||
// 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();
|
||||
}
|
||||
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 +269,49 @@ 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::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);
|
||||
}
|
||||
|
|
102
mrf24j.h
102
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,88 @@
|
|||
#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 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);
|
||||
|
||||
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 */
|
||||
|
||||
|
||||
|
|
Loading…
Reference in New Issue