diff --git a/drivers/wireless/ieee802154/mrf24j40/mrf24j40.c b/drivers/wireless/ieee802154/mrf24j40/mrf24j40.c index 94e5b7e2df4..17f5c6186d9 100644 --- a/drivers/wireless/ieee802154/mrf24j40/mrf24j40.c +++ b/drivers/wireless/ieee802154/mrf24j40/mrf24j40.c @@ -50,7 +50,6 @@ #include #include -#include #include #include #include @@ -64,61 +63,78 @@ #include "mrf24j40.h" #include "mrf24j40_reg.h" #include "mrf24j40_radif.h" +#include "mrf24j40_getset.h" #include "mrf24j40_regops.h" /**************************************************************************** * Pre-processor Definitions ****************************************************************************/ -/* Clock configuration macros */ - -#define MRF24J40_SLPCLKPER_100KHZ ((1000 * 1000 * 1000)/100000) /* 10ns */ -#define MRF24J40_SLPCLKPER_32KHZ ((1000 * 1000 * 1000)/32000) /* 31.25ns */ - -#define MRF24J40_BEACONINTERVAL_NSEC(beaconorder) \ - (IEEE802154_BASE_SUPERFRAME_DURATION * (1 << beaconorder) * (16 *1000)) - -/* For now I am just setting the REMCNT to the maximum while staying in multiples - * of 10000 (100khz period) */ - -#define MRF24J40_REMCNT 60000 -#define MRF24J40_REMCNT_NSEC (MRF24J40_REMCNT * 50) - -#define MRF24J40_MAINCNT(bo, clkper) \ - ((MRF24J40_BEACONINTERVAL_NSEC(bo) - MRF24J40_REMCNT_NSEC) / \ - clkper) - /**************************************************************************** - * Internal Functions + * Private Function Prototypes ****************************************************************************/ -void mrf24j40_mactimer(FAR struct mrf24j40_radio_s *dev, int numsymbols) +#if 0 +static int mrf24j40_energydetect(FAR struct mrf24j40_radio_s *dev, + FAR uint8_t *energy); +#endif + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: mrf24j40_energydetect + * + * Description: + * Measure the RSSI level for the current channel. + * + ****************************************************************************/ + +#if 0 +static int mrf24j40_energydetect(FAR struct mrf24j40_radio_s *dev, + FAR uint8_t *energy) { - uint16_t nhalfsym; uint8_t reg; - nhalfsym = (numsymbols << 1); + /* Manually enable the LNA*/ - /* Disable the interrupt, clear the timer count */ + mrf24j40_setpamode(dev, MRF24J40_PA_ED); - reg = mrf24j40_getreg(dev->spi, MRF24J40_INTCON); - reg |= MRF24J40_INTCON_HSYMTMRIE; - mrf24j40_setreg(dev->spi, MRF24J40_INTCON, reg); + /* Set RSSI average duration to 8 symbols */ - mrf24j40_setreg(dev->spi, MRF24J40_HSYMTMRL, 0x00); - mrf24j40_setreg(dev->spi, MRF24J40_HSYMTMRH, 0x00); + reg = mrf24j40_getreg(dev->spi, MRF24J40_TXBCON1); + reg |= 0x30; + mrf24j40_setreg(dev->spi, MRF24J40_TXBCON1, reg); - reg &= ~MRF24J40_INTCON_HSYMTMRIE; - mrf24j40_setreg(dev->spi, MRF24J40_INTCON, reg); + /* 1. Set RSSIMODE1 0x3E<7> – Initiate RSSI calculation. */ - /* Set the timer count and enable interrupts */ + mrf24j40_setreg(dev->spi, MRF24J40_BBREG6, 0x80); - reg = (nhalfsym & 0xFF); - mrf24j40_setreg(dev->spi, MRF24J40_HSYMTMRL, reg); + /* 2. Wait until RSSIRDY 0x3E<0> is set to ‘1’ – RSSI calculation is + * complete. + */ - reg = (nhalfsym >> 8) & 0xFF; - mrf24j40_setreg(dev->spi, MRF24J40_HSYMTMRH, reg); + while(!(mrf24j40_getreg(dev->spi, MRF24J40_BBREG6) & 0x01)); + + /* 3. Read RSSI 0x210<7:0> – The RSSI register contains the averaged RSSI + * received power level for 8 symbol periods. + */ + + *energy = mrf24j40_getreg(dev->spi, MRF24J40_RSSI); + mrf24j40_setreg(dev->spi, MRF24J40_BBREG6, 0x40); + + /* Back to automatic control */ + + mrf24j40_setpamode(dev, MRF24J40_PA_AUTO); + + return OK; } +#endif + +/**************************************************************************** + * Public Functions + ****************************************************************************/ /**************************************************************************** * Function: mrf24j40_dopoll_csma @@ -230,179 +246,6 @@ void mrf24j40_dopoll_gts(FAR void *arg) sem_post(&dev->exclsem); } -/**************************************************************************** - * Name: mrf24j40_setorder - * - * Description: - * Configures the timers and sets the ORDER register - ****************************************************************************/ - -void mrf24j40_setorder(FAR struct mrf24j40_radio_s *dev, uint8_t bo, uint8_t so) -{ - uint32_t maincnt = 0; - uint32_t slpcal = 0; - - wlinfo("bo: %d, so: %d\n", bo, so); - - /* Calibrate the Sleep Clock (SLPCLK) frequency. Refer to Section 3.15.1.2 - * “Sleep Clock Calibration”. - */ - - /* If the Sleep Clock Selection, SLPCLKSEL (0x207<7:6), is the internal - * oscillator (100 kHz), set SLPCLKDIV to a minimum value of 0x01. - */ - - mrf24j40_setreg(dev->spi, MRF24J40_SLPCON1, 0x01); - - /* Select the source of SLPCLK (internal 100kHz) */ - - mrf24j40_setreg(dev->spi, MRF24J40_RFCON7, MRF24J40_RFCON7_SEL_100KHZ); - - /* Begin calibration by setting the SLPCALEN bit (SLPCAL2 0x20B<4>) to - * ‘1’. Sixteen samples of the SLPCLK are counted and stored in the - * SLPCAL register. No need to mask, this is the only writable bit - */ - - mrf24j40_setreg(dev->spi, MRF24J40_SLPCAL2, MRF24J40_SLPCAL2_SLPCALEN); - - /* Calibration is complete when the SLPCALRDY bit (SLPCAL2 0x20B<7>) is - * set to ‘1’. - */ - - while (!(mrf24j40_getreg(dev->spi, MRF24J40_SLPCAL2) & - MRF24J40_SLPCAL2_SLPCALRDY)) - { - usleep(1); - } - - slpcal = mrf24j40_getreg(dev->spi, MRF24J40_SLPCAL0); - slpcal |= (mrf24j40_getreg(dev->spi, MRF24J40_SLPCAL1) << 8); - slpcal |= ((mrf24j40_getreg(dev->spi, MRF24J40_SLPCAL2) << 16) & 0x0F); - - /* Set WAKECNT (SLPACK 0x35<6:0>) value = 0xC8 to set the main oscillator - * (20 MHz) start-up timer value. - */ - - mrf24j40_setreg(dev->spi, MRF24J40_SLPACK, 0xC8); - - /* Set WAKETIME to recommended value for 100kHz SLPCLK Source */ - - mrf24j40_setreg(dev->spi, MRF24J40_WAKETIMEL, 0xD2); - mrf24j40_setreg(dev->spi, MRF24J40_WAKETIMEH, 0x00); - - /* Program the Beacon Interval into the Main Counter, MAINCNT (0x229<1:0>, - * 0x228, 0x227, 0x226), and Remain Counter, REMCNT (0x225, 0x224), - * according to BO and SO values. Refer to Section 3.15.1.3 “Sleep Mode - * Counters” - */ - - mrf24j40_setreg(dev->spi, MRF24J40_REMCNTL, (MRF24J40_REMCNT & 0xFF)); - mrf24j40_setreg(dev->spi, MRF24J40_REMCNTH, ((MRF24J40_REMCNT >> 8) & 0xFF)); - - maincnt = MRF24J40_MAINCNT(bo, (slpcal * 50 / 16)); - - mrf24j40_setreg(dev->spi, MRF24J40_MAINCNT0, (maincnt & 0xFF)); - mrf24j40_setreg(dev->spi, MRF24J40_MAINCNT1, ((maincnt >> 8) & 0xFF)); - mrf24j40_setreg(dev->spi, MRF24J40_MAINCNT2, ((maincnt >> 16) & 0xFF)); - mrf24j40_setreg(dev->spi, MRF24J40_MAINCNT3, ((maincnt >> 24) & 0x03)); - - /* Configure the BO (ORDER 0x10<7:4>) and SO (ORDER 0x10<3:0>) values. - * After configuring BO and SO, the beacon frame will be sent immediately. - */ - - mrf24j40_setreg(dev->spi, MRF24J40_ORDER, ((bo << 4) & 0xF0) | (so & 0x0F)); -} - -/**************************************************************************** - * Name: mrf24j40_pacontrol - * - * Description: - * Control the external LNA/PA on the MRF24J40MB/MC/MD/ME modules - * GPIO 1: PA enable - * GPIO 2: LNA enable - * GPIO 3: PA power enable (not required on MB) - ****************************************************************************/ - -int mrf24j40_pacontrol(FAR struct mrf24j40_radio_s *dev, int mode) -{ - if (!dev->paenabled) - { - return OK; - } - - if (mode == MRF24J40_PA_AUTO) - { - mrf24j40_setreg(dev->spi, MRF24J40_TRISGPIO, 0x08); - mrf24j40_setreg(dev->spi, MRF24J40_GPIO , 0x08); - mrf24j40_setreg(dev->spi, MRF24J40_TESTMODE, 0x0F); - } - else if (mode == MRF24J40_PA_ED) - { - mrf24j40_setreg(dev->spi, MRF24J40_TESTMODE, 0x08); - mrf24j40_setreg(dev->spi, MRF24J40_TRISGPIO, 0x0F); - mrf24j40_setreg(dev->spi, MRF24J40_GPIO , 0x0C); - } - else if (mode == MRF24J40_PA_SLEEP) - { - mrf24j40_setreg(dev->spi, MRF24J40_TESTMODE, 0x08); - mrf24j40_setreg(dev->spi, MRF24J40_TRISGPIO, 0x0F); - mrf24j40_setreg(dev->spi, MRF24J40_GPIO , 0x00); - } - else - { - return -EINVAL; - } - - mrf24j40_resetrfsm(dev); - return OK; -} - -/**************************************************************************** - * Name: mrf24j40_energydetect - * - * Description: - * Measure the RSSI level for the current channel. - * - ****************************************************************************/ - -int mrf24j40_energydetect(FAR struct mrf24j40_radio_s *dev, FAR uint8_t *energy) -{ - uint8_t reg; - - /* Manually enable the LNA*/ - - mrf24j40_pacontrol(dev, MRF24J40_PA_ED); - - /* Set RSSI average duration to 8 symbols */ - - reg = mrf24j40_getreg(dev->spi, MRF24J40_TXBCON1); - reg |= 0x30; - mrf24j40_setreg(dev->spi, MRF24J40_TXBCON1, reg); - - /* 1. Set RSSIMODE1 0x3E<7> – Initiate RSSI calculation. */ - - mrf24j40_setreg(dev->spi, MRF24J40_BBREG6, 0x80); - - /* 2. Wait until RSSIRDY 0x3E<0> is set to ‘1’ – RSSI calculation is - * complete. - */ - - while(!(mrf24j40_getreg(dev->spi, MRF24J40_BBREG6) & 0x01)); - - /* 3. Read RSSI 0x210<7:0> – The RSSI register contains the averaged RSSI - * received power level for 8 symbol periods. - */ - - *energy = mrf24j40_getreg(dev->spi, MRF24J40_RSSI); - mrf24j40_setreg(dev->spi, MRF24J40_BBREG6, 0x40); - - /* Back to automatic control */ - - mrf24j40_pacontrol(dev, MRF24J40_PA_AUTO); - - return OK; -} - /**************************************************************************** * Name: mrf24j40_norm_setup * @@ -569,77 +412,7 @@ void mrf24j40_setup_fifo(FAR struct mrf24j40_radio_s *dev, FAR const uint8_t *bu } } -/**************************************************************************** - * Name: mrf24j40_rxenable - * - * Description: - * Enable/Disable receiver. - * - ****************************************************************************/ -int mrf24j40_rxenable(FAR struct ieee802154_radio_s *radio, bool enable) -{ - FAR struct mrf24j40_radio_s *dev = (FAR struct mrf24j40_radio_s *)radio; - uint8_t reg; - - dev->rxenabled = enable; - - - if (enable) - { - /* Disable packet reception. See pg. 109 of datasheet */ - - mrf24j40_setreg(dev->spi, MRF24J40_BBREG1, MRF24J40_BBREG1_RXDECINV); - - /* Enable rx int */ - - reg = mrf24j40_getreg(dev->spi, MRF24J40_INTCON); - reg &= ~MRF24J40_INTCON_RXIE; - mrf24j40_setreg(dev->spi, MRF24J40_INTCON, reg); - - /* Purge the RX buffer */ - - reg = mrf24j40_getreg(dev->spi, MRF24J40_RXFLUSH); - reg |= MRF24J40_RXFLUSH_RXFLUSH; - mrf24j40_setreg(dev->spi, MRF24J40_RXFLUSH, reg); - - /* Re-enable packet reception. See pg. 109 of datasheet */ - - mrf24j40_setreg(dev->spi, MRF24J40_BBREG1, 0); - } - else - { - /* Disable rx int */ - - reg = mrf24j40_getreg(dev->spi, MRF24J40_INTCON); - reg |= MRF24J40_INTCON_RXIE; - mrf24j40_setreg(dev->spi, MRF24J40_INTCON, reg); - } - - return OK; -} - -/**************************************************************************** - * Name: mrf24j40_resetrfsm - * - * Description: - * Reset the RF state machine. Required at boot, after channel change, - * and probably after PA settings. - * - ****************************************************************************/ - -void mrf24j40_resetrfsm(FAR struct mrf24j40_radio_s *dev) -{ - uint8_t reg; - - reg = mrf24j40_getreg(dev->spi, MRF24J40_RFCTL); - reg |= 0x04; - mrf24j40_setreg(dev->spi, MRF24J40_RFCTL, reg); - - reg &= ~0x04; - mrf24j40_setreg(dev->spi, MRF24J40_RFCTL, reg); - up_udelay(200); -} /**************************************************************************** * Public Functions diff --git a/drivers/wireless/ieee802154/mrf24j40/mrf24j40.h b/drivers/wireless/ieee802154/mrf24j40/mrf24j40.h index 1a3c15da096..bbfca37f4f6 100644 --- a/drivers/wireless/ieee802154/mrf24j40/mrf24j40.h +++ b/drivers/wireless/ieee802154/mrf24j40/mrf24j40.h @@ -52,7 +52,9 @@ #include #include -/* NuttX implementation defines **********************************************/ +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ #define MRF24J40_GTS_SLOTS 2 @@ -87,6 +89,24 @@ #define MRF24J40_SYMBOL_DURATION_PS 16000000 +/* Clock configuration macros */ + +#define MRF24J40_SLPCLKPER_100KHZ ((1000 * 1000 * 1000)/100000) /* 10ns */ +#define MRF24J40_SLPCLKPER_32KHZ ((1000 * 1000 * 1000)/32000) /* 31.25ns */ + +#define MRF24J40_BEACONINTERVAL_NSEC(beaconorder) \ + (IEEE802154_BASE_SUPERFRAME_DURATION * (1 << beaconorder) * (16 *1000)) + +/* For now I am just setting the REMCNT to the maximum while staying in multiples + * of 10000 (100khz period) */ + +#define MRF24J40_REMCNT 60000 +#define MRF24J40_REMCNT_NSEC (MRF24J40_REMCNT * 50) + +#define MRF24J40_MAINCNT(bo, clkper) \ + ((MRF24J40_BEACONINTERVAL_NSEC(bo) - MRF24J40_REMCNT_NSEC) / \ + clkper) + /* Configuration *************************************************************/ #ifndef CONFIG_SCHED_HPWORK @@ -106,7 +126,7 @@ #endif /**************************************************************************** - * Private Types + * Public Types ****************************************************************************/ /* A MRF24J40 device instance */ @@ -157,38 +177,11 @@ struct mrf24j40_radio_s }; /**************************************************************************** - * Internal Function Prototypes + * Public Data ****************************************************************************/ -int mrf24j40_interrupt(int irq, FAR void *context, FAR void *arg); -void mrf24j40_irqworker(FAR void *arg); - -void mrf24j40_dopoll_csma(FAR void *arg); -void mrf24j40_dopoll_gts(FAR void *arg); - -void mrf24j40_resetrfsm(FAR struct mrf24j40_radio_s *dev); - -void mrf24j40_setorder(FAR struct mrf24j40_radio_s *dev, uint8_t bo, uint8_t so); - -int mrf24j40_pacontrol(FAR struct mrf24j40_radio_s *dev, int mode); -int mrf24j40_energydetect(FAR struct mrf24j40_radio_s *dev, FAR uint8_t *energy); - -int mrf24j40_rxenable(FAR struct ieee802154_radio_s *dev, bool enable); - -void mrf24j40_norm_setup(FAR struct mrf24j40_radio_s *dev, - FAR struct iob_s *frame, bool csma); -void mrf24j40_gts_setup(FAR struct mrf24j40_radio_s *dev, uint8_t gts, - FAR struct iob_s *frame); -void mrf24j40_setup_fifo(FAR struct mrf24j40_radio_s *dev, - FAR const uint8_t *buf, uint8_t length, uint32_t fifo_addr); - -void mrf24j40_norm_trigger(FAR struct mrf24j40_radio_s *dev); -void mrf24j40_beacon_trigger(FAR struct mrf24j40_radio_s *dev); - -void mrf24j40_mactimer(FAR struct mrf24j40_radio_s *dev, int numsymbols); - /**************************************************************************** - * Internal Helpers + * Inline Functions ****************************************************************************/ /**************************************************************************** @@ -220,5 +213,24 @@ static inline void mrf24j40_spi_unlock(FAR struct spi_dev_s *spi) SPI_LOCK(spi,0); } -#endif /* __DRIVERS_WIRELESS_IEEE802154_MRF24J40_H */ +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ +int mrf24j40_interrupt(int irq, FAR void *context, FAR void *arg); +void mrf24j40_irqworker(FAR void *arg); + +void mrf24j40_dopoll_csma(FAR void *arg); +void mrf24j40_dopoll_gts(FAR void *arg); + +void mrf24j40_norm_setup(FAR struct mrf24j40_radio_s *dev, + FAR struct iob_s *frame, bool csma); +void mrf24j40_gts_setup(FAR struct mrf24j40_radio_s *dev, uint8_t gts, + FAR struct iob_s *frame); +void mrf24j40_setup_fifo(FAR struct mrf24j40_radio_s *dev, + FAR const uint8_t *buf, uint8_t length, uint32_t fifo_addr); + +void mrf24j40_norm_trigger(FAR struct mrf24j40_radio_s *dev); +void mrf24j40_beacon_trigger(FAR struct mrf24j40_radio_s *dev); + +#endif /* __DRIVERS_WIRELESS_IEEE802154_MRF24J40_H */ diff --git a/drivers/wireless/ieee802154/mrf24j40/mrf24j40_getset.c b/drivers/wireless/ieee802154/mrf24j40/mrf24j40_getset.c index a4b92ad666c..24bf5a644cb 100644 --- a/drivers/wireless/ieee802154/mrf24j40/mrf24j40_getset.c +++ b/drivers/wireless/ieee802154/mrf24j40/mrf24j40_getset.c @@ -43,11 +43,49 @@ #include #include +#include + #include "mrf24j40.h" #include "mrf24j40_reg.h" #include "mrf24j40_regops.h" #include "mrf24j40_getset.h" +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +static void mrf24j40_resetrfsm(FAR struct mrf24j40_radio_s *dev); + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: mrf24j40_resetrfsm + * + * Description: + * Reset the RF state machine. Required at boot, after channel change, + * and probably after PA settings. + * + ****************************************************************************/ + +static void mrf24j40_resetrfsm(FAR struct mrf24j40_radio_s *dev) +{ + uint8_t reg; + + reg = mrf24j40_getreg(dev->spi, MRF24J40_RFCTL); + reg |= 0x04; + mrf24j40_setreg(dev->spi, MRF24J40_RFCTL, reg); + + reg &= ~0x04; + mrf24j40_setreg(dev->spi, MRF24J40_RFCTL, reg); + up_udelay(200); +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + /**************************************************************************** * Name: mrf24j40_setrxmode * @@ -423,3 +461,47 @@ int mrf24j40_setcca(FAR struct mrf24j40_radio_s *dev, memcpy(&dev->cca, cca, sizeof(struct ieee802154_cca_s)); return OK; } + +/**************************************************************************** + * Name: mrf24j40_setpamode + * + * Description: + * Control the external LNA/PA on the MRF24J40MB/MC/MD/ME modules + * GPIO 1: PA enable + * GPIO 2: LNA enable + * GPIO 3: PA power enable (not required on MB) + ****************************************************************************/ + +int mrf24j40_setpamode(FAR struct mrf24j40_radio_s *dev, int mode) +{ + if (!dev->paenabled) + { + return OK; + } + + if (mode == MRF24J40_PA_AUTO) + { + mrf24j40_setreg(dev->spi, MRF24J40_TRISGPIO, 0x08); + mrf24j40_setreg(dev->spi, MRF24J40_GPIO , 0x08); + mrf24j40_setreg(dev->spi, MRF24J40_TESTMODE, 0x0F); + } + else if (mode == MRF24J40_PA_ED) + { + mrf24j40_setreg(dev->spi, MRF24J40_TESTMODE, 0x08); + mrf24j40_setreg(dev->spi, MRF24J40_TRISGPIO, 0x0F); + mrf24j40_setreg(dev->spi, MRF24J40_GPIO , 0x0C); + } + else if (mode == MRF24J40_PA_SLEEP) + { + mrf24j40_setreg(dev->spi, MRF24J40_TESTMODE, 0x08); + mrf24j40_setreg(dev->spi, MRF24J40_TRISGPIO, 0x0F); + mrf24j40_setreg(dev->spi, MRF24J40_GPIO , 0x00); + } + else + { + return -EINVAL; + } + + mrf24j40_resetrfsm(dev); + return OK; +} diff --git a/drivers/wireless/ieee802154/mrf24j40/mrf24j40_getset.h b/drivers/wireless/ieee802154/mrf24j40/mrf24j40_getset.h index 999ce928759..f1acb79feeb 100644 --- a/drivers/wireless/ieee802154/mrf24j40/mrf24j40_getset.h +++ b/drivers/wireless/ieee802154/mrf24j40/mrf24j40_getset.h @@ -61,4 +61,6 @@ int mrf24j40_settxpower(FAR struct mrf24j40_radio_s *dev, int32_t txpwr); int mrf24j40_setcca(FAR struct mrf24j40_radio_s *dev, FAR struct ieee802154_cca_s *cca); +int mrf24j40_setpamode(FAR struct mrf24j40_radio_s *dev, int mode); + #endif /* __DRIVERS_WIRELESS_IEEE802154_MRF24J40_GETSET_H */ \ No newline at end of file diff --git a/drivers/wireless/ieee802154/mrf24j40/mrf24j40_radif.c b/drivers/wireless/ieee802154/mrf24j40/mrf24j40_radif.c index ae6df003f5b..546984ff1c8 100644 --- a/drivers/wireless/ieee802154/mrf24j40/mrf24j40_radif.c +++ b/drivers/wireless/ieee802154/mrf24j40/mrf24j40_radif.c @@ -48,6 +48,8 @@ #include #include +#include + #include #include @@ -60,6 +62,18 @@ * Pre-processor Definitions ****************************************************************************/ +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +static void mrf24j40_mactimer(FAR struct mrf24j40_radio_s *dev, int numsymbols); +static void mrf24j40_setorder(FAR struct mrf24j40_radio_s *dev, uint8_t bo, + uint8_t so); + /**************************************************************************** * Private Data ****************************************************************************/ @@ -70,9 +84,119 @@ static const uint8_t g_allones[8] = }; /**************************************************************************** - * Radio Interface Functions + * Public Data ****************************************************************************/ +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +static void mrf24j40_mactimer(FAR struct mrf24j40_radio_s *dev, int numsymbols) +{ + uint16_t nhalfsym; + uint8_t reg; + + nhalfsym = (numsymbols << 1); + + /* Disable the interrupt, clear the timer count */ + + reg = mrf24j40_getreg(dev->spi, MRF24J40_INTCON); + reg |= MRF24J40_INTCON_HSYMTMRIE; + mrf24j40_setreg(dev->spi, MRF24J40_INTCON, reg); + + mrf24j40_setreg(dev->spi, MRF24J40_HSYMTMRL, 0x00); + mrf24j40_setreg(dev->spi, MRF24J40_HSYMTMRH, 0x00); + + reg &= ~MRF24J40_INTCON_HSYMTMRIE; + mrf24j40_setreg(dev->spi, MRF24J40_INTCON, reg); + + /* Set the timer count and enable interrupts */ + + reg = (nhalfsym & 0xFF); + mrf24j40_setreg(dev->spi, MRF24J40_HSYMTMRL, reg); + + reg = (nhalfsym >> 8) & 0xFF; + mrf24j40_setreg(dev->spi, MRF24J40_HSYMTMRH, reg); +} + +/**************************************************************************** + * Name: mrf24j40_setorder + * + * Description: + * Configures the timers and sets the ORDER register + ****************************************************************************/ + +static void mrf24j40_setorder(FAR struct mrf24j40_radio_s *dev, uint8_t bo, + uint8_t so) +{ + uint32_t maincnt = 0; + uint32_t slpcal = 0; + + wlinfo("bo: %d, so: %d\n", bo, so); + + /* Calibrate the Sleep Clock (SLPCLK) frequency. Refer to Section 3.15.1.2 + * “Sleep Clock Calibration”. + */ + + /* If the Sleep Clock Selection, SLPCLKSEL (0x207<7:6), is the internal + * oscillator (100 kHz), set SLPCLKDIV to a minimum value of 0x01. + */ + + mrf24j40_setreg(dev->spi, MRF24J40_SLPCON1, 0x01); + + /* Select the source of SLPCLK (internal 100kHz) */ + + mrf24j40_setreg(dev->spi, MRF24J40_RFCON7, MRF24J40_RFCON7_SEL_100KHZ); + + /* Begin calibration by setting the SLPCALEN bit (SLPCAL2 0x20B<4>) to + * ‘1’. Sixteen samples of the SLPCLK are counted and stored in the + * SLPCAL register. No need to mask, this is the only writable bit + */ + + mrf24j40_setreg(dev->spi, MRF24J40_SLPCAL2, MRF24J40_SLPCAL2_SLPCALEN); + + /* Calibration is complete when the SLPCALRDY bit (SLPCAL2 0x20B<7>) is + * set to ‘1’. + */ + + while (!(mrf24j40_getreg(dev->spi, MRF24J40_SLPCAL2) & + MRF24J40_SLPCAL2_SLPCALRDY)) + { + up_udelay(1); + } + + slpcal = mrf24j40_getreg(dev->spi, MRF24J40_SLPCAL0); + slpcal |= (mrf24j40_getreg(dev->spi, MRF24J40_SLPCAL1) << 8); + slpcal |= ((mrf24j40_getreg(dev->spi, MRF24J40_SLPCAL2) << 16) & 0x0F); + + /* Program the Beacon Interval into the Main Counter, MAINCNT (0x229<1:0>, + * 0x228, 0x227, 0x226), and Remain Counter, REMCNT (0x225, 0x224), + * according to BO and SO values. Refer to Section 3.15.1.3 “Sleep Mode + * Counters” + */ + + mrf24j40_setreg(dev->spi, MRF24J40_REMCNTL, (MRF24J40_REMCNT & 0xFF)); + mrf24j40_setreg(dev->spi, MRF24J40_REMCNTH, ((MRF24J40_REMCNT >> 8) & 0xFF)); + + maincnt = MRF24J40_MAINCNT(bo, (slpcal * 50 / 16)); + + mrf24j40_setreg(dev->spi, MRF24J40_MAINCNT0, (maincnt & 0xFF)); + mrf24j40_setreg(dev->spi, MRF24J40_MAINCNT1, ((maincnt >> 8) & 0xFF)); + mrf24j40_setreg(dev->spi, MRF24J40_MAINCNT2, ((maincnt >> 16) & 0xFF)); + mrf24j40_setreg(dev->spi, MRF24J40_MAINCNT3, ((maincnt >> 24) & 0x03)); + + /* Configure the BO (ORDER 0x10<7:4>) and SO (ORDER 0x10<3:0>) values. + * After configuring BO and SO, the beacon frame will be sent immediately. + */ + + mrf24j40_setreg(dev->spi, MRF24J40_ORDER, ((bo << 4) & 0xF0) | (so & 0x0F)); +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ +/* Radio Interface Functions ***********************************************/ + int mrf24j40_bind(FAR struct ieee802154_radio_s *radio, FAR struct ieee802154_radiocb_s *radiocb) { @@ -222,6 +346,56 @@ int mrf24j40_txdelayed(FAR struct ieee802154_radio_s *radio, return OK; } +/**************************************************************************** + * Name: mrf24j40_rxenable + * + * Description: + * Enable/Disable receiver. + * + ****************************************************************************/ + +int mrf24j40_rxenable(FAR struct ieee802154_radio_s *radio, bool enable) +{ + FAR struct mrf24j40_radio_s *dev = (FAR struct mrf24j40_radio_s *)radio; + uint8_t reg; + + dev->rxenabled = enable; + + + if (enable) + { + /* Disable packet reception. See pg. 109 of datasheet */ + + mrf24j40_setreg(dev->spi, MRF24J40_BBREG1, MRF24J40_BBREG1_RXDECINV); + + /* Enable rx int */ + + reg = mrf24j40_getreg(dev->spi, MRF24J40_INTCON); + reg &= ~MRF24J40_INTCON_RXIE; + mrf24j40_setreg(dev->spi, MRF24J40_INTCON, reg); + + /* Purge the RX buffer */ + + reg = mrf24j40_getreg(dev->spi, MRF24J40_RXFLUSH); + reg |= MRF24J40_RXFLUSH_RXFLUSH; + mrf24j40_setreg(dev->spi, MRF24J40_RXFLUSH, reg); + + /* Re-enable packet reception. See pg. 109 of datasheet */ + + mrf24j40_setreg(dev->spi, MRF24J40_BBREG1, 0); + } + else + { + /* Disable rx int */ + + reg = mrf24j40_getreg(dev->spi, MRF24J40_INTCON); + reg |= MRF24J40_INTCON_RXIE; + mrf24j40_setreg(dev->spi, MRF24J40_INTCON, reg); + } + + return OK; +} + int mrf24j40_reset(FAR struct ieee802154_radio_s *radio) { FAR struct mrf24j40_radio_s *dev = (FAR struct mrf24j40_radio_s *)radio; @@ -258,6 +432,23 @@ int mrf24j40_reset(FAR struct ieee802154_radio_s *radio) mrf24j40_setreg(dev->spi, MRF24J40_ACKTMOUT, 0x39 | MRF24J40_ACKTMOUT_DRPACK); + /* Set WAKETIME to recommended value for 100kHz SLPCLK Source. + * + * NOTE!!!: The datasheet specifies that WAKETIME > WAKECNT. It appears that + * it is even sensitive to the order in which you set WAKECNT and WAKETIME. + * Meaning, if you set WAKECNT first and it goes higher than WAKETIME, and + * then raise WAKETIME above WAKECNT, the device will not function correctly. + * Therefore, be careful when changing these registers + */ + + mrf24j40_setreg(dev->spi, MRF24J40_WAKETIMEL, 0xD2); + mrf24j40_setreg(dev->spi, MRF24J40_WAKETIMEH, 0x00); + + /* Set WAKECNT (SLPACK 0x35<6:0>) value = 0x5F to set the main oscillator + * (20 MHz) start-up timer value. + */ + + mrf24j40_setreg(dev->spi, MRF24J40_SLPACK, 0x5F); /* Enable the SLPIF and WAKEIF flags */ @@ -286,7 +477,7 @@ int mrf24j40_reset(FAR struct ieee802154_radio_s *radio) mrf24j40_settxpower(dev, 0); /*16. Set transmitter power .*/ - mrf24j40_pacontrol(dev, MRF24J40_PA_AUTO); + mrf24j40_setpamode(dev, MRF24J40_PA_AUTO); return OK; } @@ -518,3 +709,4 @@ int mrf24j40_sfupdate(FAR struct ieee802154_radio_s *radio, return OK; } + diff --git a/drivers/wireless/ieee802154/mrf24j40/mrf24j40_radif.h b/drivers/wireless/ieee802154/mrf24j40/mrf24j40_radif.h index 3eb678c6036..8d5fe07d094 100644 --- a/drivers/wireless/ieee802154/mrf24j40/mrf24j40_radif.h +++ b/drivers/wireless/ieee802154/mrf24j40/mrf24j40_radif.h @@ -55,6 +55,7 @@ int mrf24j40_txdelayed(FAR struct ieee802154_radio_s *radio, FAR struct ieee802154_txdesc_s *txdesc, uint32_t symboldelay); +int mrf24j40_rxenable(FAR struct ieee802154_radio_s *radio, bool enable); int mrf24j40_beaconstart(FAR struct ieee802154_radio_s *radio, FAR const struct ieee802154_superframespec_s *sfspec, diff --git a/wireless/ieee802154/mac802154_start.c b/wireless/ieee802154/mac802154_start.c index 2bab5afd15d..e5684a39a32 100644 --- a/wireless/ieee802154/mac802154_start.c +++ b/wireless/ieee802154/mac802154_start.c @@ -201,4 +201,4 @@ int mac802154_req_start(MACHANDLE mac, FAR struct ieee802154_start_req_s *req) errout: mac802154_unlock(priv) return ret; -} \ No newline at end of file +}