Library for the (decidedly not as good as the 24L01+) Nordic 2401A radio.

Nrf2401A.cpp

Committer:
heroic
Date:
2013-09-20
Revision:
0:db163b6f1592
Child:
1:049f6cb8b160

File content as of revision 0:db163b6f1592:

/*
 *  Nrf2401A.h
 *  A simplistic interface for using Sparkfun's Nrf2401A breakout boards with Arduino
 *
 *  Ported to mbed by Jas Strong <jasmine@heroicrobotics.com>
 *
 *  Original code for http://labs.ideo.com by Jesse Tane March 2009
 *
 *  License:
 *  --------
 *  This is free software. You can redistribute it and/or modify it under
 *  the terms of Creative Commons Attribution 3.0 United States License. 
 *  To view a copy of this license, visit http://creativecommons.org/licenses/by/3.0/us/ 
 *  or send a letter to Creative Commons, 171 Second Street, Suite 300, San Francisco, California, 94105, USA.
 *
 *  Notes:
 *  ------
 *  For documentation on how to use this library, please visit http://www.arduino.cc/playground/Main/InterfacingWithHardware
 *  Pin connections should be as follows for Arduino:
 *
 *  DR1 = 2  (digital pin 2)
 *  CE  = 3
 *  CS  = 4
 *  CLK = 5
 *  DAT = 6
 *
 */

#include "Nrf2401.h"

inline void select_chip(void) {
    _ce = 1;
}

inline void deselect_chip(void) {
    _ce = 0;
}

inline void enable_chip(void) {
    _ce = 1;
}

inline void disable_chip(void) {
    _ce = 0;
}

inline void cycle_clock(void) {
    _clk = 1;
    delay_us(1);
    _clk = 0;
}

inline void tx_data_lo(void) {
    _dat.output();
    _dat = 1;
}

inline void tx_data_hi(void) {
    _dat.output();
    _dat = 1;
}

inline int rx_data_hi(void) {
    _dat.input();
    return _dat;
}

inline int data_ready(void) {
    return _dr1;
}

Nrf2401::Nrf2401(PinName n_DR1, PinName n_CE, PinName n_CS, PinName n_CLK, PinName n_DAT) :
    _dr1(n_DR1), _ce(n_CE), _cs(n_CS), _clk(n_CLK), _clk(n_CLK), _dat(n_DAT)
{
  _dat.output();
  
  remoteAddress = 0;
  localAddress = 0;
  payloadSize = 0;
  dataRate = 1;
  channel = 111;
  power = 3;
  mode = 0;
  
  configuration[7] = 234;
  configuration[8] = 223;
  configuration[9] = 212;
  
  disable_chip();
  deselect_chip();
}

void Nrf2401::rxMode(unsigned char messageSize)
{
  mode = 1;
  if(messageSize) payloadSize = messageSize, configure();
  else configuration[14] |= 1, loadConfiguration(true);
  enable_chip();
  delay_us(250);
}

void Nrf2401::txMode(unsigned char messageSize)
{
  mode = 0;
  if(messageSize) payloadSize = messageSize, configure();
  else configuration[14] &= ~1, loadConfiguration(true);
  delay_us(250);
}

void Nrf2401::write(unsigned char* dataBuffer)
{
  if(!dataBuffer) dataBuffer = (unsigned char*) data;
  enable_chip();
  delay_us(5);
  loadByte(configuration[7]);
  loadByte(configuration[8]);
  loadByte(configuration[9]);
  loadByte(remoteAddress >> 8);
  loadByte(remoteAddress);
  for(int i=0; i<payloadSize; i++) loadByte(dataBuffer[i]);
  disable_chip();
  delay_us(250);
}

void Nrf2401::write(unsigned char dataByte)
{
  data[0] = dataByte;
  write();
}

void Nrf2401::read(unsigned char* dataBuffer)
{
  if(!dataBuffer) dataBuffer = (unsigned char*) data;
  disable_chip();
  _delay_ms(2);
  for(int i=0; i<payloadSize; i++)
  {
    dataBuffer[i] = 0;
    for(int n=7; n>-1; n--)
    {
      if(RX_DATA_HI) dataBuffer[i] |= (1 << n);
      delay_us(1);
      cycle_clock();
    }
  }
  enable_chip();
  delay_us(1);
}

bool Nrf2401::available(void)
{
  return data_ready();
}

//// you shouldn't need to call directly any of the methods below this point...

void Nrf2401::configure(void)
{
  configuration[1] = payloadSize << 3;
  configuration[10] = localAddress >> 8;
  configuration[11] = localAddress;
  configuration[12] = 163;
  configuration[13] = power | (dataRate << 5) | 76;
  configuration[14] = mode | (channel << 1);
  loadConfiguration();
}

void Nrf2401::loadConfiguration(bool modeSwitchOnly)
{
  disable_chip();
  select_chip();
  delay_us(5);
  if(modeSwitchOnly) loadByte(configuration[14]);
  else for(int i=0; i<15; i++) loadByte(configuration[i]);
  deselect_chip();
}

void Nrf2401::loadByte(unsigned char byte)
{
  for(int i=7; i>-1; i--)
  {
    if((byte & (1 << i)) == 0) tx_data_lo();
    else                       tx_data_hi();
    delay_us(1);
    cycle_clock();
  }
}