Last active
December 15, 2015 11:09
-
-
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…
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// 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