commit 19edd271b94d853d39aee70ab67d6e5c464433ec Author: Karl Palsson <github@tweak.net.au> Date: Sun Mar 13 17:33:58 2011 +0000 Initial basic version of my arduino mrf24j40 library diff --git a/mrf24j.cpp b/mrf24j.cpp new file mode 100644 index 0000000..27964be --- /dev/null +++ b/mrf24j.cpp @@ -0,0 +1,171 @@ +/** + * mrf24j.cpp, Karl Palsson, 2011, karlp@tweak.net.au + * modifed bsd license / apache license + */ + +#include "WProgram.h" +#include "mrf24j.h" + + + +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.begin(); + // arguably should not be here... + mrf_reset(); + mrf_init(); +} + +void Mrf24j::mrf_reset(void) { + digitalWrite(_pin_reset, LOW); + delay(10); // just my gut + digitalWrite(_pin_reset, HIGH); + delay(20); // from manual +} + +byte Mrf24j::mrf_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); + digitalWrite(_pin_cs, HIGH); + return ret; +} + +byte Mrf24j::mrf_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::mrf_write_short(byte address, byte data) { + digitalWrite(_pin_cs, LOW); + // 0 for top address, 1 bottom for write + SPI.transfer((address<<1 & 0b01111110) | 0x01); + SPI.transfer(data); + digitalWrite(_pin_cs, HIGH); +} + +void Mrf24j::mrf_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::mrf_pan_read(void) { + byte panh = mrf_read_short(MRF_PANIDH); + return panh << 8 | mrf_read_short(MRF_PANIDL); +} + +void Mrf24j::mrf_pan_write(word panid) { + mrf_write_short(MRF_PANIDH, panid >> 8); + mrf_write_short(MRF_PANIDL, panid & 0xff); +} + +void Mrf24j::mrf_address16_write(word address16) { + mrf_write_short(MRF_SADRH, address16 >> 8); + mrf_write_short(MRF_SADRL, address16 & 0xff); +} + +word Mrf24j::mrf_address16_read(void) { + byte a16h = mrf_read_short(MRF_SADRH); + return a16h << 8 | mrf_read_short(MRF_SADRL); +} + +/** + * Simple send 16, with acks, not much of anything.. assumes src16 and local pan only. + * @param data + */ +void Mrf24j::mrf_send16(word dest16, byte len, char * data) { + + int i = 0; + mrf_write_long(i++, 9); // header length + mrf_write_long(i++, 9+2+len); //+2 is because module seems to ignore 2 bytes after the header?! + +// 0 | pan compression | ack | no security | no data pending | data frame[3 bits] + mrf_write_long(i++, 0b01100001); // first byte of Frame Control +// 16 bit source, 802.15.4 (2003), 16 bit dest, + mrf_write_long(i++, 0b10001000); // second byte of frame control + mrf_write_long(i++, 1); // sequence number 1 + + word panid = mrf_pan_read(); + + mrf_write_long(i++, panid & 0xff); // dest panid + mrf_write_long(i++, panid >> 8); + mrf_write_long(i++, dest16 & 0xff); // dest16 low + mrf_write_long(i++, dest16 >> 8); // dest16 high + + word src16 = mrf_address16_read(); + mrf_write_long(i++, src16 & 0xff); // src16 low + mrf_write_long(i++, src16 >> 8); // src16 high + + i+=2; // All testing seems to indicate that the next two bytes are ignored. + for (int q = 0; q < len; q++) { + mrf_write_long(i++, data[q]); + } + // ack on, and go! + mrf_write_short(MRF_TXNCON, (1<<MRF_TXNACKREQ | 1<<MRF_TXNTRIG)); +} + +void Mrf24j::mrf_set_interrupts(void) { + // interrupts for rx and tx normal complete + mrf_write_short(MRF_INTCON, 0b11110110); +} + +// Set the channel to 12, 2.41Ghz, xbee channel 0xC +void Mrf24j::mrf_set_channel(void) { + mrf_write_long(MRF_RFCON0, 0x13); +} + +void Mrf24j::mrf_init(void) { +/* + // Seems a bit ridiculous when I use reset pin anyway + mrf_write_short(MRF_SOFTRST, 0x7); // from manual + while (mrf_read_short(MRF_SOFTRST) & 0x7 != 0) { + ; // wait for soft reset to finish + } +*/ + mrf_write_short(MRF_PACON2, 0x98); // – Initialize FIFOEN = 1 and TXONTS = 0x6. + mrf_write_short(MRF_TXSTBL, 0x95); // – Initialize RFSTBL = 0x9. + + mrf_write_long(MRF_RFCON0, 0x03); // – Initialize RFOPT = 0x03. + mrf_write_long(MRF_RFCON1, 0x01); // – Initialize VCOOPT = 0x02. + mrf_write_long(MRF_RFCON2, 0x80); // – Enable PLL (PLLEN = 1). + mrf_write_long(MRF_RFCON6, 0x90); // – Initialize TXFIL = 1 and 20MRECVR = 1. + mrf_write_long(MRF_RFCON7, 0x80); // – Initialize SLPCLKSEL = 0x2 (100 kHz Internal oscillator). + mrf_write_long(MRF_RFCON8, 0x10); // – Initialize RFVCO = 1. + mrf_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”): + mrf_write_short(MRF_BBREG2, 0x80); // Set CCA mode to ED + mrf_write_short(MRF_CCAEDTH, 0x60); // – Set CCA ED threshold. + mrf_write_short(MRF_BBREG6, 0x40); // – Set appended RSSI value to RXFIFO. + mrf_set_interrupts(); + mrf_set_channel(); + // max power is by default.. just leave it... + //Set transmitter power - See “REGISTER 2-62: RF CONTROL 3 REGISTER (ADDRESS: 0x203)”. + mrf_write_short(MRF_RFCTL, 0x04); // – Reset RF state machine. + mrf_write_short(MRF_RFCTL, 0x00); // part 2 + delay(1); // delay at least 192usec +} + + + diff --git a/mrf24j.h b/mrf24j.h new file mode 100644 index 0000000..6a5799f --- /dev/null +++ b/mrf24j.h @@ -0,0 +1,184 @@ +/* + * File: mrf24j.h + * copyright Karl Palsson, karlp@tweak.net.au, 2011 + * modified BSD License / apache license + */ + +#ifndef LIB_MRF24J_H +#define LIB_MRF24J_H + +#include "WProgram.h" +#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 + + +class Mrf24j +{ + +public: +Mrf24j(int pin_reset, int pin_chip_select, int pin_interrupt); +void mrf_reset(void); +void mrf_init(void); + +byte mrf_read_short(byte address); +byte mrf_read_long(word address); + +void mrf_write_short(byte address, byte data); +void mrf_write_long(word address, byte data); + +word mrf_pan_read(void); +void mrf_pan_write(word panid); + +void mrf_address16_write(word address16); +word mrf_address16_read(void); + +void mrf_set_interrupts(void); + +// Set the channel to 12, 2.41Ghz, xbee channel 0xC +void mrf_set_channel(void); + +void mrf_send16(word dest16, byte len, char * data); + +private: + int _pin_reset; + int _pin_cs; + int _pin_int; + + +}; + +#endif /* LIB_MRF24J_H */ + +