Skip to content

Instantly share code, notes, and snippets.

@mschulz
Last active December 15, 2015 11:09
Show Gist options
  • Save mschulz/5250657 to your computer and use it in GitHub Desktop.
Save mschulz/5250657 to your computer and use it in GitHub Desktop.
This code runs on an Arduino Uno, using a Sparkfun nRF24L01+ Breakout board to capture packets from an Openbeacon Active Badge. The data is passed via the serial data on the USB. In my case, I have the Uno plugged into a USB port on a Raspberry Pi. I run a bit of Python code on the Pi to encapsulate the badge data and publish that packet via MQT…
// Sniff the Openbeacon messages with the NRF24 class.
// Feed the messages to the USB port for upstream processing,
// hopefully using a Raspberry Pi. :-) This is much simpler than
// using the Netduino as a base platform, running FreeRTOS. The real hassle
// is to determine just how much processing to do on the Arduino, and how
// much to leave for the upstream processor.
//
// Wire the Sparkfun nRF24L01+ breakout board with a Uno as follows (Arduino pin => Nordic pin)
// GND == GND
// 3.3V == Vcc
// 11 == MOSI
// 12 == MISO
// 13 == SCK
// 10 == CSN
// 8 == CE
// IRQ is left disconnected
#include <NRF24.h>
#include <SPI.h>
#define XXTEA_BLOCK_COUNT 4
typedef union {
unsigned long data[XXTEA_BLOCK_COUNT];
unsigned char datab[XXTEA_BLOCK_COUNT * 4];
} __attribute__((__packed__)) TBeaconEnvelope;
// Singleton instance of the radio
NRF24 nrf24;
unsigned long swaplong(unsigned long src)
{
typedef union {
unsigned long l_word;
unsigned char l_byte[sizeof(long)];
} __attribute__((__packed__)) swapper;
swapper tmp;
unsigned char ooo;
tmp.l_word = src;
ooo = tmp.l_byte[0];
tmp.l_byte[0] = tmp.l_byte[3];
tmp.l_byte[3] = ooo;
ooo = tmp.l_byte[2];
tmp.l_byte[2] = tmp.l_byte[1];
tmp.l_byte[1] = ooo;
return tmp.l_word;
}
unsigned long TEA_KEY[] = { 0x00112233, 0x44556677, 0x8899AABB, 0xCCDDEEFF };
#define TEA_ROUNDS_COUNT (6 + 52/4)
#define DELTA 0x9e3779b9L
void xxtea_decode(unsigned long v[], unsigned long len)
{
unsigned long z, y, sum, tmp, mx;
unsigned char e;
int q;
y = v[0];
for (sum = DELTA * TEA_ROUNDS_COUNT; sum != 0; sum -= DELTA) {
e = sum >> 2 & 3;
z = v[2];
tmp = v[3];
mx = ((((z >> 5) ^(y << 2)) + ((y >> 3) ^ (z << 4))) ^ ((sum ^ y) + (TEA_KEY[3 ^ e] ^ z)));
y = tmp - mx;
v[3] = y;
z = v[1];
tmp = v[2];
mx = ((((z >> 5) ^(y << 2)) + ((y >> 3) ^ (z << 4))) ^ ((sum ^ y) + (TEA_KEY[2 ^ e] ^ z)));
y = tmp - mx;
v[2] = y;
z = v[0];
tmp = v[1];
mx = ((((z >> 5) ^(y << 2)) + ((y >> 3) ^ (z << 4))) ^ ((sum ^ y) + (TEA_KEY[1 ^ e] ^ z)));
y = tmp - mx;
v[1] = y;
z = v[3];
tmp = v[0];
mx = ((((z >> 5) ^(y << 2)) + ((y >> 3) ^ (z << 4))) ^ ((sum ^ y) + (TEA_KEY[0 ^ e] ^ z)));
y = tmp - mx;
v[0] = y;
}
}
void printMessage(unsigned char *buf, unsigned char len)
{
unsigned char i;
Serial.print("M");
for (i = 0; i < len; i++) {
if (buf[i] < 0x10)
Serial.print("0");
Serial.print(buf[i], HEX);
}
Serial.println();
//Serial.write(buf, len);
}
unsigned short
crc16 (const unsigned char *buffer, int size)
{
unsigned short crc = 0xFFFF;
if (buffer && size)
while (size--) {
crc = (crc >> 8) | (crc << 8);
crc ^= *buffer++;
crc ^= ((unsigned char) crc) >> 4;
crc ^= crc << 12;
crc ^= (crc & 0xFF) << 5;
}
return crc;
}
void setup()
{
unsigned char SMAC[] = {0x01, 0x02, 0x03, 0x02, 0x01};
unsigned char TMAC[] = {'O', 'C', 'A', 'E', 'B'};
Serial.begin(115200);
nrf24.init();
nrf24.spiWriteRegister(NRF24_REG_00_CONFIG, 0x00); // Stop nRF
nrf24.spiWriteRegister(NRF24_REG_01_EN_AA, 0x00); //Disable Shockburst
nrf24.spiWriteRegister(NRF24_REG_02_EN_RXADDR, NRF24_ERX_P0); //Set Rx Pipe 0
nrf24.spiWriteRegister(NRF24_REG_03_SETUP_AW, NRF24_AW_5_BYTES); // Setup AW for 5 bytes
if (!nrf24.setChannel(81))
Serial.println("setChannel failed");
if (!nrf24.setRF(NRF24::NRF24DataRate2Mbps, NRF24::NRF24TransmitPowerm18dBm))
Serial.println("setRF failed");
nrf24.spiWriteRegister(NRF24_REG_07_STATUS, NRF24_RX_DR|NRF24_TX_DS|NRF24_MAX_RT|0x08); // Clear status regsiter
nrf24.spiBurstWriteRegister(NRF24_REG_0A_RX_ADDR_P0, SMAC, 5);
nrf24.spiBurstWriteRegister(NRF24_REG_10_TX_ADDR, TMAC, 5);
if (!nrf24.setPayloadSize(16))
Serial.println("setPayloadSize failed");
nrf24.spiWriteRegister(NRF24_REG_00_CONFIG, NRF24_MASK_RX_DR|NRF24_MASK_TX_DS|NRF24_MASK_MAX_RT|NRF24_EN_CRC|NRF24_PWR_UP|NRF24_PRIM_RX);
}
void loop()
{
unsigned char len;
unsigned int i;
TBeaconEnvelope g_Beacon;
unsigned short crc;
nrf24.powerUpRx();
if (nrf24.spiReadRegister(NRF24_REG_07_STATUS) & NRF24_RX_DR) {
if (nrf24.recv(g_Beacon.datab, &len)) {
// Only accept 16 byte messages, for now
if (len != 16) {
Serial.print("B ytes in message not equal to 16");
return;
}
/*
* Decode the packet, then check the packet is not corrupted.
*/
for (i = 0; i < len/4; i++)
g_Beacon.data[i] = swaplong(g_Beacon.data[i]);
xxtea_decode(g_Beacon.data, len/4);
for (i = 0; i < len/4; i++)
g_Beacon.data[i] = swaplong(g_Beacon.data[i]);
/*
*Pass up meesage to the upline processor via the serial connection (USB);
*
* Each line starts with a Tag characyer and a space and then any text you want.
*
* M<sp><16 bytes of messages as 16 pairs of hex characters
*C<sp> <nothing, but here the details of the CRC failure>
*/
crc = crc16(g_Beacon.datab, len);
if (crc != 0) {
Serial.print("CRC Error: 0x");
Serial.println(crc, HEX);
} else {
printMessage(g_Beacon.datab, len);
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment