Skip to content

Instantly share code, notes, and snippets.

@jwhitehorn
Created February 11, 2014 04:35
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jwhitehorn/8929306 to your computer and use it in GitHub Desktop.
Save jwhitehorn/8929306 to your computer and use it in GitHub Desktop.
#include <stdio.h>
#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/sleep.h>
#include <util/delay.h>
#define PIN_CE 1 //Output
#define PIN_nCS 2 //Output
#define output_low(port,pin) port &= ~(1<<pin)
#define output_high(port,pin) port |= (1<<pin)
#define set_input(portdir,pin) portdir &= ~(1<<pin)
#define set_output(portdir,pin) portdir |= (1<<pin)
#define MY_MAC_0 0xEF
#define MY_MAC_1 0xFF
#define MY_MAC_2 0xC0
#define MY_MAC_3 0xAA
#define MY_MAC_4 0x18
#define MY_MAC_5 0x00
ISR(PCINT0_vect)
{
//useless
}
void btLeCrc(const uint8_t* data, uint8_t len, uint8_t* dst){
uint8_t v, t, d;
while(len--){
d = *data++;
for(v = 0; v < 8; v++, d >>= 1){
t = dst[0] >> 7;
dst[0] <<= 1;
if(dst[1] & 0x80) dst[0] |= 1;
dst[1] <<= 1;
if(dst[2] & 0x80) dst[1] |= 1;
dst[2] <<= 1;
if(t != (d & 1)){
dst[2] ^= 0x5B;
dst[1] ^= 0x06;
}
}
}
}
uint8_t swapbits(uint8_t a){
uint8_t v = 0;
if(a & 0x80) v |= 0x01;
if(a & 0x40) v |= 0x02;
if(a & 0x20) v |= 0x04;
if(a & 0x10) v |= 0x08;
if(a & 0x08) v |= 0x10;
if(a & 0x04) v |= 0x20;
if(a & 0x02) v |= 0x40;
if(a & 0x01) v |= 0x80;
return v;
}
void btLeWhiten(uint8_t* data, uint8_t len, uint8_t whitenCoeff){
uint8_t m;
while(len--){
for(m = 1; m; m <<= 1){
if(whitenCoeff & 0x80){
whitenCoeff ^= 0x11;
(*data) ^= m;
}
whitenCoeff <<= 1;
}
data++;
}
}
static inline uint8_t btLeWhitenStart(uint8_t chan){
//the value we actually use is what BT'd use left shifted one...makes our life easier
return swapbits(chan) | 2;
}
void btLePacketEncode(uint8_t* packet, uint8_t len, uint8_t chan){
//length is of packet, including crc. pre-populate crc in packet with initial crc value!
uint8_t i, dataLen = len - 3;
btLeCrc(packet, dataLen, packet + dataLen);
for(i = 0; i < 3; i++, dataLen++) packet[dataLen] = swapbits(packet[dataLen]);
btLeWhiten(packet, len, btLeWhitenStart(chan));
for(i = 0; i < len; i++) packet[i] = swapbits(packet[i]);
}
void SPI_init(void){
DDRB = ((1<<DDB2)|(1<<DDB1)|(1<<DDB0)); //spi pins on port b MOSI SCK,SS outputs
SPCR = ((1<<SPE)|(1<<MSTR)|(1<<SPR0)|(1<<CPOL)|(1<<CPHA)); // SPI enable, Master, f/16
}
uint8_t spi_byte(uint8_t byte){
SPDR = byte;
while(!(SPSR & (1<<SPIF)))
;
return SPDR;
}
void nrf_cmd(uint8_t cmd, uint8_t data){
output_low(PORTB, PIN_nCS);
spi_byte(cmd);
spi_byte(data);
output_high(PORTB, PIN_nCS);
}
void nrf_simplebyte(uint8_t cmd){
output_low(PORTB, PIN_nCS);
spi_byte(cmd);
output_high(PORTB, PIN_nCS);
}
void nrf_manybytes(uint8_t* data, uint8_t len){
output_low(PORTB, PIN_nCS);
do{
spi_byte(*data++);
}while(--len);
output_high(PORTB, PIN_nCS);
}
void fob_init (void){
//DDRA = (uint8_t)~(1<<5);
DDRB = 0b00000110;
//PORTA = 0b10001111;
output_low(PORTB, PIN_CE);
TCCR0B = (1<<CS00);
MCUCR = (1<<SM1)|(1<<SE);
sei();
}
int main (void)
{
static const uint8_t chRf[] = {2, 26,80};
static const uint8_t chLe[] = {37,38,39};
uint8_t i, L, ch = 0;
uint8_t buf[32];
fob_init();
SPI_init();
//DDRA |= 4;
//PORTA |= 4;
nrf_cmd(0x20, 0x12); //on, no crc, int on RX/TX done
nrf_cmd(0x21, 0x00); //no auto-acknowledge
nrf_cmd(0x22, 0x00); //no RX
nrf_cmd(0x23, 0x02); //5-byte address
nrf_cmd(0x24, 0x00); //no auto-retransmit
nrf_cmd(0x26, 0x06); //1MBps at 0dBm
nrf_cmd(0x27, 0x3E); //clear various flags
nrf_cmd(0x3C, 0x00); //no dynamic payloads
nrf_cmd(0x3D, 0x00); //no features
nrf_cmd(0x31, 32); //always RX 32 bytes
nrf_cmd(0x22, 0x01); //RX on pipe 0
buf[0] = 0x30; //set addresses
buf[1] = swapbits(0x8E);
buf[2] = swapbits(0x89);
buf[3] = swapbits(0xBE);
buf[4] = swapbits(0xD6);
nrf_manybytes(buf, 5);
buf[0] = 0x2A;
nrf_manybytes(buf, 5);
while(1){
L = 0;
buf[L++] = 0x42; //PDU type, given address is random
buf[L++] = 11;//17 bytes of payload
buf[L++] = MY_MAC_0;
buf[L++] = MY_MAC_1;
buf[L++] = MY_MAC_2;
buf[L++] = MY_MAC_3;
buf[L++] = MY_MAC_4;
buf[L++] = MY_MAC_5;
buf[L++] = 2; //flags (LE-only, limited discovery mode)
buf[L++] = 0x01;
buf[L++] = 0x05;
buf[L++] = 7;
buf[L++] = 0x08;
buf[L++] = 'n';
buf[L++] = 'R';
buf[L++] = 'F';
buf[L++] = ' ';
buf[L++] = 'L';
buf[L++] = 'E';
buf[L++] = 0x55; //CRC start value: 0x555555
buf[L++] = 0x55;
buf[L++] = 0x55;
if(++ch == sizeof(chRf)) ch = 0;
nrf_cmd(0x25, chRf[ch]);
nrf_cmd(0x27, 0x6E); //clear flags
btLePacketEncode(buf, L, chLe[ch]);
nrf_simplebyte(0xE2); //Clear RX Fifo
nrf_simplebyte(0xE1); //Clear TX Fifo
output_low(PORTB, PIN_nCS);
spi_byte(0xA0);
for(i = 0 ; i < L ; i++) spi_byte(buf[i]);
output_high(PORTB, PIN_nCS);
nrf_cmd(0x20, 0x12); //tx on
output_high(PORTB, PIN_CE);
_delay_ms(10);
output_low(PORTB, PIN_CE); //(in preparation of switching to RX quickly)
}
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment