8 changed files with 31 additions and 780 deletions
@ -1,6 +0,0 @@
@@ -1,6 +0,0 @@
|
||||
The microchip mrf24j40ma is an 802.15.4 module, with a SPI interface. It's nice and cheap, and it is |
||||
readily usable on a breadboard, unlike xbee modules. More information here: |
||||
http://www.microchip.com/wwwproducts/Devices.aspx?dDocName=en535967 |
||||
|
||||
This library provides a basic interface to send and receive packets using plain 802.15.4. beacon mode |
||||
is not supported. |
@ -1,86 +0,0 @@
@@ -1,86 +0,0 @@
|
||||
/** |
||||
* Example code for using a microchip mrf24j40 module to send and receive |
||||
* packets using plain 802.15.4 |
||||
* Requirements: 3 pins for spi, 3 pins for reset, chip select and interrupt |
||||
* notifications |
||||
* This example file is considered to be in the public domain |
||||
* Originally written by Karl Palsson, karlp@tweak.net.au, March 2011 |
||||
*/ |
||||
#include <SPI.h> |
||||
#include <mrf24j.h> |
||||
|
||||
const int pin_reset = 6; |
||||
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); |
||||
|
||||
long last_time; |
||||
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); |
||||
|
||||
// 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(); |
||||
} |
||||
|
||||
void interrupt_routine() { |
||||
mrf.interrupt_handler(); // mrf24 object 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() { |
||||
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"); |
||||
} |
||||
} |
@ -1,72 +0,0 @@
@@ -1,72 +0,0 @@
|
||||
/** |
||||
* Example code for using a microchip mrf24j40 module to receive only |
||||
* packets using plain 802.15.4 |
||||
* Requirements: 3 pins for spi, 3 pins for reset, chip select and interrupt |
||||
* notifications |
||||
* This example file is considered to be in the public domain |
||||
* Originally written by Karl Palsson, karlp@tweak.net.au, March 2011 |
||||
*/ |
||||
#include <SPI.h> |
||||
#include <mrf24j.h> |
||||
|
||||
const int pin_reset = 6; |
||||
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); |
||||
|
||||
// uncomment if you want to receive any packet on this channel |
||||
//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(INT0) on ATmega8/168/328 |
||||
interrupts(); |
||||
} |
||||
|
||||
void interrupt_routine() { |
||||
mrf.interrupt_handler(); // mrf24 object interrupt routine |
||||
} |
||||
|
||||
void loop() { |
||||
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 |
||||
} |
@ -1,57 +0,0 @@
@@ -1,57 +0,0 @@
|
||||
/** |
||||
* Example code for using a microchip mrf24j40 module to send simple packets |
||||
* |
||||
* Requirements: 3 pins for spi, 3 pins for reset, chip select and interrupt |
||||
* notifications |
||||
* This example file is considered to be in the public domain |
||||
* Originally written by Karl Palsson, karlp@tweak.net.au, March 2011 |
||||
*/ |
||||
#include <SPI.h> |
||||
#include <mrf24j.h> |
||||
|
||||
const int pin_reset = 6; |
||||
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); |
||||
|
||||
long last_time; |
||||
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(INT0) on ATmega8/168/328 |
||||
last_time = millis(); |
||||
interrupts(); |
||||
} |
||||
|
||||
void interrupt_routine() { |
||||
mrf.interrupt_handler(); // mrf24 object interrupt routine |
||||
} |
||||
|
||||
void loop() { |
||||
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"); |
||||
} |
||||
} |
@ -0,0 +1,28 @@
@@ -0,0 +1,28 @@
|
||||
MCU?=atmega328p |
||||
F_CPU=8000000 |
||||
PROG?=arduino |
||||
PORT?=COM5 |
||||
CC=avr-g++ |
||||
OBJCOPY=avr-objcopy |
||||
CFLAGS=-Wall -g -mmcu=${MCU} -DF_CPU=${F_CPU} -I. |
||||
TARGET=main |
||||
SRCS= src/*.cpp $(wildcard lib/*/src/*.cpp) |
||||
|
||||
all: build flash |
||||
|
||||
build: |
||||
${CC} ${CFLAGS} -o bin/${MODE}.bin ${SRCS} test/${MODE}/main.cpp -O2 |
||||
${CC} ${CFLAGS} -o bin/${MODE}.elf ${SRCS} test/${MODE}/main.cpp -O2 |
||||
${OBJCOPY} -j .text -j .data -O ihex bin/${MODE}.bin bin/${MODE}.hex |
||||
|
||||
flash: |
||||
avrdude -p ${MCU} -c ${PROG} -P ${PORT} ${BAUD} -U flash:w:bin/${MODE}.hex |
||||
|
||||
clean: |
||||
rm -f bin/* |
||||
|
||||
term: |
||||
python3 lib/usart/term.py |
||||
|
||||
avarice: |
||||
avarice --program --file bin/main.elf --part atmega32 --dragon :4242 |
@ -1,325 +0,0 @@
@@ -1,325 +0,0 @@
|
||||
/**
|
||||
* mrf24j.cpp, Karl Palsson, 2011, karlp@tweak.net.au |
||||
* modified bsd license / apache license |
||||
*/ |
||||
|
||||
#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; |
||||
_pin_int = pin_interrupt; |
||||
|
||||
pinMode(_pin_reset, OUTPUT); |
||||
pinMode(_pin_cs, OUTPUT); |
||||
pinMode(_pin_int, INPUT); |
||||
|
||||
SPI.setBitOrder(MSBFIRST) ; |
||||
SPI.setDataMode(SPI_MODE0); |
||||
SPI.begin(); |
||||
} |
||||
|
||||
void Mrf24j::reset(void) { |
||||
digitalWrite(_pin_reset, LOW); |
||||
delay(10); // just my gut
|
||||
digitalWrite(_pin_reset, HIGH); |
||||
delay(20); // from manual
|
||||
} |
||||
|
||||
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(0x00); |
||||
digitalWrite(_pin_cs, HIGH); |
||||
return ret; |
||||
} |
||||
|
||||
byte Mrf24j::read_long(word address) { |
||||
digitalWrite(_pin_cs, LOW); |
||||
byte ahigh = address >> 3; |
||||
byte alow = address << 5; |
||||
SPI.transfer(0x80 | ahigh); // high bit for long
|
||||
SPI.transfer(alow); |
||||
byte ret = SPI.transfer(0); |
||||
digitalWrite(_pin_cs, HIGH); |
||||
return ret; |
||||
} |
||||
|
||||
|
||||
void Mrf24j::write_short(byte address, byte data) { |
||||
digitalWrite(_pin_cs, LOW); |
||||
// 0 for top short address, 1 bottom for write
|
||||
SPI.transfer((address<<1 & 0b01111110) | 0x01); |
||||
SPI.transfer(data); |
||||
digitalWrite(_pin_cs, HIGH); |
||||
} |
||||
|
||||
void Mrf24j::write_long(word address, byte data) { |
||||
digitalWrite(_pin_cs, LOW); |
||||
byte ahigh = address >> 3; |
||||
byte alow = address << 5; |
||||
SPI.transfer(0x80 | ahigh); // high bit for long
|
||||
SPI.transfer(alow | 0x10); // last bit for write
|
||||
SPI.transfer(data); |
||||
digitalWrite(_pin_cs, HIGH); |
||||
} |
||||
|
||||
word Mrf24j::get_pan(void) { |
||||
byte panh = read_short(MRF_PANIDH); |
||||
return panh << 8 | read_short(MRF_PANIDL); |
||||
} |
||||
|
||||
void Mrf24j::set_pan(word panid) { |
||||
write_short(MRF_PANIDH, panid >> 8); |
||||
write_short(MRF_PANIDL, panid & 0xff); |
||||
} |
||||
|
||||
void Mrf24j::address16_write(word address16) { |
||||
write_short(MRF_SADRH, address16 >> 8); |
||||
write_short(MRF_SADRL, address16 & 0xff); |
||||
} |
||||
|
||||
word Mrf24j::address16_read(void) { |
||||
byte a16h = read_short(MRF_SADRH); |
||||
return a16h << 8 | read_short(MRF_SADRL); |
||||
} |
||||
|
||||
/**
|
||||
* Simple send 16, with acks, not much of anything.. assumes src16 and local pan only. |
||||
* @param 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++, 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
|
||||
// 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
|
||||
|
||||
word panid = get_pan(); |
||||
|
||||
write_long(i++, panid & 0xff); // dest panid
|
||||
write_long(i++, panid >> 8); |
||||
write_long(i++, dest16 & 0xff); // dest16 low
|
||||
write_long(i++, dest16 >> 8); // dest16 high
|
||||
|
||||
word src16 = address16_read(); |
||||
write_long(i++, src16 & 0xff); // src16 low
|
||||
write_long(i++, src16 >> 8); // src16 high
|
||||
|
||||
// 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]); |
||||
} |
||||
// ack on, and go!
|
||||
write_short(MRF_TXNCON, (1<<MRF_TXNACKREQ | 1<<MRF_TXNTRIG)); |
||||
} |
||||
|
||||
void Mrf24j::set_interrupts(void) { |
||||
// interrupts for rx and tx normal complete
|
||||
write_short(MRF_INTCON, 0b11110110); |
||||
} |
||||
|
||||
/** use the 802.15.4 channel numbers..
|
||||
*/ |
||||
void Mrf24j::set_channel(byte channel) { |
||||
write_long(MRF_RFCON0, (((channel - 11) << 4) | 0x03)); |
||||
} |
||||
|
||||
void Mrf24j::init(void) { |
||||
/*
|
||||
// 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.
|
||||
|
||||
write_long(MRF_RFCON0, 0x03); // – Initialize RFOPT = 0x03.
|
||||
write_long(MRF_RFCON1, 0x01); // – Initialize VCOOPT = 0x02.
|
||||
write_long(MRF_RFCON2, 0x80); // – Enable PLL (PLLEN = 1).
|
||||
write_long(MRF_RFCON6, 0x90); // – Initialize TXFIL = 1 and 20MRECVR = 1.
|
||||
write_long(MRF_RFCON7, 0x80); // – Initialize SLPCLKSEL = 0x2 (100 kHz Internal oscillator).
|
||||
write_long(MRF_RFCON8, 0x10); // – Initialize RFVCO = 1.
|
||||
write_long(MRF_SLPCON1, 0x21); // – Initialize CLKOUTEN = 1 and SLPCLKDIV = 0x01.
|
||||
|
||||
// Configuration for nonbeacon-enabled devices (see Section 3.8 “Beacon-Enabled and
|
||||
// Nonbeacon-Enabled Networks”):
|
||||
write_short(MRF_BBREG2, 0x80); // Set CCA mode to ED
|
||||
write_short(MRF_CCAEDTH, 0x60); // – Set CCA ED threshold.
|
||||
write_short(MRF_BBREG6, 0x40); // – Set appended RSSI value to RXFIFO.
|
||||
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_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); |
||||
} else { |
||||
write_short(MRF_RXMCR, 0x00); |
||||
} |
||||
} |
||||
|
||||
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); |
||||
} |
||||
|
||||
void Mrf24j::rx_disable(void) { |
||||
write_short(MRF_BBREG1, 0x04); // RXDECINV - disable receiver
|
||||
} |
||||
|
||||
void Mrf24j::rx_enable(void) { |
||||
write_short(MRF_BBREG1, 0x00); // RXDECINV - enable receiver
|
||||
} |
@ -1,234 +0,0 @@
@@ -1,234 +0,0 @@
|
||||
/*
|
||||
* File: mrf24j.h |
||||
* copyright Karl Palsson, karlp@tweak.net.au, 2011 |
||||
* modified BSD License / apache license |
||||
*/ |
||||
|
||||
#ifndef LIB_MRF24J_H |
||||
#define LIB_MRF24J_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" |
||||
|
||||
|
||||
#define MRF_RXMCR 0x00 |
||||
#define MRF_PANIDL 0x01 |
||||
#define MRF_PANIDH 0x02 |
||||
#define MRF_SADRL 0x03 |
||||
#define MRF_SADRH 0x04 |
||||
#define MRF_EADR0 0x05 |
||||
#define MRF_EADR1 0x06 |
||||
#define MRF_EADR2 0x07 |
||||
#define MRF_EADR3 0x08 |
||||
#define MRF_EADR4 0x09 |
||||
#define MRF_EADR5 0x0A |
||||
#define MRF_EADR6 0x0B |
||||
#define MRF_EADR7 0x0C |
||||
#define MRF_RXFLUSH 0x0D |
||||
//#define MRF_Reserved 0x0E
|
||||
//#define MRF_Reserved 0x0F
|
||||
#define MRF_ORDER 0x10 |
||||
#define MRF_TXMCR 0x11 |
||||
#define MRF_ACKTMOUT 0x12 |
||||
#define MRF_ESLOTG1 0x13 |
||||
#define MRF_SYMTICKL 0x14 |
||||
#define MRF_SYMTICKH 0x15 |
||||
#define MRF_PACON0 0x16 |
||||
#define MRF_PACON1 0x17 |
||||
#define MRF_PACON2 0x18 |
||||
//#define MRF_Reserved 0x19
|
||||
#define MRF_TXBCON0 0x1A |
||||
|
||||
// TXNCON: TRANSMIT NORMAL FIFO CONTROL REGISTER (ADDRESS: 0x1B)
|
||||
#define MRF_TXNCON 0x1B |
||||
#define MRF_TXNTRIG 0 |
||||
#define MRF_TXNSECEN 1 |
||||
#define MRF_TXNACKREQ 2 |
||||
#define MRF_INDIRECT 3 |
||||
#define MRF_FPSTAT 4 |
||||
|
||||
#define MRF_TXG1CON 0x1C |
||||
#define MRF_TXG2CON 0x1D |
||||
#define MRF_ESLOTG23 0x1E |
||||
#define MRF_ESLOTG45 0x1F |
||||
#define MRF_ESLOTG67 0x20 |
||||
#define MRF_TXPEND 0x21 |
||||
#define MRF_WAKECON 0x22 |
||||
#define MRF_FRMOFFSET 0x23 |
||||
// TXSTAT: TX MAC STATUS REGISTER (ADDRESS: 0x24)
|
||||
#define MRF_TXSTAT 0x24 |
||||
#define TXNRETRY1 7 |
||||
#define TXNRETRY0 6 |
||||
#define CCAFAIL 5 |
||||
#define TXG2FNT 4 |
||||
#define TXG1FNT 3 |
||||
#define TXG2STAT 2 |
||||
#define TXG1STAT 1 |
||||
#define TXNSTAT 0 |
||||
|
||||
#define MRF_TXBCON1 0x25 |
||||
#define MRF_GATECLK 0x26 |
||||
#define MRF_TXTIME 0x27 |
||||
#define MRF_HSYMTMRL 0x28 |
||||
#define MRF_HSYMTMRH 0x29 |
||||
#define MRF_SOFTRST 0x2A |
||||
//#define MRF_Reserved 0x2B
|
||||
#define MRF_SECCON0 0x2C |
||||
#define MRF_SECCON1 0x2D |
||||
#define MRF_TXSTBL 0x2E |
||||
//#define MRF_Reserved 0x2F
|
||||
#define MRF_RXSR 0x30 |
||||
#define MRF_INTSTAT 0x31 |
||||
#define MRF_INTCON 0x32 |
||||
#define MRF_GPIO 0x33 |
||||
#define MRF_TRISGPIO 0x34 |
||||
#define MRF_SLPACK 0x35 |
||||
#define MRF_RFCTL 0x36 |
||||
#define MRF_SECCR2 0x37 |
||||
#define MRF_BBREG0 0x38 |
||||
#define MRF_BBREG1 0x39 |
||||
#define MRF_BBREG2 0x3A |
||||
#define MRF_BBREG3 0x3B |
||||
#define MRF_BBREG4 0x3C |
||||
//#define MRF_Reserved 0x3D
|
||||
#define MRF_BBREG6 0x3E |
||||
#define MRF_CCAEDTH 0x3F |
||||
|
||||
#define MRF_RFCON0 0x200 |
||||
#define MRF_RFCON1 0x201 |
||||
#define MRF_RFCON2 0x202 |
||||
#define MRF_RFCON3 0x203 |
||||
#define MRF_RFCON5 0x205 |
||||
#define MRF_RFCON6 0x206 |
||||
#define MRF_RFCON7 0x207 |
||||
#define MRF_RFCON8 0x208 |
||||
#define MRF_SLPCAL0 0x209 |
||||
#define MRF_SLPCAL1 0x20A |
||||
#define MRF_SLPCAL2 0x20B |
||||
#define MRF_RSSI 0x210 |
||||
#define MRF_SLPCON0 0x211 |
||||
#define MRF_SLPCON1 0x220 |
||||
#define MRF_WAKETIMEL 0x222 |
||||
#define MRF_WAKETIMEH 0x223 |
||||
#define MRF_REMCNTL 0x224 |
||||
#define MRF_REMCNTH 0x225 |
||||
#define MRF_MAINCNT0 0x226 |
||||
#define MRF_MAINCNT1 0x227 |
||||
#define MRF_MAINCNT2 0x228 |
||||
#define MRF_MAINCNT3 0x229 |
||||
#define MRF_TESTMODE 0x22F |
||||
#define MRF_ASSOEADR1 0x231 |
||||
#define MRF_ASSOEADR2 0x232 |
||||
#define MRF_ASSOEADR3 0x233 |
||||
#define MRF_ASSOEADR4 0x234 |
||||
#define MRF_ASSOEADR5 0x235 |
||||
#define MRF_ASSOEADR6 0x236 |
||||
#define MRF_ASSOEADR7 0x237 |
||||
#define MRF_ASSOSADR0 0x238 |
||||
#define MRF_ASSOSADR1 0x239 |
||||
#define MRF_UPNONCE0 0x240 |
||||
#define MRF_UPNONCE1 0x241 |
||||
#define MRF_UPNONCE2 0x242 |
||||
#define MRF_UPNONCE3 0x243 |
||||
#define MRF_UPNONCE4 0x244 |
||||
#define MRF_UPNONCE5 0x245 |
||||
#define MRF_UPNONCE6 0x246 |
||||
#define MRF_UPNONCE7 0x247 |
||||
#define MRF_UPNONCE8 0x248 |
||||
#define MRF_UPNONCE9 0x249 |
||||
#define MRF_UPNONCE10 0x24A |
||||
#define MRF_UPNONCE11 0x24B |
||||
#define MRF_UPNONCE12 0x24C |
||||
|
||||
#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); |
||||
|
||||
byte read_short(byte address); |
||||
byte read_long(word address); |
||||
|
||||
void write_short(byte address, byte data); |
||||
void write_long(word address, byte data); |
||||
|
||||
word get_pan(void); |
||||
void set_pan(word panid); |
||||
|
||||
void address16_write(word address16); |
||||
word address16_read(void); |
||||
|
||||
void set_interrupts(void); |
||||
|
||||
void set_promiscuous(boolean enabled); |
||||
|
||||
/**
|
||||
* Set the channel, using 802.15.4 channel numbers (11..26) |
||||
*/ |
||||
void set_channel(byte channel); |
||||
|
||||
void rx_enable(void); |
||||
void rx_disable(void); |
||||
|
||||
/** If you want to throw away rx data */ |
||||
void rx_flush(void); |
||||
|
||||
rx_info_t * get_rxinfo(void); |
||||
|
||||
tx_info_t * get_txinfo(void); |
||||
|
||||
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