diff --git a/RC_Turrel/README.md b/RC_Turrel/README.md new file mode 100644 index 0000000..ad56413 --- /dev/null +++ b/RC_Turrel/README.md @@ -0,0 +1,36 @@ +# DIY RC FPV rocket turrel + + +## Schemes +![TX](https://github.com/AlexGyver/RC_Turrel/blob/master/%D0%A1%D1%85%D0%B5%D0%BC%D1%8B/TX_bb.png) + +![RX](https://github.com/AlexGyver/RC_Turrel/blob/master/%D0%A1%D1%85%D0%B5%D0%BC%D1%8B/RX_bb.png) + +## Components +* Arduino NANO x2 http://ali.pub/uxbqf + +* RF24 radio x2 http://ali.pub/2cmut +* Power adapter x2 http://ali.pub/ynf1u +* Or this http://ali.pub/uy67g + +* 18650 batteries http://alexgyver.ru/18650/ +* 18650 holder http://ali.pub/0jumn +* DC-DC booster http://ali.pub/m86vt + +* LEDs http://ali.pub/cgqui +* Resistors 220 Ohm http://ali.pub/9suk0 +* Toggles http://ali.pub/iv1p0 +* Joystick http://ali.pub/96qlf + +* Prototype board http://ali.pub/v0rxe +* Mosfets http://ali.pub/s58ow +* Resistors 100 Ohm http://ali.pub/u4jqh +* Terminal http://ali.pub/weq63 +* Wire http://ali.pub/45sw9 +* Servo 180 degree http://ali.pub/crigl +* Servo 360 http://ali.pub/90qsn + +* FPV display http://ali.pub/ihw4c +* FPV camera 3 in 1 http://ali.pub/b32a1 +* Reciever http://ali.pub/mrwo9 +* 3S battery http://ali.pub/u53i8 \ No newline at end of file diff --git a/RC_Turrel/drawings/RX.fzz b/RC_Turrel/drawings/RX.fzz new file mode 100644 index 0000000..404c4c1 Binary files /dev/null and b/RC_Turrel/drawings/RX.fzz differ diff --git a/RC_Turrel/drawings/RX_bb.jpg b/RC_Turrel/drawings/RX_bb.jpg new file mode 100644 index 0000000..9aff7c8 Binary files /dev/null and b/RC_Turrel/drawings/RX_bb.jpg differ diff --git a/RC_Turrel/drawings/TX.fzz b/RC_Turrel/drawings/TX.fzz new file mode 100644 index 0000000..5bbd0bb Binary files /dev/null and b/RC_Turrel/drawings/TX.fzz differ diff --git a/RC_Turrel/drawings/TX_bb.jpg b/RC_Turrel/drawings/TX_bb.jpg new file mode 100644 index 0000000..445215a Binary files /dev/null and b/RC_Turrel/drawings/TX_bb.jpg differ diff --git a/RC_Turrel/firmware/pyroRX/pyroRX.ino b/RC_Turrel/firmware/pyroRX/pyroRX.ino new file mode 100644 index 0000000..03a11ed --- /dev/null +++ b/RC_Turrel/firmware/pyroRX/pyroRX.ino @@ -0,0 +1,112 @@ +/* Данный скетч делает следующее: передатчик (TX) отправляет массив + данных, который генерируется согласно показаниям с кнопки и с + двух потенциомтеров. Приёмник (RX) получает массив, и записывает + данные на реле, сервомашинку и генерирует ШИМ сигнал на транзистор. + by AlexGyver 2016 +*/ + +#include +#include "nRF24L01.h" +#include "RF24.h" +#include + +Servo servoX, servoY; + +byte MOSFET[12] = {4, 18, 5, 17, 7, 15, 3, 19, 6, 16, 8, 14}; //массив пинов, к которым подключены мосфеты +boolean FLAGS[12]; // массив, хранящий время для таймера каждого мосфета? по умолчанию {0,0,0,0,0,0,0,0} +unsigned long TIMES[12]; // массив, хранящий состояния мосфетов + +int fuse_time = 1800; // время в миллисекундах, которое ток будет подаваться на спираль +byte fuse_number; +boolean launch, launch_flag; +int in_data[3] = {0, 512, 512}; +byte pipeNo; + +RF24 radio(9, 10); // "создать" модуль на пинах 9 и 10 Для Уно + +byte address[][6] = {"1Node", "2Node", "3Node", "4Node", "5Node", "6Node"}; //возможные номера труб + +int posX0 = 1470; // начальное положение серво по оси Х (серво постоянного вращения, покоится на месте) +int posY = 1500; // начальное положение серво по оси Х (серво постоянного вращения, покоится на месте) +int posX; +int errorX, errorY; // переменные для расчёта ошибки +unsigned long last; + +void setup() { + //Serial.begin(9600); //открываем порт для связи с ПК + + servoX.attach(1); + servoY.attach(0); + + // настраиваем пины мосфетов как выходы по массиву + for (int i = 0; i <= 11; i++) { + pinMode(MOSFET[i], OUTPUT); + } + + radio.begin(); //активировать модуль + radio.setAutoAck(1); //режим подтверждения приёма, 1 вкл 0 выкл + radio.setRetries(0, 15); //(время между попыткой достучаться, число попыток) + radio.enableAckPayload(); //разрешить отсылку данных в ответ на входящий сигнал + radio.setPayloadSize(6); //размер пакета, в байтах + + radio.openReadingPipe(1, address[0]); //хотим слушать трубу 0 + radio.setChannel(0x60); //выбираем канал (в котором нет шумов!) + + radio.setPALevel (RF24_PA_MAX); //уровень мощности передатчика. На выбор RF24_PA_MIN, RF24_PA_LOW, RF24_PA_HIGH, RF24_PA_MAX + radio.setDataRate (RF24_1MBPS); //скорость обмена. На выбор RF24_2MBPS, RF24_1MBPS, RF24_250KBPS + //должна быть одинакова на приёмнике и передатчике! + //при самой низкой скорости имеем самую высокую чувствительность и дальность!! + + radio.powerUp(); //начать работу + radio.startListening(); //начинаем слушать эфир, мы приёмный модуль +} + +void loop() { + + if (millis() - last > 3) { + posX = posX0 - errorX / 3; // управляем скоростью вращения сервы по Х + posY = posY - errorY / 300; // управляем скоростью вращения сервы по Y + + posX = constrain(posX, 900, 2000); // ограничиваем текущее положение серв, чтобы не выходило за пределы вращения + posY = constrain(posY, 900, 2000); + + last = millis(); + } + + while ( radio.available(&pipeNo)) { // слушаем эфир со всех труб + radio.read( &in_data, sizeof(in_data) ); // читаем входящий сигнал + + errorX = in_data[0]; // расчёт ошибки, как начальное положение ручки - текущее + errorY = in_data[1]; // расчёт ошибки, как начальное положение ручки - текущее + + servoX.writeMicroseconds(posX); + servoY.writeMicroseconds(posY); + + launch = in_data[2]; + + if (launch == 1 && launch_flag == 0) { + launch_flag = 1; + + if (FLAGS[fuse_number] == 0) { + FLAGS[fuse_number] = 1; // поднять флаг для мосфета, по входящему сигналу + TIMES[fuse_number] = millis(); // запомнить время прихода сигнала + digitalWrite(MOSFET[fuse_number], HIGH); // подать питание на мосфет (на запал) + //Serial.print("Fuse #"); Serial.print(fuse_number); Serial.println(" ON"); + } + fuse_number++; + if (fuse_number > 11) fuse_number = 0; + } + if (launch == 0 && launch_flag == 1) { + launch_flag = 0; + } + + } + + for (int i = 0; i <= 11; i++) { // пройтись по всем 10ти мосфетам + if (millis() - TIMES[i] > fuse_time && FLAGS[i] == 1) { // если время с момента открытия мосфета > заданного + digitalWrite(MOSFET[i], LOW); // закрыть мосфет, погасить запал + FLAGS[i] = 0; + //Serial.print("Fuse #"); Serial.print(i); Serial.println(" OFF"); + } + } +} diff --git a/RC_Turrel/firmware/pyroTX/pyroTX.ino b/RC_Turrel/firmware/pyroTX/pyroTX.ino new file mode 100644 index 0000000..d6f8cd9 --- /dev/null +++ b/RC_Turrel/firmware/pyroTX/pyroTX.ino @@ -0,0 +1,97 @@ +/* + Created 2017 + by AlexGyver + AlexGyver Home Labs Inc. +*/ +#include "Keypad.h" //библиотека клавиатуры +#include // библиотека для работы с шиной SPI +#include "nRF24L01.h" // библиотека радиомодуля +#include "RF24.h" // ещё библиотека радиомодуля + +RF24 radio(9, 10); // "создать" модуль на пинах 9 и 10 Для Уно +byte address[][6] = {"1Node", "2Node", "3Node", "4Node", "5Node", "6Node"}; //возможные номера труб + +byte redLED = 2; +byte greenLED = 3; +byte ready_toggle = 4; +byte launch_butt = 8; + +byte stickX = 0; +byte stickY = 1; +int stickX0, stickY0; +int errorX, errorY; // переменные для расчёта ошибки + +int check = 111; + +boolean check_answer; +boolean flag, flag_fuse, launch_flag, toggle_flag; + +int out_data[3]; // [номер запала, состояние, позиция Х сервы, позиция У сервы] + +unsigned long last; + +void setup() { + Serial.begin(9600); + + pinMode(redLED, OUTPUT); + pinMode(greenLED, OUTPUT); + digitalWrite(greenLED, HIGH); // зажечь зелёный светодиод + + pinMode(launch_butt, INPUT_PULLUP); + pinMode(ready_toggle, INPUT_PULLUP); + + delay(50); + stickX0 = analogRead(stickX); + delay(50); + stickY0 = analogRead(stickY); + + radio.begin(); //активировать модуль + radio.setAutoAck(1); //режим подтверждения приёма, 1 вкл 0 выкл + radio.setRetries(0, 15); //(время между попыткой достучаться, число попыток) + radio.enableAckPayload(); //разрешить отсылку данных в ответ на входящий сигнал + radio.setPayloadSize(6); //размер пакета, в байтах + + radio.openWritingPipe(address[0]); //мы - труба 0, открываем канал для передачи данных + radio.setChannel(0x60); //выбираем канал (в котором нет шумов!) + + radio.setPALevel (RF24_PA_MAX); //уровень мощности передатчика. На выбор RF24_PA_MIN, RF24_PA_LOW, RF24_PA_HIGH, RF24_PA_MAX + radio.setDataRate (RF24_1MBPS); //скорость обмена. На выбор RF24_2MBPS, RF24_1MBPS, RF24_250KBPS + //должна быть одинакова на приёмнике и передатчике! + //при самой низкой скорости имеем самую высокую чувствительность и дальность!! + + radio.powerUp(); //начать работу + radio.stopListening(); //не слушаем радиоэфир, мы передатчик +} + +void loop() { + if (abs(stickX0 - analogRead(stickX)) > 2) errorX = stickX0 - analogRead(0); else errorX = 0; + if (abs(stickY0 - analogRead(stickY)) > 2) errorY = stickY0 - analogRead(1); else errorY = 0; + + out_data[0] = errorY; + out_data[1] = errorX; + radio.write(&out_data, sizeof(out_data)); + + boolean launch_butt_state = !digitalRead(launch_butt); + boolean toggle_state = !digitalRead(ready_toggle); + + if (launch_butt_state == 1 && launch_flag == 0 && flag == 1) { + out_data[2] = 1; + radio.write(&out_data, sizeof(out_data)); + out_data[2] = 0; + launch_flag = 1; + } + if (launch_butt_state == 0 && launch_flag == 1) { + launch_flag = 0; + } + if (toggle_state == 1) { + digitalWrite(greenLED, LOW); + digitalWrite(redLED, HIGH); + flag = 1; + } + if (toggle_state == 0) { + digitalWrite(greenLED, HIGH); + digitalWrite(redLED, LOW); + flag = 0; + } +} + diff --git a/RC_Turrel/libraries/RF24-master/RF24.cpp b/RC_Turrel/libraries/RF24-master/RF24.cpp new file mode 100644 index 0000000..aaade07 --- /dev/null +++ b/RC_Turrel/libraries/RF24-master/RF24.cpp @@ -0,0 +1,1319 @@ +/* + Copyright (C) 2011 J. Coliz + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + */ + +#include "nRF24L01.h" +#include "RF24_config.h" +#include "RF24.h" + +/****************************************************************************/ + +void RF24::csn(bool mode) +{ + // Minimum ideal SPI bus speed is 2x data rate + // If we assume 2Mbs data rate and 16Mhz clock, a + // divider of 4 is the minimum we want. + // CLK:BUS 8Mhz:2Mhz, 16Mhz:4Mhz, or 20Mhz:5Mhz +#ifdef ARDUINO + #if ( !defined( __AVR_ATtiny85__ ) && !defined( __AVR_ATtiny84__) && !defined (__arm__) ) || defined (CORE_TEENSY) + SPI.setBitOrder(MSBFIRST); + SPI.setDataMode(SPI_MODE0); + SPI.setClockDivider(SPI_CLOCK_DIV2); + #endif +#endif + +#if !defined (__arm__) || defined (CORE_TEENSY) + digitalWrite(csn_pin,mode); +#endif + +} + +/****************************************************************************/ + +void RF24::ce(bool level) +{ + digitalWrite(ce_pin,level); +} + +/****************************************************************************/ + +uint8_t RF24::read_register(uint8_t reg, uint8_t* buf, uint8_t len) +{ + uint8_t status; + +#if defined (__arm__) && !defined ( CORE_TEENSY ) + status = SPI.transfer(csn_pin, R_REGISTER | ( REGISTER_MASK & reg ), SPI_CONTINUE ); + while ( len-- > 1 ){ + *buf++ = SPI.transfer(csn_pin,0xff, SPI_CONTINUE); + } + *buf++ = SPI.transfer(csn_pin,0xff); + +#else + csn(LOW); + status = SPI.transfer( R_REGISTER | ( REGISTER_MASK & reg ) ); + while ( len-- ){ + *buf++ = SPI.transfer(0xff); + } + csn(HIGH); + +#endif + + return status; +} + +/****************************************************************************/ + +uint8_t RF24::read_register(uint8_t reg) +{ + + #if defined (__arm__) && !defined ( CORE_TEENSY ) + SPI.transfer(csn_pin, R_REGISTER | ( REGISTER_MASK & reg ) , SPI_CONTINUE); + uint8_t result = SPI.transfer(csn_pin,0xff); + #else + csn(LOW); + SPI.transfer( R_REGISTER | ( REGISTER_MASK & reg ) ); + uint8_t result = SPI.transfer(0xff); + + csn(HIGH); + #endif + + return result; +} + +/****************************************************************************/ + +uint8_t RF24::write_register(uint8_t reg, const uint8_t* buf, uint8_t len) +{ + uint8_t status; + + #if defined (__arm__) && !defined ( CORE_TEENSY ) + status = SPI.transfer(csn_pin, W_REGISTER | ( REGISTER_MASK & reg ), SPI_CONTINUE ); + while ( --len){ + SPI.transfer(csn_pin,*buf++, SPI_CONTINUE); + } + SPI.transfer(csn_pin,*buf++); + #else + + csn(LOW); + status = SPI.transfer( W_REGISTER | ( REGISTER_MASK & reg ) ); + while ( len-- ) + SPI.transfer(*buf++); + + csn(HIGH); + + #endif + + return status; +} + +/****************************************************************************/ + +uint8_t RF24::write_register(uint8_t reg, uint8_t value) +{ + uint8_t status; + + IF_SERIAL_DEBUG(printf_P(PSTR("write_register(%02x,%02x)\r\n"),reg,value)); + + #if defined (__arm__) && !defined ( CORE_TEENSY ) + status = SPI.transfer(csn_pin, W_REGISTER | ( REGISTER_MASK & reg ), SPI_CONTINUE); + SPI.transfer(csn_pin,value); + #else + + csn(LOW); + status = SPI.transfer( W_REGISTER | ( REGISTER_MASK & reg ) ); + SPI.transfer(value); + csn(HIGH); + + #endif + + return status; +} + +/****************************************************************************/ + +uint8_t RF24::write_payload(const void* buf, uint8_t data_len, const uint8_t writeType) +{ + uint8_t status; + const uint8_t* current = reinterpret_cast(buf); + + if(data_len > 32) data_len = 32; + uint8_t blank_len = dynamic_payloads_enabled ? 0 : 32 - data_len; + + //printf("[Writing %u bytes %u blanks]",data_len,blank_len); + + #if defined (__arm__) && !defined ( CORE_TEENSY ) + + status = SPI.transfer(csn_pin, writeType , SPI_CONTINUE); + + if(blank_len){ + while ( data_len--){ + SPI.transfer(csn_pin,*current++, SPI_CONTINUE); + } + while ( --blank_len ){ + SPI.transfer(csn_pin,0, SPI_CONTINUE); + } + SPI.transfer(csn_pin,0); + }else{ + while( --data_len ){ + SPI.transfer(csn_pin,*current++, SPI_CONTINUE); + } + SPI.transfer(csn_pin,*current); + } + + #else + + csn(LOW); + status = SPI.transfer( writeType ); + while ( data_len-- ) { + SPI.transfer(*current++); + } + while ( blank_len-- ) { + SPI.transfer(0); + } + csn(HIGH); + + #endif + + return status; +} + +/****************************************************************************/ + +uint8_t RF24::read_payload(void* buf, uint8_t data_len) +{ + uint8_t status; + uint8_t* current = reinterpret_cast(buf); + + if(data_len > payload_size) data_len = payload_size; + uint8_t blank_len = dynamic_payloads_enabled ? 0 : 32 - data_len; + + //printf("[Reading %u bytes %u blanks]",data_len,blank_len); + + + #if defined (__arm__) && !defined ( CORE_TEENSY ) + + status = SPI.transfer(csn_pin, R_RX_PAYLOAD, SPI_CONTINUE ); + + if( blank_len ){ + while ( data_len-- ){ + *current++ = SPI.transfer(csn_pin,0xFF, SPI_CONTINUE); + } + + while ( --blank_len ){ + SPI.transfer(csn_pin,0xFF, SPI_CONTINUE); + } + SPI.transfer(csn_pin,0xFF); + }else{ + while ( --data_len ){ + *current++ = SPI.transfer(csn_pin,0xFF, SPI_CONTINUE); + } + *current = SPI.transfer(csn_pin,0xFF); + } + + #else + + csn(LOW); + status = SPI.transfer( R_RX_PAYLOAD ); + while ( data_len-- ) { + *current++ = SPI.transfer(0xFF); + } + while ( blank_len-- ) { + SPI.transfer(0xff); + } + csn(HIGH); + + #endif + + return status; +} + +/****************************************************************************/ + +uint8_t RF24::flush_rx(void) +{ + return spiTrans( FLUSH_RX ); +} + +/****************************************************************************/ + +uint8_t RF24::flush_tx(void) +{ + return spiTrans( FLUSH_TX ); +} + +/****************************************************************************/ + +uint8_t RF24::spiTrans(uint8_t cmd){ + + uint8_t status; + #if defined (__arm__) && !defined ( CORE_TEENSY ) + status = SPI.transfer(csn_pin, cmd ); + #else + + csn(LOW); + status = SPI.transfer( cmd ); + csn(HIGH); + #endif + return status; + +} + +/****************************************************************************/ + +uint8_t RF24::get_status(void) +{ + return spiTrans(NOP); +} + +/****************************************************************************/ + +void RF24::print_status(uint8_t status) +{ + printf_P(PSTR("STATUS\t\t = 0x%02x RX_DR=%x TX_DS=%x MAX_RT=%x RX_P_NO=%x TX_FULL=%x\r\n"), + status, + (status & _BV(RX_DR))?1:0, + (status & _BV(TX_DS))?1:0, + (status & _BV(MAX_RT))?1:0, + ((status >> RX_P_NO) & B111), + (status & _BV(TX_FULL))?1:0 + ); +} + +/****************************************************************************/ + +void RF24::print_observe_tx(uint8_t value) +{ + printf_P(PSTR("OBSERVE_TX=%02x: POLS_CNT=%x ARC_CNT=%x\r\n"), + value, + (value >> PLOS_CNT) & B1111, + (value >> ARC_CNT) & B1111 + ); +} + +/****************************************************************************/ + +void RF24::print_byte_register(const char* name, uint8_t reg, uint8_t qty) +{ + char extra_tab = strlen_P(name) < 8 ? '\t' : 0; + printf_P(PSTR(PRIPSTR"\t%c ="),name,extra_tab); + while (qty--) + printf_P(PSTR(" 0x%02x"),read_register(reg++)); + printf_P(PSTR("\r\n")); +} + +/****************************************************************************/ + +void RF24::print_address_register(const char* name, uint8_t reg, uint8_t qty) +{ + char extra_tab = strlen_P(name) < 8 ? '\t' : 0; + printf_P(PSTR(PRIPSTR"\t%c ="),name,extra_tab); + + while (qty--) + { + uint8_t buffer[addr_width]; + read_register(reg++,buffer,sizeof buffer); + + printf_P(PSTR(" 0x")); + uint8_t* bufptr = buffer + sizeof buffer; + while( --bufptr >= buffer ) + printf_P(PSTR("%02x"),*bufptr); + } + + printf_P(PSTR("\r\n")); +} + +/****************************************************************************/ + +RF24::RF24(uint8_t _cepin, uint8_t _cspin): + ce_pin(_cepin), csn_pin(_cspin), p_variant(false), + payload_size(32), dynamic_payloads_enabled(false), addr_width(5)//,pipe0_reading_address(0) +{ +} + +/****************************************************************************/ + +void RF24::setChannel(uint8_t channel) +{ + const uint8_t max_channel = 127; + write_register(RF_CH,min(channel,max_channel)); +} + +/****************************************************************************/ + +void RF24::setPayloadSize(uint8_t size) +{ + payload_size = min(size,32); +} + +/****************************************************************************/ + +uint8_t RF24::getPayloadSize(void) +{ + return payload_size; +} + +/****************************************************************************/ + +#if !defined (MINIMAL) + +static const char rf24_datarate_e_str_0[] PROGMEM = "1MBPS"; +static const char rf24_datarate_e_str_1[] PROGMEM = "2MBPS"; +static const char rf24_datarate_e_str_2[] PROGMEM = "250KBPS"; +static const char * const rf24_datarate_e_str_P[] PROGMEM = { + rf24_datarate_e_str_0, + rf24_datarate_e_str_1, + rf24_datarate_e_str_2, +}; +static const char rf24_model_e_str_0[] PROGMEM = "nRF24L01"; +static const char rf24_model_e_str_1[] PROGMEM = "nRF24L01+"; +static const char * const rf24_model_e_str_P[] PROGMEM = { + rf24_model_e_str_0, + rf24_model_e_str_1, +}; +static const char rf24_crclength_e_str_0[] PROGMEM = "Disabled"; +static const char rf24_crclength_e_str_1[] PROGMEM = "8 bits"; +static const char rf24_crclength_e_str_2[] PROGMEM = "16 bits" ; +static const char * const rf24_crclength_e_str_P[] PROGMEM = { + rf24_crclength_e_str_0, + rf24_crclength_e_str_1, + rf24_crclength_e_str_2, +}; +static const char rf24_pa_dbm_e_str_0[] PROGMEM = "PA_MIN"; +static const char rf24_pa_dbm_e_str_1[] PROGMEM = "PA_LOW"; +static const char rf24_pa_dbm_e_str_2[] PROGMEM = "PA_HIGH"; +static const char rf24_pa_dbm_e_str_3[] PROGMEM = "PA_MAX"; +static const char * const rf24_pa_dbm_e_str_P[] PROGMEM = { + rf24_pa_dbm_e_str_0, + rf24_pa_dbm_e_str_1, + rf24_pa_dbm_e_str_2, + rf24_pa_dbm_e_str_3, +}; + +void RF24::printDetails(void) +{ + print_status(get_status()); + + print_address_register(PSTR("RX_ADDR_P0-1"),RX_ADDR_P0,2); + print_byte_register(PSTR("RX_ADDR_P2-5"),RX_ADDR_P2,4); + print_address_register(PSTR("TX_ADDR"),TX_ADDR); + + print_byte_register(PSTR("RX_PW_P0-6"),RX_PW_P0,6); + print_byte_register(PSTR("EN_AA"),EN_AA); + print_byte_register(PSTR("EN_RXADDR"),EN_RXADDR); + print_byte_register(PSTR("RF_CH"),RF_CH); + print_byte_register(PSTR("RF_SETUP"),RF_SETUP); + print_byte_register(PSTR("CONFIG"),CONFIG); + print_byte_register(PSTR("DYNPD/FEATURE"),DYNPD,2); + +#if defined(__arm__) + printf_P(PSTR("Data Rate\t = %s\r\n"),pgm_read_word(&rf24_datarate_e_str_P[getDataRate()])); + printf_P(PSTR("Model\t\t = %s\r\n"),pgm_read_word(&rf24_model_e_str_P[isPVariant()])); + printf_P(PSTR("CRC Length\t = %s\r\n"),pgm_read_word(&rf24_crclength_e_str_P[getCRCLength()])); + printf_P(PSTR("PA Power\t = %s\r\n"),pgm_read_word(&rf24_pa_dbm_e_str_P[getPALevel()])); +#else + printf_P(PSTR("Data Rate\t = %S\r\n"),pgm_read_word(&rf24_datarate_e_str_P[getDataRate()])); + printf_P(PSTR("Model\t\t = %S\r\n"),pgm_read_word(&rf24_model_e_str_P[isPVariant()])); + printf_P(PSTR("CRC Length\t = %S\r\n"),pgm_read_word(&rf24_crclength_e_str_P[getCRCLength()])); + printf_P(PSTR("PA Power\t = %S\r\n"),pgm_read_word(&rf24_pa_dbm_e_str_P[getPALevel()])); +#endif +} + +#endif +/****************************************************************************/ + +void RF24::begin(void) +{ + // Initialize pins + pinMode(ce_pin,OUTPUT); + + #if defined(__arm__) && ! defined( CORE_TEENSY ) + SPI.begin(csn_pin); // Using the extended SPI features of the DUE + SPI.setClockDivider(csn_pin, 9); // Set the bus speed to 8.4mhz on Due + SPI.setBitOrder(csn_pin,MSBFIRST); // Set the bit order and mode specific to this device + SPI.setDataMode(csn_pin,SPI_MODE0); + ce(LOW); + //csn(HIGH); + #else + pinMode(csn_pin,OUTPUT); + SPI.begin(); + ce(LOW); + csn(HIGH); + #endif + + // Must allow the radio time to settle else configuration bits will not necessarily stick. + // This is actually only required following power up but some settling time also appears to + // be required after resets too. For full coverage, we'll always assume the worst. + // Enabling 16b CRC is by far the most obvious case if the wrong timing is used - or skipped. + // Technically we require 4.5ms + 14us as a worst case. We'll just call it 5ms for good measure. + // WARNING: Delay is based on P-variant whereby non-P *may* require different timing. + delay( 5 ) ; + + // Set 1500uS (minimum for 32B payload in ESB@250KBPS) timeouts, to make testing a little easier + // WARNING: If this is ever lowered, either 250KBS mode with AA is broken or maximum packet + // sizes must never be used. See documentation for a more complete explanation. + setRetries(5,15); + + // Reset value is MAX + //setPALevel( RF24_PA_MAX ) ; + + // Determine if this is a p or non-p RF24 module and then + // reset our data rate back to default value. This works + // because a non-P variant won't allow the data rate to + // be set to 250Kbps. + if( setDataRate( RF24_250KBPS ) ) + { + p_variant = true ; + } + + // Then set the data rate to the slowest (and most reliable) speed supported by all + // hardware. + setDataRate( RF24_1MBPS ) ; + + // Initialize CRC and request 2-byte (16bit) CRC + setCRCLength( RF24_CRC_16 ) ; + + // Disable dynamic payloads, to match dynamic_payloads_enabled setting - Reset value is 0 + //write_register(DYNPD,0); + + // Reset current status + // Notice reset and flush is the last thing we do + write_register(STATUS,_BV(RX_DR) | _BV(TX_DS) | _BV(MAX_RT) ); + + // Set up default configuration. Callers can always change it later. + // This channel should be universally safe and not bleed over into adjacent + // spectrum. + setChannel(76); + + // Flush buffers + flush_rx(); + flush_tx(); + + powerUp(); //Power up by default when begin() is called + + // Enable PTX, do not write CE high so radio will remain in standby I mode ( 130us max to transition to RX or TX instead of 1500us from powerUp ) + // PTX should use only 22uA of power + write_register(CONFIG, ( read_register(CONFIG) ) & ~_BV(PRIM_RX) ); + +} + +/****************************************************************************/ + +void RF24::startListening(void) +{ + powerUp(); + write_register(CONFIG, read_register(CONFIG) | _BV(PRIM_RX)); + write_register(STATUS, _BV(RX_DR) | _BV(TX_DS) | _BV(MAX_RT) ); + + // Restore the pipe0 adddress, if exists + if (pipe0_reading_address[0] > 0){ + write_register(RX_ADDR_P0, pipe0_reading_address, addr_width); + } + + // Flush buffers + //flush_rx(); + flush_tx(); + + // Go! + ce(HIGH); + +} + +/****************************************************************************/ + +void RF24::stopListening(void) +{ + + ce(LOW); + #if defined(__arm__) + delayMicroseconds(130); + #endif + flush_tx(); + //flush_rx(); + + write_register(CONFIG, ( read_register(CONFIG) ) & ~_BV(PRIM_RX) ); + delayMicroseconds(130); //Found that adding this delay back actually increases response time +} + +/****************************************************************************/ + +void RF24::powerDown(void) +{ + ce(LOW); // Guarantee CE is low on powerDown + write_register(CONFIG,read_register(CONFIG) & ~_BV(PWR_UP)); +} + +/****************************************************************************/ + +//Power up now. Radio will not power down unless instructed by MCU for config changes etc. +void RF24::powerUp(void) +{ + uint8_t cfg = read_register(CONFIG); + + // if not powered up then power up and wait for the radio to initialize + if (!(cfg & _BV(PWR_UP))){ + write_register(CONFIG,read_register(CONFIG) | _BV(PWR_UP)); + + // For nRF24L01+ to go from power down mode to TX or RX mode it must first pass through stand-by mode. + // There must be a delay of Tpd2stby (see Table 16.) after the nRF24L01+ leaves power down mode before + // the CEis set high. - Tpd2stby can be up to 5ms per the 1.0 datasheet + delay(5); + + } +} + +/******************************************************************/ +#if defined (FAILURE_HANDLING) +void RF24::errNotify(){ + IF_SERIAL_DEBUG(printf_P(PSTR("HARDWARE FAIL\r\n"))); + failureDetected = 1; +} +#endif +/******************************************************************/ + +//Similar to the previous write, clears the interrupt flags +bool RF24::write( const void* buf, uint8_t len, const bool multicast ) +{ + //Start Writing + startFastWrite(buf,len,multicast); + + //Wait until complete or failed + #if defined (FAILURE_HANDLING) + uint32_t timer = millis(); + #endif + + while( ! ( get_status() & ( _BV(TX_DS) | _BV(MAX_RT) ))) { + #if defined (FAILURE_HANDLING) + if(millis() - timer > 75){ + errNotify(); + return 0; + } + #endif + } + + ce(LOW); + + uint8_t status = write_register(STATUS,_BV(RX_DR) | _BV(TX_DS) | _BV(MAX_RT) ); + + //Max retries exceeded + if( status & _BV(MAX_RT)){ + flush_tx(); //Only going to be 1 packet int the FIFO at a time using this method, so just flush + return 0; + } + //TX OK 1 or 0 + return 1; +} + +bool RF24::write( const void* buf, uint8_t len ){ + return write(buf,len,0); +} +/****************************************************************************/ + +//For general use, the interrupt flags are not important to clear +bool RF24::writeBlocking( const void* buf, uint8_t len, uint32_t timeout ) +{ + //Block until the FIFO is NOT full. + //Keep track of the MAX retries and set auto-retry if seeing failures + //This way the FIFO will fill up and allow blocking until packets go through + //The radio will auto-clear everything in the FIFO as long as CE remains high + + uint32_t timer = millis(); //Get the time that the payload transmission started + + while( ( get_status() & ( _BV(TX_FULL) ))) { //Blocking only if FIFO is full. This will loop and block until TX is successful or timeout + + if( get_status() & _BV(MAX_RT)){ //If MAX Retries have been reached + reUseTX(); //Set re-transmit and clear the MAX_RT interrupt flag + if(millis() - timer > timeout){ return 0; } //If this payload has exceeded the user-defined timeout, exit and return 0 + } + #if defined (FAILURE_HANDLING) + if(millis() - timer > (timeout+75) ){ + errNotify(); + return 0; + } + #endif + + } + + //Start Writing + startFastWrite(buf,len,0); //Write the payload if a buffer is clear + + return 1; //Return 1 to indicate successful transmission +} + +/****************************************************************************/ + +void RF24::reUseTX(){ + write_register(STATUS,_BV(MAX_RT) ); //Clear max retry flag + spiTrans( REUSE_TX_PL ); + ce(LOW); //Re-Transfer packet + ce(HIGH); +} + +/****************************************************************************/ + +bool RF24::writeFast( const void* buf, uint8_t len, const bool multicast ) +{ + //Block until the FIFO is NOT full. + //Keep track of the MAX retries and set auto-retry if seeing failures + //Return 0 so the user can control the retrys and set a timer or failure counter if required + //The radio will auto-clear everything in the FIFO as long as CE remains high + + #if defined (FAILURE_HANDLING) + uint32_t timer = millis(); + #endif + + while( ( get_status() & ( _BV(TX_FULL) ))) { //Blocking only if FIFO is full. This will loop and block until TX is successful or fail + + if( get_status() & _BV(MAX_RT)){ + //reUseTX(); //Set re-transmit + write_register(STATUS,_BV(MAX_RT) ); //Clear max retry flag + return 0; //Return 0. The previous payload has been retransmitted + //From the user perspective, if you get a 0, just keep trying to send the same payload + } + #if defined (FAILURE_HANDLING) + if(millis() - timer > 75 ){ + errNotify(); + return 0; + } + #endif + } + //Start Writing + startFastWrite(buf,len,multicast); + + return 1; +} + +bool RF24::writeFast( const void* buf, uint8_t len ){ + return writeFast(buf,len,0); +} + +/****************************************************************************/ + +//Per the documentation, we want to set PTX Mode when not listening. Then all we do is write data and set CE high +//In this mode, if we can keep the FIFO buffers loaded, packets will transmit immediately (no 130us delay) +//Otherwise we enter Standby-II mode, which is still faster than standby mode +//Also, we remove the need to keep writing the config register over and over and delaying for 150 us each time if sending a stream of data + +void RF24::startFastWrite( const void* buf, uint8_t len, const bool multicast){ //TMRh20 + + //write_payload( buf,len); + write_payload( buf, len,multicast ? W_TX_PAYLOAD_NO_ACK : W_TX_PAYLOAD ) ; + ce(HIGH); + +} + + +//Added the original startWrite back in so users can still use interrupts, ack payloads, etc +//Allows the library to pass all tests +void RF24::startWrite( const void* buf, uint8_t len, const bool multicast ){ + + // Send the payload + + //write_payload( buf, len ); + write_payload( buf, len,multicast? W_TX_PAYLOAD_NO_ACK : W_TX_PAYLOAD ) ; + ce(HIGH); + #if defined(CORE_TEENSY) || !defined(ARDUINO) + delayMicroseconds(10); + #endif + ce(LOW); + + +} + +bool RF24::txStandBy(){ + #if defined (FAILURE_HANDLING) + uint32_t timeout = millis(); + #endif + while( ! (read_register(FIFO_STATUS) & _BV(TX_EMPTY)) ){ + if( get_status() & _BV(MAX_RT)){ + write_register(STATUS,_BV(MAX_RT) ); + ce(LOW); + flush_tx(); //Non blocking, flush the data + return 0; + } + #if defined (FAILURE_HANDLING) + if( millis() - timeout > 75){ + errNotify(); + return 0; + } + #endif + } + + ce(LOW); //Set STANDBY-I mode + return 1; +} + +bool RF24::txStandBy(uint32_t timeout){ + + uint32_t start = millis(); + + while( ! (read_register(FIFO_STATUS) & _BV(TX_EMPTY)) ){ + if( get_status() & _BV(MAX_RT)){ + write_register(STATUS,_BV(MAX_RT) ); + ce(LOW); //Set re-transmit + ce(HIGH); + if(millis() - start >= timeout){ + ce(LOW); flush_tx(); return 0; + } + } + #if defined (FAILURE_HANDLING) + if( millis() - start > (timeout+75)){ + errNotify(); + return 0; + } + #endif + } + + + ce(LOW); //Set STANDBY-I mode + return 1; + +} +/****************************************************************************/ + +void RF24::maskIRQ(bool tx, bool fail, bool rx){ + + write_register(CONFIG, ( read_register(CONFIG) ) | fail << MASK_MAX_RT | tx << MASK_TX_DS | rx << MASK_RX_DR ); +} + +/****************************************************************************/ + +uint8_t RF24::getDynamicPayloadSize(void) +{ + uint8_t result = 0; + + #if defined (__arm__) && ! defined( CORE_TEENSY ) + SPI.transfer(csn_pin, R_RX_PL_WID, SPI_CONTINUE ); + result = SPI.transfer(csn_pin,0xff); + #else + csn(LOW); + SPI.transfer( R_RX_PL_WID ); + result = SPI.transfer(0xff); + csn(HIGH); + + #endif + + if(result > 32) { flush_rx(); return 0; } + return result; +} + +/****************************************************************************/ + +bool RF24::available(void) +{ + return available(NULL); +} + +/****************************************************************************/ + +bool RF24::available(uint8_t* pipe_num) +{ + + //Check the FIFO buffer to see if data is waitng to be read + + if (!( read_register(FIFO_STATUS) & _BV(RX_EMPTY) )){ + + // If the caller wants the pipe number, include that + if ( pipe_num ){ + uint8_t status = get_status(); + *pipe_num = ( status >> RX_P_NO ) & B111; + } + return 1; + } + + + return 0; + + +} + +/****************************************************************************/ + +void RF24::read( void* buf, uint8_t len ){ + + // Fetch the payload + read_payload( buf, len ); + + //Clear the two possible interrupt flags with one command + write_register(STATUS,_BV(RX_DR) | _BV(MAX_RT) | _BV(TX_DS) ); + +} + +/****************************************************************************/ + +void RF24::whatHappened(bool& tx_ok,bool& tx_fail,bool& rx_ready) +{ + // Read the status & reset the status in one easy call + // Or is that such a good idea? + uint8_t status = write_register(STATUS,_BV(RX_DR) | _BV(TX_DS) | _BV(MAX_RT) ); + + // Report to the user what happened + tx_ok = status & _BV(TX_DS); + tx_fail = status & _BV(MAX_RT); + rx_ready = status & _BV(RX_DR); +} + +/****************************************************************************/ + +void RF24::openWritingPipe(uint64_t value) +{ + // Note that AVR 8-bit uC's store this LSB first, and the NRF24L01(+) + // expects it LSB first too, so we're good. + + write_register(RX_ADDR_P0, reinterpret_cast(&value), addr_width); + write_register(TX_ADDR, reinterpret_cast(&value), addr_width); + + //const uint8_t max_payload_size = 32; + //write_register(RX_PW_P0,min(payload_size,max_payload_size)); + write_register(RX_PW_P0,payload_size); +} + +/****************************************************************************/ +void RF24::openWritingPipe(const uint8_t *address) +{ + // Note that AVR 8-bit uC's store this LSB first, and the NRF24L01(+) + // expects it LSB first too, so we're good. + + write_register(RX_ADDR_P0,address, addr_width); + write_register(TX_ADDR, address, addr_width); + + //const uint8_t max_payload_size = 32; + //write_register(RX_PW_P0,min(payload_size,max_payload_size)); + write_register(RX_PW_P0,payload_size); +} + +/****************************************************************************/ +static const uint8_t child_pipe[] PROGMEM = +{ + RX_ADDR_P0, RX_ADDR_P1, RX_ADDR_P2, RX_ADDR_P3, RX_ADDR_P4, RX_ADDR_P5 +}; +static const uint8_t child_payload_size[] PROGMEM = +{ + RX_PW_P0, RX_PW_P1, RX_PW_P2, RX_PW_P3, RX_PW_P4, RX_PW_P5 +}; +static const uint8_t child_pipe_enable[] PROGMEM = +{ + ERX_P0, ERX_P1, ERX_P2, ERX_P3, ERX_P4, ERX_P5 +}; + +void RF24::openReadingPipe(uint8_t child, uint64_t address) +{ + // If this is pipe 0, cache the address. This is needed because + // openWritingPipe() will overwrite the pipe 0 address, so + // startListening() will have to restore it. + if (child == 0){ + memcpy(pipe0_reading_address,&address,addr_width); + } + + if (child <= 6) + { + // For pipes 2-5, only write the LSB + if ( child < 2 ) + write_register(pgm_read_byte(&child_pipe[child]), reinterpret_cast(&address), addr_width); + else + write_register(pgm_read_byte(&child_pipe[child]), reinterpret_cast(&address), 1); + + write_register(pgm_read_byte(&child_payload_size[child]),payload_size); + + // Note it would be more efficient to set all of the bits for all open + // pipes at once. However, I thought it would make the calling code + // more simple to do it this way. + write_register(EN_RXADDR,read_register(EN_RXADDR) | _BV(pgm_read_byte(&child_pipe_enable[child]))); + } +} + +/****************************************************************************/ +void RF24::setAddressWidth(uint8_t a_width){ + + if(a_width -= 2){ + write_register(SETUP_AW,a_width%4); + addr_width = (a_width%4) + 2; + } + +} + +/****************************************************************************/ + +void RF24::openReadingPipe(uint8_t child, const uint8_t *address) +{ + // If this is pipe 0, cache the address. This is needed because + // openWritingPipe() will overwrite the pipe 0 address, so + // startListening() will have to restore it. + if (child == 0){ + memcpy(pipe0_reading_address,address,addr_width); + } + if (child <= 6) + { + // For pipes 2-5, only write the LSB + if ( child < 2 ){ + write_register(pgm_read_byte(&child_pipe[child]), address, addr_width); + }else{ + write_register(pgm_read_byte(&child_pipe[child]), address, 1); + } + write_register(pgm_read_byte(&child_payload_size[child]),payload_size); + + // Note it would be more efficient to set all of the bits for all open + // pipes at once. However, I thought it would make the calling code + // more simple to do it this way. + write_register(EN_RXADDR,read_register(EN_RXADDR) | _BV(pgm_read_byte(&child_pipe_enable[child]))); + + } +} + +/****************************************************************************/ + +void RF24::closeReadingPipe( uint8_t pipe ) +{ + write_register(EN_RXADDR,read_register(EN_RXADDR) & ~_BV(pgm_read_byte(&child_pipe_enable[pipe]))); +} + +/****************************************************************************/ + +void RF24::toggle_features(void) +{ + + #if defined (__arm__) && ! defined( CORE_TEENSY ) + SPI.transfer(csn_pin, ACTIVATE, SPI_CONTINUE ); + SPI.transfer(csn_pin, 0x73 ); + #else + csn(LOW); + SPI.transfer( ACTIVATE ); + SPI.transfer( 0x73 ); + csn(HIGH); + #endif +} + +/****************************************************************************/ + +void RF24::enableDynamicPayloads(void) +{ + // Enable dynamic payload throughout the system + + toggle_features(); + write_register(FEATURE,read_register(FEATURE) | _BV(EN_DPL) ); + + + IF_SERIAL_DEBUG(printf("FEATURE=%i\r\n",read_register(FEATURE))); + + // Enable dynamic payload on all pipes + // + // Not sure the use case of only having dynamic payload on certain + // pipes, so the library does not support it. + write_register(DYNPD,read_register(DYNPD) | _BV(DPL_P5) | _BV(DPL_P4) | _BV(DPL_P3) | _BV(DPL_P2) | _BV(DPL_P1) | _BV(DPL_P0)); + + dynamic_payloads_enabled = true; +} + +/****************************************************************************/ + +void RF24::enableAckPayload(void) +{ + // + // enable ack payload and dynamic payload features + // + + toggle_features(); + write_register(FEATURE,read_register(FEATURE) | _BV(EN_ACK_PAY) | _BV(EN_DPL) ); + + IF_SERIAL_DEBUG(printf("FEATURE=%i\r\n",read_register(FEATURE))); + + // + // Enable dynamic payload on pipes 0 & 1 + // + + write_register(DYNPD,read_register(DYNPD) | _BV(DPL_P1) | _BV(DPL_P0)); + dynamic_payloads_enabled = true; +} + +/****************************************************************************/ + +void RF24::enableDynamicAck(void){ + // + // enable dynamic ack features + // + toggle_features(); + write_register(FEATURE,read_register(FEATURE) | _BV(EN_DYN_ACK) ); + + IF_SERIAL_DEBUG(printf("FEATURE=%i\r\n",read_register(FEATURE))); + + +} + +/****************************************************************************/ + +void RF24::writeAckPayload(uint8_t pipe, const void* buf, uint8_t len) +{ + const uint8_t* current = reinterpret_cast(buf); + + uint8_t data_len = min(len,32); + + #if defined (__arm__) && ! defined( CORE_TEENSY ) + SPI.transfer(csn_pin, W_ACK_PAYLOAD | ( pipe & B111 ), SPI_CONTINUE); + while ( data_len-- > 1 ){ + SPI.transfer(csn_pin,*current++, SPI_CONTINUE); + } + SPI.transfer(csn_pin,*current++); + + #else + csn(LOW); + SPI.transfer(W_ACK_PAYLOAD | ( pipe & B111 ) ); + + while ( data_len-- ) + SPI.transfer(*current++); + + csn(HIGH); + + #endif +} + +/****************************************************************************/ + +bool RF24::isAckPayloadAvailable(void) +{ + return ! read_register(FIFO_STATUS) & _BV(RX_EMPTY); +} + +/****************************************************************************/ + +bool RF24::isPVariant(void) +{ + return p_variant ; +} + +/****************************************************************************/ + +void RF24::setAutoAck(bool enable) +{ + if ( enable ) + write_register(EN_AA, B111111); + else + write_register(EN_AA, 0); +} + +/****************************************************************************/ + +void RF24::setAutoAck( uint8_t pipe, bool enable ) +{ + if ( pipe <= 6 ) + { + uint8_t en_aa = read_register( EN_AA ) ; + if( enable ) + { + en_aa |= _BV(pipe) ; + } + else + { + en_aa &= ~_BV(pipe) ; + } + write_register( EN_AA, en_aa ) ; + } +} + +/****************************************************************************/ + +bool RF24::testCarrier(void) +{ + return ( read_register(CD) & 1 ); +} + +/****************************************************************************/ + +bool RF24::testRPD(void) +{ + return ( read_register(RPD) & 1 ) ; +} + +/****************************************************************************/ + +void RF24::setPALevel(uint8_t level) +{ + + uint8_t setup = read_register(RF_SETUP) & 0b11111000; + + if(level > 3){ // If invalid level, go to max PA + level = (RF24_PA_MAX << 1) + 1; // +1 to support the SI24R1 chip extra bit + }else{ + level = (level << 1) + 1; // Else set level as requested + } + + + write_register( RF_SETUP, setup |= level ) ; // Write it to the chip +} + +/****************************************************************************/ + +uint8_t RF24::getPALevel(void) +{ + + return (read_register(RF_SETUP) & (_BV(RF_PWR_LOW) | _BV(RF_PWR_HIGH))) >> 1 ; +} + +/****************************************************************************/ + +bool RF24::setDataRate(rf24_datarate_e speed) +{ + bool result = false; + uint8_t setup = read_register(RF_SETUP) ; + + // HIGH and LOW '00' is 1Mbs - our default + setup &= ~(_BV(RF_DR_LOW) | _BV(RF_DR_HIGH)) ; + if( speed == RF24_250KBPS ) + { + // Must set the RF_DR_LOW to 1; RF_DR_HIGH (used to be RF_DR) is already 0 + // Making it '10'. + setup |= _BV( RF_DR_LOW ) ; + } + else + { + // Set 2Mbs, RF_DR (RF_DR_HIGH) is set 1 + // Making it '01' + if ( speed == RF24_2MBPS ) + { + setup |= _BV(RF_DR_HIGH); + } + } + write_register(RF_SETUP,setup); + + // Verify our result + if ( read_register(RF_SETUP) == setup ) + { + result = true; + } + + return result; +} + +/****************************************************************************/ + +rf24_datarate_e RF24::getDataRate( void ) +{ + rf24_datarate_e result ; + uint8_t dr = read_register(RF_SETUP) & (_BV(RF_DR_LOW) | _BV(RF_DR_HIGH)); + + // switch uses RAM (evil!) + // Order matters in our case below + if ( dr == _BV(RF_DR_LOW) ) + { + // '10' = 250KBPS + result = RF24_250KBPS ; + } + else if ( dr == _BV(RF_DR_HIGH) ) + { + // '01' = 2MBPS + result = RF24_2MBPS ; + } + else + { + // '00' = 1MBPS + result = RF24_1MBPS ; + } + return result ; +} + +/****************************************************************************/ + +void RF24::setCRCLength(rf24_crclength_e length) +{ + uint8_t config = read_register(CONFIG) & ~( _BV(CRCO) | _BV(EN_CRC)) ; + + // switch uses RAM (evil!) + if ( length == RF24_CRC_DISABLED ) + { + // Do nothing, we turned it off above. + } + else if ( length == RF24_CRC_8 ) + { + config |= _BV(EN_CRC); + } + else + { + config |= _BV(EN_CRC); + config |= _BV( CRCO ); + } + write_register( CONFIG, config ) ; +} + +/****************************************************************************/ + +rf24_crclength_e RF24::getCRCLength(void) +{ + rf24_crclength_e result = RF24_CRC_DISABLED; + uint8_t config = read_register(CONFIG) & ( _BV(CRCO) | _BV(EN_CRC)) ; + + if ( config & _BV(EN_CRC ) ) + { + if ( config & _BV(CRCO) ) + result = RF24_CRC_16; + else + result = RF24_CRC_8; + } + + return result; +} + +/****************************************************************************/ + +void RF24::disableCRC( void ) +{ + uint8_t disable = read_register(CONFIG) & ~_BV(EN_CRC) ; + write_register( CONFIG, disable ) ; +} + +/****************************************************************************/ +void RF24::setRetries(uint8_t delay, uint8_t count) +{ + write_register(SETUP_RETR,(delay&0xf)< + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + */ + +/** + * @file RF24.h + * + * Class declaration for RF24 and helper enums + */ + +#ifndef __RF24_H__ +#define __RF24_H__ + +#include + +/** + * Power Amplifier level. + * + * For use with setPALevel() + */ +typedef enum { RF24_PA_MIN = 0,RF24_PA_LOW, RF24_PA_HIGH, RF24_PA_MAX, RF24_PA_ERROR } rf24_pa_dbm_e ; + +/** + * Data rate. How fast data moves through the air. + * + * For use with setDataRate() + */ +typedef enum { RF24_1MBPS = 0, RF24_2MBPS, RF24_250KBPS } rf24_datarate_e; + +/** + * CRC Length. How big (if any) of a CRC is included. + * + * For use with setCRCLength() + */ +typedef enum { RF24_CRC_DISABLED = 0, RF24_CRC_8, RF24_CRC_16 } rf24_crclength_e; + +/** + * Driver for nRF24L01(+) 2.4GHz Wireless Transceiver + */ + +class RF24 +{ +private: + uint8_t ce_pin; /**< "Chip Enable" pin, activates the RX or TX role */ + uint8_t csn_pin; /**< SPI Chip select */ + + bool p_variant; /* False for RF24L01 and true for RF24L01P */ + uint8_t payload_size; /**< Fixed size of payloads */ + bool dynamic_payloads_enabled; /**< Whether dynamic payloads are enabled. */ + uint8_t pipe0_reading_address[5]; /**< Last address set on pipe 0 for reading. */ + uint8_t addr_width; + + +public: + + /** + * @name Primary public interface + * + * These are the main methods you need to operate the chip + */ + /**@{*/ + + /** + * Constructor + * + * Creates a new instance of this driver. Before using, you create an instance + * and send in the unique pins that this chip is connected to. + * + * @param _cepin The pin attached to Chip Enable on the RF module + * @param _cspin The pin attached to Chip Select + */ + RF24(uint8_t _cepin, uint8_t _cspin); + + /** + * Begin operation of the chip + * + * Call this in setup(), before calling any other methods. + * + * @note Optimization: The radio is partially configured in PTX mode + * when begin is called to make the transition to PTX mode simpler. + */ + void begin(void); + + /** + * Start listening on the pipes opened for reading. + * + * Be sure to call openReadingPipe() first. Do not call write() while + * in this mode, without first calling stopListening(). Call + * isAvailable() to check for incoming traffic, and read() to get it. + */ + void startListening(void); + + /** + * Stop listening for incoming messages + * + * Do this before calling write(). + * + * @note Optimization: The radio will be taken out of PRX mode as soon + * as listening is stopped. Enables quicker and simpler engaging of + * primary transmitter (PTX) mode. + */ + void stopListening(void); + + /** + * Test whether there are bytes available to be read + * + * @note Optimization: The available functino now checks the FIFO + * buffers directly for data instead of relying of interrupt flags. + * + * @note Interrupt flags will not be cleared until a payload is + * actually read from the FIFO + * + * @see txStandBy() + * @see startWrite() + * @see write() + * @see writeFast() + * + * @return True if there is a payload available, false if none is + */ + bool available(void); + + /** + * Read the payload + * + * The size of data read is the fixed payload size, see getPayloadSize() + * + * @note I specifically chose 'void*' as a data type to make it easier + * for beginners to use. No casting needed. + * + * @note Optimization: No longer boolean. Use available to + * determine if packets are available. Interrupt flags are now cleared + * during reads instead of when calling available(). + * + * @param buf Pointer to a buffer where the data should be written + * @param len Maximum number of bytes to read into the buffer + * @return No return value. Use available(). + */ + void read( void* buf, uint8_t len ); + + /** + * @note Optimization: Improved performance slightly + * Write to the open writing pipe + * + * Be sure to call openWritingPipe() first to set the destination + * of where to write to. + * + * This blocks until the message is successfully acknowledged by + * the receiver or the timeout/retransmit maxima are reached. In + * the current configuration, the max delay here is 60ms. + * + * The maximum size of data written is the fixed payload size, see + * getPayloadSize(). However, you can write less, and the remainder + * will just be filled with zeroes. + * + * TX/RX/RT interrupt flags will be cleared every time write is called + * + * @param buf Pointer to the data to be sent + * @param len Number of bytes to be sent + * @return True if the payload was delivered successfully false if not + */ + bool write( const void* buf, uint8_t len ); + + /** + * New: Open a pipe for writing + * + * Only one pipe can be open at once, but you can change the pipe + * you'll write to. Call stopListening() first. + * + * Addresses are assigned via a byte array, default is 5 byte address length + * + * Usage is exactly the same as before, except for declaring the array + * + * @code + * uint8_t addresses[][6] = {"1Node","2Node"}; + * openWritingPipe(addresses[0]); + * @endcode + * @see setAddressWidth + * + * @param address The address of the pipe to open. Coordinate these pipe + * addresses amongst nodes on the network. + */ + + void openWritingPipe(const uint8_t *address); + + /** + * Open a pipe for reading + * + * Up to 6 pipes can be open for reading at once. Open all the + * reading pipes, and then call startListening(). + * + * @see openWritingPipe + * @see setAddressWidth + * + * @warning Pipes 1-5 should share the same address, except the first byte. + * Only the first byte in the array should be unique, e.g. + * @code + * uint8_t addresses[][6] = {"1Node","2Node"}; + * openReadingPipe(1,addresses[0]); + * openReadingPipe(2,addresses[1]); + * @endcode + * + * @warning Pipe 0 is also used by the writing pipe. So if you open + * pipe 0 for reading, and then startListening(), it will overwrite the + * writing pipe. Ergo, do an openWritingPipe() again before write(). + * + * @param number Which pipe# to open, 0-5. + * @param address The 24, 32 or 40 bit address of the pipe to open. + */ + + void openReadingPipe(uint8_t number, const uint8_t *address); + + /** + * Close a pipe after it has been previously opened. + * Can be safely called without having previously opened a pipe. + * @param pipe Which pipe # to close, 0-5. + */ + void closeReadingPipe( uint8_t pipe ) ; + + /**@}*/ + /** + * @name Advanced Operation + * + * Methods you can use to drive the chip in more advanced ways + */ + /**@{*/ + + /** + * Print a giant block of debugging information to stdout + * + * @warning Does nothing if stdout is not defined. See fdevopen in stdio.h + */ + void printDetails(void); + + /** + * Test whether there are bytes available to be read in the + * FIFO buffers. This optimized version does not rely on interrupt + * flags, but checks the actual FIFO buffers. + * + * @note Optimization: Interrupt flags are no longer cleared when available is called, + * but will be reset only when the data is read from the FIFO buffers. + * + * @param[out] pipe_num Which pipe has the payload available + * @return True if there is a payload available, false if none is + */ + bool available(uint8_t* pipe_num); + + /** + * Enter low-power mode + * + * To return to normal power mode, either write() some data or + * startListening, or powerUp(). + * + * @note Optimization: The radio will never enter power down unless instructed + * by the MCU via this command. + */ + void powerDown(void); + + /** + * Leave low-power mode - making radio more responsive + * + * To return to low power mode, call powerDown(). + */ + void powerUp(void) ; + + /** + * Write for single NOACK writes. Disables acknowledgements/autoretries for a single write. + * + * @note enableDynamicAck() must be called to enable this feature + * + * Can be used with enableAckPayload() to request a response + * @see enableDynamicAck() + * @see setAutoAck() + * @see write() + * + * @param buf Pointer to the data to be sent + * @param len Number of bytes to be sent + * @param multicast Request ACK (0), NOACK (1) + */ + bool write( const void* buf, uint8_t len, const bool multicast ); + + /** + * @note Optimization: New Command * + * This will not block until the 3 FIFO buffers are filled with data. + * Once the FIFOs are full, writeFast will simply wait for success or + * timeout, and return 1 or 0 respectively. From a user perspective, just + * keep trying to send the same data. The library will keep auto retrying + * the current payload using the built in functionality. + * @warning It is important to never keep the nRF24L01 in TX mode for more than 4ms at a time. If the auto + * retransmit is enabled, the nRF24L01 is never in TX mode long enough to disobey this rule. Allow the FIFO + * to clear by issuing txStandBy() or ensure appropriate time between transmissions. + * + * ONLY max retry interrupt flags will be cleared when writeFast is called + * + * @code + * Example (Partial blocking): + * + * radio.writeFast(&buf,32); // Writes 1 payload to the buffers + * txStandBy(); // Returns 0 if failed. 1 if success. Blocks only until MAX_RT timeout or success. Data flushed on fail. + * + * radio.writeFast(&buf,32); // Writes 1 payload to the buffers + * txStandBy(1000); // Using extended timeouts, returns 1 if success. Retries failed payloads for 1 seconds before returning 0. + * @endcode + * + * @see txStandBy() + * @see write() + * @see writeBlocking() + * + * @param buf Pointer to the data to be sent + * @param len Number of bytes to be sent + * @return True if the payload was delivered successfully false if not + */ + bool writeFast( const void* buf, uint8_t len ); + + /** + * WriteFast for single NOACK writes. Disables acknowledgements/autoretries for a single write. + * + * @note enableDynamicAck() must be called to enable this feature + * @see enableDynamicAck() + * @see setAutoAck() + * + * @param buf Pointer to the data to be sent + * @param len Number of bytes to be sent + * @param multicast Request ACK (0) or NOACK (1) + */ + bool writeFast( const void* buf, uint8_t len, const bool multicast ); + + /** + * @note Optimization: New Command + * This function extends the auto-retry mechanism to any specified duration. + * It will not block until the 3 FIFO buffers are filled with data. + * If so the library will auto retry until a new payload is written + * or the user specified timeout period is reached. + * @warning It is important to never keep the nRF24L01 in TX mode for more than 4ms at a time. If the auto + * retransmit is enabled, the nRF24L01 is never in TX mode long enough to disobey this rule. Allow the FIFO + * to clear by issuing txStandBy() or ensure appropriate time between transmissions. + * + * ONLY max retry interrupt flags will be cleared when writeBlocking is called + * @code + * Example (Full blocking): + * + * radio.writeBlocking(&buf,32,1000); //Wait up to 1 second to write 1 payload to the buffers + * txStandBy(1000); //Wait up to 1 second for the payload to send. Return 1 if ok, 0 if failed. + * //Blocks only until user timeout or success. Data flushed on fail. + * @endcode + * @note If used from within an interrupt, the interrupt should be disabled until completion, and sei(); called to enable millis(). + * @see txStandBy() + * @see write() + * @see writeFast() + * + * @param buf Pointer to the data to be sent + * @param len Number of bytes to be sent + * @param timeout User defined timeout in milliseconds. + * @return True if the payload was loaded into the buffer successfully false if not + */ + bool writeBlocking( const void* buf, uint8_t len, uint32_t timeout ); + + /** + * @note Optimization: New Command + * This function should be called as soon as transmission is finished to + * drop the radio back to STANDBY-I mode. If not issued, the radio will + * remain in STANDBY-II mode which, per the data sheet, is not a recommended + * operating mode. + * + * @note When transmitting data in rapid succession, it is still recommended by + * the manufacturer to drop the radio out of TX or STANDBY-II mode if there is + * time enough between sends for the FIFOs to empty. + * + * Relies on built-in auto retry functionality. + * + * @code + * Example (Partial blocking): + * + * radio.writeFast(&buf,32); + * radio.writeFast(&buf,32); + * radio.writeFast(&buf,32); //Fills the FIFO buffers up + * bool ok = txStandBy(); //Returns 0 if failed. 1 if success. + * //Blocks only until MAX_RT timeout or success. Data flushed on fail. + * @endcode + * @see txStandBy(unsigned long timeout) + * @return True if transmission is successful + * + */ + bool txStandBy(); + + /** + * @note Optimization: New Command + * + * This function allows extended blocking and auto-retries per a user defined timeout + * @code + * Fully Blocking Example: + * + * radio.writeFast(&buf,32); + * radio.writeFast(&buf,32); + * radio.writeFast(&buf,32); //Fills the FIFO buffers up + * bool ok = txStandBy(1000); //Returns 0 if failed after 1 second of retries. 1 if success. + * //Blocks only until user defined timeout or success. Data flushed on fail. + * @endcode + * @note If used from within an interrupt, the interrupt should be disabled until completion, and sei(); called to enable millis(). + * @param timeout Number of milliseconds to retry failed payloads + * @return True if transmission is successful + * + */ + bool txStandBy(uint32_t timeout); + + /** + * Write an ack payload for the specified pipe + * + * The next time a message is received on @p pipe, the data in @p buf will + * be sent back in the acknowledgement. + * + * @warning According to the data sheet, only three of these can be pending + * at any time as there are only 3 FIFO buffers. + * + * @param pipe Which pipe# (typically 1-5) will get this response. + * @param buf Pointer to data that is sent + * @param len Length of the data to send, up to 32 bytes max. Not affected + * by the static payload set by setPayloadSize(). + */ + void writeAckPayload(uint8_t pipe, const void* buf, uint8_t len); + + /** + * Enable dynamic ACKs (single write multicasting) for chosen messages + * + * @note To enable full multicasting or per-pipe multicast, use setAutoAck() + * + * @warning This MUST be called prior to attempting single write NOACK calls + * @code + * radio.enableDynamicAck(); + * radio.write(&data,32,1); // Sends a payload with no acknowledgement requested + * radio.write(&data,32,0); // Sends a payload using auto-retry/autoACK + * @endcode + */ + void enableDynamicAck(); + + /** + * Determine if an ack payload was received in the most recent call to + * write(). + * + * Call read() to retrieve the ack payload. + * + * @note Optimization: Calling this function NO LONGER clears the interrupt + * flag. The new functionality checks the RX FIFO buffer for an ACK payload + * instead of relying on interrupt flags.Reading the payload will clear the flags. + * + * @return True if an ack payload is available. + */ + bool isAckPayloadAvailable(void); + + /** + * Call this when you get an interrupt to find out why + * + * Tells you what caused the interrupt, and clears the state of + * interrupts. + * + * @param[out] tx_ok The send was successful (TX_DS) + * @param[out] tx_fail The send failed, too many retries (MAX_RT) + * @param[out] rx_ready There is a message waiting to be read (RX_DS) + */ + void whatHappened(bool& tx_ok,bool& tx_fail,bool& rx_ready); + + /** + * Non-blocking write to the open writing pipe used for buffered writes + * + * @note Optimization: This function now leaves the CE pin high, so the radio + * will remain in TX or STANDBY-II Mode until a txStandBy() command is issued. + * This allows the chip to be used to its full potential in TX mode. + * @warning It is important to never keep the nRF24L01 in TX mode for more than 4ms at a time. If the auto + * retransmit is enabled, the nRF24L01 is never in TX mode long enough to disobey this rule. Allow the FIFO + * to clear by issuing txStandBy() or ensure appropriate time between transmissions. + * + * @see write() + * @see writeFast() + * @see startWrite() + * @see writeBlocking() + * + * For single noAck writes see: + * @see enableDynamicAck() + * @see setAutoAck() + * + * @param buf Pointer to the data to be sent + * @param len Number of bytes to be sent + * @param multicast Request ACK (0) or NOACK (1) + * @return True if the payload was delivered successfully false if not + */ + void startFastWrite( const void* buf, uint8_t len, const bool multicast ); + + /** + * Non-blocking write to the open writing pipe + * + * Just like write(), but it returns immediately. To find out what happened + * to the send, catch the IRQ and then call whatHappened(). + * + * @note Optimization: This function again behaves as it did previously for backwards-compatibility. + * with user code. The library uses startFastWrite() internally. + * This is mainly used for single-payload transactions. + * + * @see write() + * @see writeFast() + * @see startFastWrite() + * @see whatHappened() + * + * For single noAck writes see: + * @see enableDynamicAck() + * @see setAutoAck() + * + * @param buf Pointer to the data to be sent + * @param len Number of bytes to be sent + * @param multicast Request ACK (0) or NOACK (1) + * + */ + void startWrite( const void* buf, uint8_t len, const bool multicast ); + + /** + * Optimization: New Command + * + * This function is mainly used internally to take advantage of the auto payload + * re-use functionality of the chip, but can be beneficial to users as well. + * + * The function will instruct the radio to re-use the data in the FIFO buffers, + * and instructs the radio to re-send once the timeout limit has been reached. + * Used by writeFast and writeBlocking to initiate retries when a TX failure + * occurs. Retries are automatically initiated except with the standard write(). + * This way, data is not flushed from the buffer until switching between modes. + * + * @note This is to be used AFTER auto-retry fails if wanting to resend + * using the built-in payload reuse features. + * After issuing reUseTX(), it will keep reending the same payload forever or until + * a payload is written to the FIFO, or a flush_tx command is given. + */ + void reUseTX(); + + /** + * Empty the transmit buffer + * + * @return Current value of status register + */ + uint8_t flush_tx(void); + + /** + * Test whether there was a carrier on the line for the + * previous listening period. + * + * Useful to check for interference on the current channel. + * + * @return true if was carrier, false if not + */ + bool testCarrier(void); + + /** + * Test whether a signal (carrier or otherwise) greater than + * or equal to -64dBm is present on the channel. Valid only + * on nRF24L01P (+) hardware. On nRF24L01, use testCarrier(). + * + * Useful to check for interference on the current channel and + * channel hopping strategies. + * + * @return true if signal => -64dBm, false if not + */ + bool testRPD(void) ; + + /** + * Test whether this is a real radio, or a mock shim for + * debugging. Setting either pin to 0xff is the way to + * indicate that this is not a real radio. + * + * @return true if this is a legitimate radio + */ + bool isValid() { return ce_pin != 0xff && csn_pin != 0xff; } + + /** + * The radio will generate interrupt signals when a transmission is complete, + * a transmission fails, or a payload is received. This allows users to mask + * those interrupts to prevent them from generating a signal on the interrupt + * pin. + * + * @code + * Mask all interrupts except the receive interrupt: + * + * radio.maskIRQ(1,1,0); + * @endcode + * + * @param tx_ok Mask transmission complete interrupts + * @param tx_fail Mask transmit failure interrupts + * @param rx_ready Mask payload received interrupts + */ + void maskIRQ(bool tx_ok,bool tx_fail,bool rx_ready); + + /** + * Set the address width from 3 to 5 bytes (24, 32 or 40 bit) + * + * @param a_width The address width to use: 3,4 or 5 + */ + + void setAddressWidth(uint8_t a_width); + + /**@}*/ + + /**@}*/ + /** + * @name Optional Configurators + * + * Methods you can use to get or set the configuration of the chip. + * None are required. Calling begin() sets up a reasonable set of + * defaults. + */ + /**@{*/ + + /** + * Set the number and delay of retries upon failed submit + * + * @param delay How long to wait between each retry, in multiples of 250us, + * max is 15. 0 means 250us, 15 means 4000us. + * @param count How many retries before giving up, max 15 + */ + void setRetries(uint8_t delay, uint8_t count); + + /** + * Set RF communication channel + * + * @param channel Which RF channel to communicate on, 0-127 + */ + void setChannel(uint8_t channel); + + /** + * Set Static Payload Size + * + * This implementation uses a pre-stablished fixed payload size for all + * transmissions. If this method is never called, the driver will always + * transmit the maximum payload size (32 bytes), no matter how much + * was sent to write(). + * + * @todo Implement variable-sized payloads feature + * + * @param size The number of bytes in the payload + */ + void setPayloadSize(uint8_t size); + + /** + * Get Static Payload Size + * + * @see setPayloadSize() + * + * @return The number of bytes in the payload + */ + uint8_t getPayloadSize(void); + + /** + * Get Dynamic Payload Size + * + * For dynamic payloads, this pulls the size of the payload off + * the chip + * + * @note Optimization: Corrupt packets are now detected and flushed per the + * manufacturer. + * + * @return Payload length of last-received dynamic payload + */ + uint8_t getDynamicPayloadSize(void); + + /** + * Enable custom payloads on the acknowledge packets + * + * Ack payloads are a handy way to return data back to senders without + * manually changing the radio modes on both units. + * + * @see examples/pingpair_pl/pingpair_pl.pde + */ + void enableAckPayload(void); + + /** + * Enable dynamically-sized payloads + * + * This way you don't always have to send large packets just to send them + * once in a while. This enables dynamic payloads on ALL pipes. + * + * @see examples/pingpair_pl/pingpair_dyn.pde + */ + void enableDynamicPayloads(void); + + /** + * Determine whether the hardware is an nRF24L01+ or not. + * + * @return true if the hardware is nRF24L01+ (or compatible) and false + * if its not. + */ + bool isPVariant(void) ; + + /** + * Enable or disable auto-acknowlede packets + * + * This is enabled by default, so it's only needed if you want to turn + * it off for some reason. + * + * @param enable Whether to enable (true) or disable (false) auto-acks + */ + void setAutoAck(bool enable); + + /** + * Enable or disable auto-acknowlede packets on a per pipeline basis. + * + * AA is enabled by default, so it's only needed if you want to turn + * it off/on for some reason on a per pipeline basis. + * + * @param pipe Which pipeline to modify + * @param enable Whether to enable (true) or disable (false) auto-acks + */ + void setAutoAck( uint8_t pipe, bool enable ) ; + + /** + * Set Power Amplifier (PA) level to one of four levels: + * RF24_PA_MIN, RF24_PA_LOW, RF24_PA_HIGH and RF24_PA_MAX + * + * The power levels correspond to the following output levels respectively: + * NRF24L01: -18dBm, -12dBm,-6dBM, and 0dBm + * + * SI24R1: -6dBm, 0dBm, 3dBM, and 7dBm. + * + * @param level Desired PA level. + */ + void setPALevel ( uint8_t level ); + + /** + * Fetches the current PA level. + * + * NRF24L01: -18dBm, -12dBm, -6dBm and 0dBm + * SI24R1: -6dBm, 0dBm, 3dBm, 7dBm + * + * @return Returns values 0 to 3 representing the PA Level. + */ + uint8_t getPALevel( void ); + + /** + * Set the transmission data rate + * + * @warning setting RF24_250KBPS will fail for non-plus units + * + * @param speed RF24_250KBPS for 250kbs, RF24_1MBPS for 1Mbps, or RF24_2MBPS for 2Mbps + * @return true if the change was successful + */ + bool setDataRate(rf24_datarate_e speed); + + /** + * Fetches the transmission data rate + * + * @return Returns the hardware's currently configured datarate. The value + * is one of 250kbs, RF24_1MBPS for 1Mbps, or RF24_2MBPS, as defined in the + * rf24_datarate_e enum. + */ + rf24_datarate_e getDataRate( void ) ; + + /** + * Set the CRC length + * + * @param length RF24_CRC_8 for 8-bit or RF24_CRC_16 for 16-bit + */ + void setCRCLength(rf24_crclength_e length); + + /** + * Get the CRC length + * + * @return RF24_DISABLED if disabled or RF24_CRC_8 for 8-bit or RF24_CRC_16 for 16-bit + */ + rf24_crclength_e getCRCLength(void); + + /** + * Disable CRC validation + * + */ + void disableCRC( void ) ; + + /** + * Enable error detection by un-commenting #define FAILURE_HANDLING in RF24_config.h + * If a failure has been detected, it usually indicates a hardware issue. By default the library + * will cease operation when a failure is detected. + * This should allow advanced users to detect and resolve intermittent hardware issues. + * + * In most cases, the radio must be re-enabled via radio.begin(); and the appropriate settings + * applied after a failure occurs, if wanting to re-enable the device immediately. + * + * Usage: (Failure handling must be enabled per above) + * @code + * if(radio.failureDetected){ + * radio.begin(); // Attempt to re-configure the radio with defaults + * radio.failureDetected = 0; // Reset the detection value + * radio.openWritingPipe(addresses[1]); // Re-configure pipe addresses + * radio.openReadingPipe(1,addresses[0]); + * report_failure(); // Blink leds, send a message, etc. to indicate failure + * } + * @endcode + */ + #if defined (FAILURE_HANDLING) + bool failureDetected; + #endif + /**@}*/ + /** + * @name Deprecated + * + * Methods provided for backwards compabibility. + */ + /**@{*/ + + + /** + * Open a pipe for reading + * @note For compatibility with old code only, see new function + * + * @warning Pipes 1-5 should share the first 32 bits. + * Only the least significant byte should be unique, e.g. + * @code + * openReadingPipe(1,0xF0F0F0F0AA); + * openReadingPipe(2,0xF0F0F0F066); + * @endcode + * + * @warning Pipe 0 is also used by the writing pipe. So if you open + * pipe 0 for reading, and then startListening(), it will overwrite the + * writing pipe. Ergo, do an openWritingPipe() again before write(). + * + * @param number Which pipe# to open, 0-5. + * @param address The 40-bit address of the pipe to open. + */ + void openReadingPipe(uint8_t number, uint64_t address); + + /** + * Open a pipe for writing + * @note For compatibility with old code only, see new function + * Addresses are 40-bit hex values, e.g.: + * + * @code + * openWritingPipe(0xF0F0F0F0F0); + * @endcode + * + * @param address The 40-bit address of the pipe to open. + */ + void openWritingPipe(uint64_t address); + +private: + + /** + * @name Low-level internal interface. + * + * Protected methods that address the chip directly. Regular users cannot + * ever call these. They are documented for completeness and for developers who + * may want to extend this class. + */ + /**@{*/ + + /** + * Set chip select pin + * + * Running SPI bus at PI_CLOCK_DIV2 so we don't waste time transferring data + * and best of all, we make use of the radio's FIFO buffers. A lower speed + * means we're less likely to effectively leverage our FIFOs and pay a higher + * AVR runtime cost as toll. + * + * @param mode HIGH to take this unit off the SPI bus, LOW to put it on + */ + void csn(bool mode); + + /** + * Set chip enable + * + * @param level HIGH to actively begin transmission or LOW to put in standby. Please see data sheet + * for a much more detailed description of this pin. + */ + void ce(bool level); + + /** + * Read a chunk of data in from a register + * + * @param reg Which register. Use constants from nRF24L01.h + * @param buf Where to put the data + * @param len How many bytes of data to transfer + * @return Current value of status register + */ + uint8_t read_register(uint8_t reg, uint8_t* buf, uint8_t len); + + /** + * Read single byte from a register + * + * @param reg Which register. Use constants from nRF24L01.h + * @return Current value of register @p reg + */ + uint8_t read_register(uint8_t reg); + + /** + * Write a chunk of data to a register + * + * @param reg Which register. Use constants from nRF24L01.h + * @param buf Where to get the data + * @param len How many bytes of data to transfer + * @return Current value of status register + */ + uint8_t write_register(uint8_t reg, const uint8_t* buf, uint8_t len); + + /** + * Write a single byte to a register + * + * @param reg Which register. Use constants from nRF24L01.h + * @param value The new value to write + * @return Current value of status register + */ + uint8_t write_register(uint8_t reg, uint8_t value); + + /** + * Write the transmit payload + * + * The size of data written is the fixed payload size, see getPayloadSize() + * + * @param buf Where to get the data + * @param len Number of bytes to be sent + * @return Current value of status register + */ + uint8_t write_payload(const void* buf, uint8_t len, const uint8_t writeType); + + /** + * Read the receive payload + * + * The size of data read is the fixed payload size, see getPayloadSize() + * + * @param buf Where to put the data + * @param len Maximum number of bytes to read + * @return Current value of status register + */ + uint8_t read_payload(void* buf, uint8_t len); + + /** + * Empty the receive buffer + * + * @return Current value of status register + */ + uint8_t flush_rx(void); + + /** + * Retrieve the current status of the chip + * + * @return Current value of status register + */ + uint8_t get_status(void); + + /** + * Decode and print the given status to stdout + * + * @param status Status value to print + * + * @warning Does nothing if stdout is not defined. See fdevopen in stdio.h + */ + void print_status(uint8_t status); + + /** + * Decode and print the given 'observe_tx' value to stdout + * + * @param value The observe_tx value to print + * + * @warning Does nothing if stdout is not defined. See fdevopen in stdio.h + */ + void print_observe_tx(uint8_t value); + + /** + * Print the name and value of an 8-bit register to stdout + * + * Optionally it can print some quantity of successive + * registers on the same line. This is useful for printing a group + * of related registers on one line. + * + * @param name Name of the register + * @param reg Which register. Use constants from nRF24L01.h + * @param qty How many successive registers to print + */ + void print_byte_register(const char* name, uint8_t reg, uint8_t qty = 1); + + /** + * Print the name and value of a 40-bit address register to stdout + * + * Optionally it can print some quantity of successive + * registers on the same line. This is useful for printing a group + * of related registers on one line. + * + * @param name Name of the register + * @param reg Which register. Use constants from nRF24L01.h + * @param qty How many successive registers to print + */ + void print_address_register(const char* name, uint8_t reg, uint8_t qty = 1); + + /** + * Turn on or off the special features of the chip + * + * The chip has certain 'features' which are only available when the 'features' + * are enabled. See the datasheet for details. + */ + void toggle_features(void); + + /** + * Built in spi transfer function to simplify repeating code repeating code + */ + + uint8_t spiTrans(uint8_t cmd); + + #if defined (FAILURE_HANDLING) + void errNotify(void); + #endif + + /**@}*/ + +}; + +/** + * @example GettingStarted.ino + * Updated: TMRh20 2014
+ * + * This is an example of how to use the RF24 class to communicate on a basic level. Write this sketch to two + * different nodes. Put one of the nodes into 'transmit' mode by connecting with the serial monitor and
+ * sending a 'T'. The ping node sends the current time to the pong node, which responds by sending the value + * back. The ping node can then see how long the whole cycle took.
+ * @note For a more efficient call-response scenario see the GettingStarted_CallResponse.ino example. + * @note When switching between sketches, the radio may need to be powered down to clear settings that are not "un-set" otherwise + */ + +/** + * @example GettingStarted_CallResponse.ino + * New: TMRh20 2014
+ * + * This example continues to make use of all the normal functionality of the radios including + * the auto-ack and auto-retry features, but allows ack-payloads to be written optionlly as well.
+ * This allows very fast call-response communication, with the responding radio never having to + * switch out of Primary Receiver mode to send back a payload, but having the option to switch to
+ * primary transmitter if wanting to initiate communication instead of respond to a commmunication. + */ + +/** + * @example Transfer.ino + * New: TMRh20
+ * This example demonstrates half-rate transfer using the FIFO buffers
+ * + * It is an example of how to use the RF24 class. Write this sketch to two + * different nodes. Put one of the nodes into 'transmit' mode by connecting
+ * with the serial monitor and sending a 'T'. The data transfer will begin, + * with the receiver displaying the payload count. (32Byte Payloads)
+ */ + +/** + * @example TransferTimeouts.ino + * New: TMRh20
+ * This example demonstrates the use of and extended timeout period and + * auto-retries/auto-reUse to increase reliability in noisy or low signal scenarios.
+ * + * Write this sketch to two different nodes. Put one of the nodes into 'transmit' + * mode by connecting with the serial monitor and sending a 'T'. The data
+ * transfer will begin, with the receiver displaying the payload count and the + * data transfer rate. + */ + +/** + * @example starping.pde + * + * This sketch is a more complex example of using the RF24 library for Arduino. + * Deploy this on up to six nodes. Set one as the 'pong receiver' by tying the + * role_pin low, and the others will be 'ping transmit' units. The ping units + * unit will send out the value of millis() once a second. The pong unit will + * respond back with a copy of the value. Each ping unit can get that response + * back, and determine how long the whole cycle took. + * + * This example requires a bit more complexity to determine which unit is which. + * The pong receiver is identified by having its role_pin tied to ground. + * The ping senders are further differentiated by a byte in eeprom. + */ + +/** + * @example pingpair_ack.ino + * Update: TMRh20
+ * This example continues to make use of all the normal functionality of the radios including + * the auto-ack and auto-retry features, but allows ack-payloads to be written optionlly as well.
+ * This allows very fast call-response communication, with the responding radio never having to + * switch out of Primary Receiver mode to send back a payload, but having the option to if wanting
+ * to initiate communication instead of respond to a commmunication. + */ + +/** + * @example pingpair_irq.ino + * Update: TMRh20
+ * This is an example of how to user interrupts to interact with the radio, and a demonstration + * of how to use them to sleep when receiving, and not miss any payloads.
+ * The pingpair_sleepy example expands on sleep functionality with a timed sleep option for the transmitter. + * Sleep functionality is built directly into my fork of the RF24Network library
+ */ + +/** + * @example pingpair_sleepy.ino + * Update: TMRh20
+ * This is an example of how to use the RF24 class to create a battery- + * efficient system. It is just like the GettingStarted_CallResponse example, but the
+ * ping node powers down the radio and sleeps the MCU after every + * ping/pong cycle, and the receiver sleeps between payloads.
+ */ + +/** + * @example pingpair_dyn.ino + * + * This is an example of how to use payloads of a varying (dynamic) size. + */ + +/** + * @example pingpair_maple.pde + * + * This is an example of how to use the RF24 class on the Maple. For a more + * detailed explanation, see my blog post: + * nRF24L01+ Running on Maple + * + * It will communicate well to an Arduino-based unit as well, so it's not for only Maple-to-Maple communication. + * + * Write this sketch to two different nodes, + * connect the role_pin to ground on one. The ping node sends the current time to the pong node, + * which responds by sending the value back. The ping node can then see how long the whole cycle + * took. + */ + +/** + * @example nordic_fob.pde + * + * This is an example of how to use the RF24 class to receive signals from the + * Sparkfun Nordic FOB. See http://www.sparkfun.com/products/8602 . + * Thanks to Kirk Mower for providing test hardware. + */ + +/** + * @example led_remote.pde + * + * This is an example of how to use the RF24 class to control a remote + * bank of LED's using buttons on a remote control. + * + * Every time the buttons change on the remote, the entire state of + * buttons is send to the led board, which displays the state. + */ + +/** + * @example scanner.ino + * + * Example to detect interference on the various channels available. + * This is a good diagnostic tool to check whether you're picking a + * good channel for your application. + * + * Inspired by cpixip. + * See http://arduino.cc/forum/index.php/topic,54795.0.html + */ + +/** + * @mainpage Optimized High Speed Driver for nRF24L01(+) 2.4GHz Wireless Transceiver + * + * @section Goals Design Goals + * + * This library fork is designed to be... + * @li More compliant with the manufacturer specified operation of the chip, while allowing advanced users + * to work outside the recommended operation. + * @li Utilize the capabilities of the radio to their full potential via Arduino + * @li More reliable, responsive and feature rich + * @li Easy for beginners to use, with well documented examples and features + * @li Consumed with a public interface that's similiar to other Arduino standard libraries + * + * @section News News + * + * Main changes:
+ * - The library has been tweaked to allow full use of the FIFO buffers for maximum transfer speeds + * - Changes to read() and available () functionality have increased reliability and response + * - Extended timeout periods have been added to aid in noisy or otherwise unreliable environments + * - Delays have been removed where possible to ensure maximum efficiency + * - Full Due support with extended SPI functions + * - ATTiny now supported. + * - Raspberry Pi now supported + * - More! See the links below and class documentation for more info. + * + * If issues are discovered with the documentation, please report them here + * @section Useful Useful References + * + * Please refer to: + * + * @li Documentation Main Page + * @li RF24 Class Documentation + * @li Source Code + * @li Download + * @li Chip Datasheet + * @li Original Library + * + * This chip uses the SPI bus, plus two chip control pins. Remember that pin 10 must still remain an output, or + * the SPI hardware will go into 'slave' mode. + * + * @section Board_Support Board Support + * + * Most standard Arduino based boards are supported: + * - ATMega 328 based boards (Uno, Nano, etc) + * - Mega Boards (1280, 2560, etc) + * - Arduino Due: Must use one of the hardware SS/CSN pins as extended SPI methods are used. + * Initial Due support taken from https://github.com/mcrosson/RF24/tree/due + * - ATTiny board support added from https://github.com/jscrane/RF24 + * Note: ATTiny support is built into the library. Do not include SPI.h.
+ * ATTiny 85: D0(pin 5): MISO, D1(pin6) MOSI, D2(pin7) SCK, D3(pin2):CSN/SS, D4(pin3): CE
+ * ATTiny 84: PA6:MISO, PA5:MOSI, PA4:SCK, PA7:CSN/SS, CE as desired
+ * See https://github.com/TCWORLD/ATTinyCore/tree/master/PCREL%20Patch%20for%20GCC for ATTiny patch + * - Raspberry Pi Support: See the readme at https://github.com/TMRh20/RF24/tree/master/RPi + * + * @section More More Information + * + * @section Info and Projects + * + * @li Project blog: + * @li TMRh20.blogspot.com + * @li RF24 Wireless Audio Library + * @li Optimized RF24 Network Layer + * @li ManiacBug on GitHub (Original Library Author) + */ + +#endif // __RF24_H__ + + diff --git a/RC_Turrel/libraries/RF24-master/RF24_config.h b/RC_Turrel/libraries/RF24-master/RF24_config.h new file mode 100644 index 0000000..28d912c --- /dev/null +++ b/RC_Turrel/libraries/RF24-master/RF24_config.h @@ -0,0 +1,149 @@ + +/* + Copyright (C) 2011 J. Coliz + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Added Arduino Due support from https://github.com/mcrosson/ + */ + +#ifndef __RF24_CONFIG_H__ +#define __RF24_CONFIG_H__ + + #if ARDUINO < 100 + #include + #else + #include + #endif + + #include + + /*** USER DEFINES: ***/ + //#define FAILURE_HANDLING + //#define SERIAL_DEBUG + //#define MINIMAL + /**********************/ + + // Define _BV for non-Arduino platforms and for Arduino DUE +#if defined (ARDUINO) && !defined (__arm__) + #include +#else + + #include + #include + #include + + + #if defined(__arm__) || defined (CORE_TEENSY) + #include + #endif + + #if !defined(CORE_TEENSY) + #define _BV(x) (1<<(x)) + #if !defined(__arm__) + extern HardwareSPI SPI; + #endif + #endif + + +#endif + + + #ifdef SERIAL_DEBUG + #define IF_SERIAL_DEBUG(x) ({x;}) + #else + #define IF_SERIAL_DEBUG(x) + #if defined(__AVR_ATtiny84__) || defined(__AVR_ATtiny85__) + #define printf_P(...) + #endif + #endif + +// Avoid spurious warnings +// Arduino DUE is arm and uses traditional PROGMEM constructs +#if 1 +#if ! defined( NATIVE ) && defined( ARDUINO ) && ! defined(__arm__) && ! defined( CORE_TEENSY3 ) +#undef PROGMEM +#define PROGMEM __attribute__(( section(".progmem.data") )) +#undef PSTR +#define PSTR(s) (__extension__({static const char __c[] PROGMEM = (s); &__c[0];})) +#endif +#endif + +// Progmem is Arduino-specific +// Arduino DUE is arm and does not include avr/pgmspace +#if defined(ARDUINO) && ! defined(__arm__) + #include + #define PRIPSTR "%S" +#else +#if ! defined(ARDUINO) // This doesn't work on Arduino DUE + typedef char const char; +#else // Fill in pgm_read_byte that is used, but missing from DUE + #define pgm_read_byte(addr) (*(const unsigned char *)(addr)) +#endif + + +#if !defined ( CORE_TEENSY ) + typedef uint16_t prog_uint16_t; + #define PSTR(x) (x) + #define printf_P printf + #define strlen_P strlen + #define PROGMEM + #define pgm_read_word(p) (*(p)) +#endif + + #define PRIPSTR "%s" + +#endif + + + +// ATTiny support code is from https://github.com/jscrane/RF24 + +#if defined(__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__) || defined(__AVR_ATtiny24__) || defined(__AVR_ATtiny44__) || defined(__AVR_ATtiny84__) +#include +#include +#include + +#define SPI_CLOCK_DIV4 0x00 +#define SPI_CLOCK_DIV16 0x01 +#define SPI_CLOCK_DIV64 0x02 +#define SPI_CLOCK_DIV128 0x03 +#define SPI_CLOCK_DIV2 0x04 +#define SPI_CLOCK_DIV8 0x05 +#define SPI_CLOCK_DIV32 0x06 +//#define SPI_CLOCK_DIV64 0x07 + +#define SPI_MODE0 0x00 +#define SPI_MODE1 0x04 +#define SPI_MODE2 0x08 +#define SPI_MODE3 0x0C + +#define SPI_MODE_MASK 0x0C // CPOL = bit 3, CPHA = bit 2 on SPCR +#define SPI_CLOCK_MASK 0x03 // SPR1 = bit 1, SPR0 = bit 0 on SPCR +#define SPI_2XCLOCK_MASK 0x01 // SPI2X = bit 0 on SPSR + + + +class SPIClass { +public: + static byte transfer(byte _data); + + // SPI Configuration methods + + inline static void attachInterrupt(); + inline static void detachInterrupt(); // Default + + static void begin(); // Default + static void end(); + + static void setBitOrder(uint8_t); + static void setDataMode(uint8_t); + static void setClockDivider(uint8_t); +}; +extern SPIClass SPI; + +#endif //ATTiny +#endif // __RF24_CONFIG_H__ + diff --git a/RC_Turrel/libraries/RF24-master/examples/GettingStarted/GettingStarted.ino b/RC_Turrel/libraries/RF24-master/examples/GettingStarted/GettingStarted.ino new file mode 100644 index 0000000..000ccdd --- /dev/null +++ b/RC_Turrel/libraries/RF24-master/examples/GettingStarted/GettingStarted.ino @@ -0,0 +1,137 @@ +/* + Copyright (C) 2011 J. Coliz + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. +//2014 - TMRh20 - Updated along with Optimized RF24 Library fork + */ + +/** + * Example for Getting Started with nRF24L01+ radios. + * + * This is an example of how to use the RF24 class to communicate on a basic level. Write this sketch to two + * different nodes. Put one of the nodes into 'transmit' mode by connecting with the serial monitor and + * sending a 'T'. The ping node sends the current time to the pong node, which responds by sending the value + * back. The ping node can then see how long the whole cycle took. + * Note: For a more efficient call-response scenario see the GettingStarted_CallResponse.ino example. + * Note: When switching between sketches, the radio may need to be powered down to clear settings that are not "un-set" otherwise + */ + + +#include +#include "nRF24L01.h" +#include "RF24.h" +#include "printf.h" + +// Hardware configuration: Set up nRF24L01 radio on SPI bus plus pins 9 & 10 +RF24 radio(7,8); + +byte addresses[][6] = {"1Node","2Node"}; + + +// Set up roles to simplify testing +boolean role; // The main role variable, holds the current role identifier +boolean role_ping_out = 1, role_pong_back = 0; // The two different roles. + +void setup() { + + + Serial.begin(57600); + printf_begin(); + printf("\n\rRF24/examples/GettingStarted/\n\r"); + printf("*** PRESS 'T' to begin transmitting to the other node\n\r"); + + // Setup and configure rf radio + radio.begin(); // Start up the radio + radio.setAutoAck(1); // Ensure autoACK is enabled + radio.setRetries(15,15); // Max delay between retries & number of retries + radio.openWritingPipe(addresses[1]); + radio.openReadingPipe(1,addresses[0]); + + radio.startListening(); // Start listening + radio.printDetails(); // Dump the configuration of the rf unit for debugging +} + +void loop(void){ + + +/****************** Ping Out Role ***************************/ + if (role == role_ping_out) { + + radio.stopListening(); // First, stop listening so we can talk. + + + printf("Now sending \n\r"); + + unsigned long time = micros(); // Take the time, and send it. This will block until complete + if (!radio.write( &time, sizeof(unsigned long) )){ printf("failed.\n\r"); } + + radio.startListening(); // Now, continue listening + + unsigned long started_waiting_at = micros(); // Set up a timeout period, get the current microseconds + boolean timeout = false; // Set up a variable to indicate if a response was received or not + + while ( ! radio.available() ){ // While nothing is received + if (micros() - started_waiting_at > 200000 ){ // If waited longer than 200ms, indicate timeout and exit while loop + timeout = true; + break; + } + } + + if ( timeout ){ // Describe the results + printf("Failed, response timed out.\n\r"); + }else{ + unsigned long got_time; // Grab the response, compare, and send to debugging spew + radio.read( &got_time, sizeof(unsigned long) ); + + // Spew it + printf("Sent %lu, Got response %lu, round-trip delay: %lu microseconds\n\r",time,got_time,micros()-got_time); + } + + // Try again 1s later + delay(1000); + } + +/****************** Pong Back Role ***************************/ + + if ( role == role_pong_back ) + { + if( radio.available()){ + unsigned long got_time; // Variable for the received timestamp + while (radio.available()) { // While there is data ready + radio.read( &got_time, sizeof(unsigned long) ); // Get the payload + } + + radio.stopListening(); // First, stop listening so we can talk + radio.write( &got_time, sizeof(unsigned long) ); // Send the final one back. + radio.startListening(); // Now, resume listening so we catch the next packets. + printf("Sent response %lu \n\r", got_time); + } + } + + +/****************** Change Roles via Serial Commands ***************************/ + + if ( Serial.available() ) + { + char c = toupper(Serial.read()); + if ( c == 'T' && role == role_pong_back ) + { + printf("*** CHANGING TO TRANSMIT ROLE -- PRESS 'R' TO SWITCH BACK\n\r"); + + role = role_ping_out; // Become the primary transmitter (ping out) + radio.openWritingPipe(addresses[0]); + radio.openReadingPipe(1,addresses[1]); + + } + else if ( c == 'R' && role == role_ping_out ) + { + printf("*** CHANGING TO RECEIVE ROLE -- PRESS 'T' TO SWITCH BACK\n\r"); + + role = role_pong_back; // Become the primary receiver (pong back) + radio.openWritingPipe(addresses[1]); + radio.openReadingPipe(1,addresses[0]); + } + } +} \ No newline at end of file diff --git a/RC_Turrel/libraries/RF24-master/examples/Serial_Chat/nRF24_Serial_Chat.ino b/RC_Turrel/libraries/RF24-master/examples/Serial_Chat/nRF24_Serial_Chat.ino new file mode 100644 index 0000000..8150677 --- /dev/null +++ b/RC_Turrel/libraries/RF24-master/examples/Serial_Chat/nRF24_Serial_Chat.ino @@ -0,0 +1,171 @@ +/* +nRF Serial Chat + +Date : 29 Sep 2015 +Author : Stanley Seow +e-mail : stanleyseow@gmail.com +Version : 1.00 +Desc : +I worte this simple interactive serial chat over nRF that can be used for both sender +and receiver as I swapped the TX & RX addr during read/write operation. + +It read input from Serial Monitor and display the output to the other side +Serial Monitor or 16x2 LCD (if available)... like a simple chat program. + +Max payload is 32 bytes for radio but the serialEvent will chopped the entire buffer +for next payload to be sent out sequentially. + +*/ + +#define I2C_LCD + +#ifdef I2C_LCD +#include +#include +LiquidCrystal_I2C lcd(0x3F,16,2); // set the LCD address to 0x27 for a 16 chars and 2 line display +//LiquidCrystal_I2C lcd(0x27,16,2); // set the LCD address to 0x27 for a 16 chars and 2 line display +#endif + +#include +#include "nRF24L01.h" +#include "RF24.h" +#include "printf.h" + + +RF24 radio(8,9); + +const uint64_t pipes[2] = { 0xDEDEDEDEE7LL, 0xDEDEDEDEE9LL }; + +boolean stringComplete = false; // whether the string is complete +static int dataBufferIndex = 0; +boolean stringOverflow = false; +char charOverflow = 0; + +char SendPayload[31] = ""; +char RecvPayload[31] = ""; +char serialBuffer[31] = ""; + +void setup(void) { + + Serial.begin(9600); + +#ifdef I2C_LCD + lcd.init(); + lcd.backlight(); + lcd.begin(16,2); + lcd.print("RF Chat V1.0"); + delay(500); + //lcd.clear(); +#endif + + printf_begin(); + radio.begin(); + + radio.setDataRate(RF24_250KBPS); + radio.setPALevel(RF24_PA_MAX); + radio.setChannel(70); + + radio.enableDynamicPayloads(); + radio.setRetries(15,15); + radio.setCRCLength(RF24_CRC_16); + + radio.openWritingPipe(pipes[0]); + radio.openReadingPipe(1,pipes[1]); + + radio.startListening(); + radio.printDetails(); + + Serial.println(); + Serial.println("RF Chat V01.0"); + delay(500); + lcd.clear(); +} + +void loop(void) { + + nRF_receive(); + serial_receive(); + +} // end loop() + +void serialEvent() { + while (Serial.available() > 0 ) { + char incomingByte = Serial.read(); + + if (stringOverflow) { + serialBuffer[dataBufferIndex++] = charOverflow; // Place saved overflow byte into buffer + serialBuffer[dataBufferIndex++] = incomingByte; // saved next byte into next buffer + stringOverflow = false; // turn overflow flag off + } else if (dataBufferIndex > 31) { + stringComplete = true; // Send this buffer out to radio + stringOverflow = true; // trigger the overflow flag + charOverflow = incomingByte; // Saved the overflow byte for next loop + dataBufferIndex = 0; // reset the bufferindex + break; + } + else if(incomingByte=='\n'){ + serialBuffer[dataBufferIndex] = 0; + stringComplete = true; + } else { + serialBuffer[dataBufferIndex++] = incomingByte; + serialBuffer[dataBufferIndex] = 0; + } + } // end while() +} // end serialEvent() + +void nRF_receive(void) { + int len = 0; + if ( radio.available() ) { + len = radio.getDynamicPayloadSize(); + radio.read(&RecvPayload,len); + delay(5); + + RecvPayload[len] = 0; // null terminate string + +#ifdef I2C_LCD + lcd.setCursor(0,0); + lcd.print("R: "); + lcd.setCursor(2,0); + lcd.print(RecvPayload); +#endif + Serial.print("R:"); + Serial.print(RecvPayload); + Serial.println(); + RecvPayload[0] = 0; // Clear the buffers + } + +} // end nRF_receive() + +void serial_receive(void){ + + if (stringComplete) { + strcat(SendPayload,serialBuffer); + // swap TX & Rx addr for writing + radio.openWritingPipe(pipes[1]); + radio.openReadingPipe(0,pipes[0]); + radio.stopListening(); + radio.write(&SendPayload,strlen(SendPayload)); + +#ifdef I2C_LCD + lcd.setCursor(0,1); + lcd.print("S: "); + lcd.setCursor(2,1); + lcd.print(SendPayload); +#endif + + Serial.print("S:"); + Serial.print(SendPayload); + Serial.println(); + stringComplete = false; + + // restore TX & Rx addr for reading + radio.openWritingPipe(pipes[0]); + radio.openReadingPipe(1,pipes[1]); + radio.startListening(); + SendPayload[0] = 0; + dataBufferIndex = 0; + } // endif +} // end serial_receive() + + + diff --git a/RC_Turrel/libraries/RF24-master/examples/Serial_Chat/printf.h b/RC_Turrel/libraries/RF24-master/examples/Serial_Chat/printf.h new file mode 100644 index 0000000..b2efd56 --- /dev/null +++ b/RC_Turrel/libraries/RF24-master/examples/Serial_Chat/printf.h @@ -0,0 +1,37 @@ +/* + Copyright (C) 2011 J. Coliz + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + */ + +/** + * @file printf.h + * + * Setup necessary to direct stdout to the Arduino Serial library, which + * enables 'printf' + */ + +#ifndef __PRINTF_H__ +#define __PRINTF_H__ + +#ifdef ARDUINO + +int serial_putc( char c, FILE * ) +{ + Serial.write( c ); + + return c; +} + +void printf_begin(void) +{ + fdevopen( &serial_putc, 0 ); +} + +#else +#error This example is only for use on Arduino. +#endif // ARDUINO + +#endif // __PRINTF_H__ diff --git a/RC_Turrel/libraries/RF24-master/examples/Transfer/Transfer.ino b/RC_Turrel/libraries/RF24-master/examples/Transfer/Transfer.ino new file mode 100644 index 0000000..4242327 --- /dev/null +++ b/RC_Turrel/libraries/RF24-master/examples/Transfer/Transfer.ino @@ -0,0 +1,152 @@ +/* +TMRh20 2014 + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + */ + +/** General Data Transfer Rate Test + * This example demonstrates basic data transfer functionality with the + updated library. This example will display the transfer rates acheived using + the slower form of high-speed transfer using blocking-writes. + */ + + +#include +#include "RF24.h" +#include "printf.h" + +/************* USER Configuration *****************************/ + // Hardware configuration +RF24 radio(8,9); // Set up nRF24L01 radio on SPI bus plus pins 8 & 9 + +/***************************************************************/ + +const uint64_t pipes[2] = { 0xABCDABCD71LL, 0x544d52687CLL }; // Radio pipe addresses for the 2 nodes to communicate. + +byte data[32]; //Data buffer for testing data transfer speeds + +unsigned long counter, rxTimer; //Counter and timer for keeping track transfer info +unsigned long startTime, stopTime; +bool TX=1,RX=0,role=0; + +void setup(void) { + + // The UNO Adapter uses pin 10 as Vcc + pinMode(10,OUTPUT); + digitalWrite(10,HIGH); + delay(500); + + Serial.begin(57600); + printf_begin(); + + radio.begin(); // Setup and configure rf radio + radio.setChannel(1); + radio.setPALevel(RF24_PA_MAX); + radio.setDataRate(RF24_1MBPS); + radio.setAutoAck(1); // Ensure autoACK is enabled + radio.setRetries(2,15); // Optionally, increase the delay between retries & # of retries + radio.setCRCLength(RF24_CRC_8); + radio.openWritingPipe(pipes[0]); + radio.openReadingPipe(1,pipes[1]); + + radio.startListening(); // Start listening + radio.printDetails(); // Dump the configuration of the rf unit for debugging + + printf("\n\rRF24/examples/Transfer Rates/\n\r"); + printf("*** PRESS 'T' to begin transmitting to the other node\n\r"); + + randomSeed(analogRead(0)); //Seed for random number generation + + for(int i=0; i<32; i++){ + data[i] = random(255); //Load the buffer with random data + } + radio.powerUp(); //Power up the radio +} + +void loop(void){ + + + if(role == TX){ + + delay(2000); + + printf("Initiating Basic Data Transfer\n\r"); + + + unsigned long cycles = 10000; //Change this to a higher or lower number. + + startTime = millis(); + unsigned long pauseTime = millis(); + + for(int i=0; i 3){ +// pauseTime = millis(); +// radio.txStandBy(); // Need to drop out of TX mode every 4ms if sending a steady stream of multicast data +// //delayMicroseconds(130); // This gives the PLL time to sync back up +// } + + } + + stopTime = millis(); + //This should be called to wait for completion and put the radio in standby mode after transmission, returns 0 if data still in FIFO (timed out), 1 if success + if(!radio.txStandBy()){ counter+=3; } //Standby, block only until FIFO empty or auto-retry timeout. Flush TX FIFO if failed + //radio.txStandBy(1000); //Standby, using extended timeout period of 1 second + + float numBytes = cycles*32; + float rate = numBytes / (stopTime - startTime); + + Serial.print("Transfer complete at "); Serial.print(rate); printf(" KB/s \n\r"); + Serial.print(counter); Serial.print(" of "); Serial.print(cycles); printf(" Packets Failed to Send\n\r"); + counter = 0; + + } + + + +if(role == RX){ + while(radio.available()){ + radio.read(&data,32); + counter++; + } + if(millis() - rxTimer > 1000){ + rxTimer = millis(); + float numBytes = (counter*32)/1000.0; + Serial.print("Rate: "); + Serial.print(numBytes); + printf("KB/s \n Payload Count: %d \n\r", counter); + counter = 0; + } + } + // + // Change roles + // + + if ( Serial.available() ) + { + char c = toupper(Serial.read()); + if ( c == 'T' && role == RX ) + { + printf("*** CHANGING TO TRANSMIT ROLE -- PRESS 'R' TO SWITCH BACK\n\r"); + radio.openWritingPipe(pipes[1]); + radio.openReadingPipe(1,pipes[0]); + radio.stopListening(); + role = TX; // Become the primary transmitter (ping out) + } + else if ( c == 'R' && role == TX ) + { + radio.openWritingPipe(pipes[0]); + radio.openReadingPipe(1,pipes[1]); + radio.startListening(); + printf("*** CHANGING TO RECEIVE ROLE -- PRESS 'T' TO SWITCH BACK\n\r"); + role = RX; // Become the primary receiver (pong back) + } + } +} diff --git a/RC_Turrel/libraries/RF24-master/examples/TransferTimeouts/TransferTimeouts.ino b/RC_Turrel/libraries/RF24-master/examples/TransferTimeouts/TransferTimeouts.ino new file mode 100644 index 0000000..65fce99 --- /dev/null +++ b/RC_Turrel/libraries/RF24-master/examples/TransferTimeouts/TransferTimeouts.ino @@ -0,0 +1,189 @@ +/* +TMRh20 2014 + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + */ + +/** Reliably transmitting large volumes of data with a low signal or in noisy environments + * This example demonstrates data transfer functionality with the use of auto-retry + and auto-reUse functionality enabled. This sketch demonstrates how a user can extend + the auto-retry functionality to any chosen time period, preventing data loss and ensuring + the consistency of data. + + This sketh demonstrates use of the writeBlocking() functionality, and extends the standard + retry functionality of the radio. Payloads will be auto-retried until successful or the + extended timeout period is reached. + */ + + + +#include +#include "nRF24L01.h" +#include "RF24.h" +#include "printf.h" + +/************* USER Configuration *****************************/ + +RF24 radio(48,49); // Set up nRF24L01 radio on SPI bus plus pins 7 & 8 +unsigned long timeoutPeriod = 3000; // Set a user-defined timeout period. With auto-retransmit set to (15,15) retransmission will take up to 60ms and as little as 7.5ms with it set to (1,15). + // With a timeout period of 1000, the radio will retry each payload for up to 1 second before giving up on the transmission and starting over + +/***************************************************************/ + +const uint64_t pipes[2] = { 0xABCDABCD71LL, 0x544d52687CLL }; // Radio pipe addresses for the 2 nodes to communicate. + +byte data[32]; //Data buffer + +volatile unsigned long counter; +unsigned long rxTimer,startTime, stopTime, payloads = 0; +bool TX=1,RX=0,role=0, transferInProgress = 0; + + +void setup(void) { + + Serial.begin(57600); + printf_begin(); + + radio.begin(); // Setup and configure rf radio + radio.setChannel(1); // Set the channel + radio.setPALevel(RF24_PA_LOW); // Set PA LOW for this demonstration. We want the radio to be as lossy as possible for this example. + radio.setDataRate(RF24_1MBPS); // Raise the data rate to reduce transmission distance and increase lossiness + radio.setAutoAck(1); // Ensure autoACK is enabled + radio.setRetries(2,15); // Optionally, increase the delay between retries. Want the number of auto-retries as high as possible (15) + radio.setCRCLength(RF24_CRC_16); // Set CRC length to 16-bit to ensure quality of data + radio.openWritingPipe(pipes[0]); // Open the default reading and writing pipe + radio.openReadingPipe(1,pipes[1]); + + radio.startListening(); // Start listening + radio.printDetails(); // Dump the configuration of the rf unit for debugging + + printf("\n\rRF24/examples/Transfer Rates/\n\r"); + printf("*** PRESS 'T' to begin transmitting to the other node\n\r"); + + randomSeed(analogRead(0)); //Seed for random number generation + for(int i=0; i<32; i++){ + data[i] = random(255); //Load the buffer with random data + } + radio.powerUp(); //Power up the radio + + +} + + + +void loop(void){ + + + if(role == TX){ + delay(2000); // Pause for a couple seconds between transfers + printf("Initiating Extended Timeout Data Transfer\n\r"); + + unsigned long cycles = 1000; // Change this to a higher or lower number. This is the number of payloads that will be sent. + + unsigned long transferCMD[] = {'H','S',cycles }; // Indicate to the other radio that we are starting, and provide the number of payloads that will be sent + radio.writeFast(&transferCMD,12); // Send the transfer command + if(radio.txStandBy(timeoutPeriod)){ // If transfer initiation was successful, do the following + + startTime = millis(); // For calculating transfer rate + boolean timedOut = 0; // Boolean for keeping track of failures + + for(int i=0; i timeoutPeriod){ // If no data available, check the timeout period + Serial.println("Transfer Failed"); // If per-payload timeout exceeeded, end the transfer + transferInProgress = 0; + }else + if(counter >= payloads){ // If the specified number of payloads is reached, transfer is completed + startTime = millis() - startTime; // Calculate the total time spent during transfer + float numBytes = counter*32; // Calculate the number of bytes transferred + Serial.print("Rate: "); // Print the transfer rate and number of payloads + Serial.print(numBytes/startTime); + Serial.println(" KB/s"); + printf("Payload Count: %d \n\r", counter); + transferInProgress = 0; // End the transfer as complete + } + } + + + } + + // + // Change roles + // + + if ( Serial.available() ) + { + char c = toupper(Serial.read()); + if ( c == 'T' && role == RX ) + { + printf("*** CHANGING TO TRANSMIT ROLE -- PRESS 'R' TO SWITCH BACK\n\r"); + radio.openWritingPipe(pipes[1]); + radio.openReadingPipe(1,pipes[0]); + radio.stopListening(); + role = TX; // Become the primary transmitter (ping out) + } + else if ( c == 'R' && role == TX ) + { + radio.openWritingPipe(pipes[0]); + radio.openReadingPipe(1,pipes[1]); + radio.startListening(); + printf("*** CHANGING TO RECEIVE ROLE -- PRESS 'T' TO SWITCH BACK\n\r"); + role = RX; // Become the primary receiver (pong back) + } + } +} + + diff --git a/RC_Turrel/libraries/RF24-master/examples/Usage/led_remote/Jamfile b/RC_Turrel/libraries/RF24-master/examples/Usage/led_remote/Jamfile new file mode 100644 index 0000000..901f8da --- /dev/null +++ b/RC_Turrel/libraries/RF24-master/examples/Usage/led_remote/Jamfile @@ -0,0 +1,206 @@ +PROJECT_NAME = $(PWD:B) ; +PROJECT_DIR = . ; +PROJECT_LIBS = SPI RF24 ; + +OUT_DIR = ojam ; +F_CPU = 16000000 ; +MCU = atmega328p ; +PORTS = /dev/tty.usbserial-A600eHIs /dev/tty.usbserial-A40081RP /dev/tty.usbserial-A9007LmI ; + +UPLOAD_RATE = 57600 ; +AVRDUDE_PROTOCOL = stk500v1 ; +COM = 33 ; + +# Host-specific overrides for locations +if $(OS) = MACOSX +{ +ARDUINO_VERSION = 22 ; +OLD_DIR = /opt/arduino-0021 ; +AVR_TOOLS_PATH = $(OLD_DIR)/hardware/tools/avr/bin ; +AVRDUDECONFIG_PATH = $(OLD_DIR)/hardware/tools/avr/etc ; +ARDUINO_DIR = /opt/Arduino ; +ARDUINO_AVR = /usr/lib/avr/include ; +} + +# Where is everything? +ARDUINO_VERSION ?= 22 ; +AVR_TOOLS_PATH ?= /usr/bin ; +ARDUINO_DIR ?= /opt/arduino-00$(ARDUINO_VERSION) ; +ARDUINO_AVR ?= $(ARDUINO_DIR)/hardware/tools/avr/avr/include/avr ; +AVRDUDECONFIG_PATH ?= $(ARDUINO_DIR)/hardware/tools ; +ARDUINO_CORE = $(ARDUINO_DIR)/hardware/arduino/cores/arduino ; +ARDUINO_LIB = $(ARDUINO_DIR)/libraries ; +SKETCH_LIB = $(HOME)/Source/Arduino/libraries ; +AVR_CC = $(AVR_TOOLS_PATH)/avr-gcc ; +AVR_CXX = $(AVR_TOOLS_PATH)/avr-g++ ; +AVR_LD = $(AVR_TOOLS_PATH)/avr-gcc ; +AVR_OBJCOPY = $(AVR_TOOLS_PATH)/avr-objcopy ; +AVRDUDE = $(AVR_TOOLS_PATH)/avrdude ; + +DEFINES = F_CPU=$(F_CPU)L ARDUINO=$(ARDUINO_VERSION) VERSION_H ; +CTUNING = -ffunction-sections -fdata-sections ; +CXXTUNING = -fno-exceptions -fno-strict-aliasing ; +CFLAGS = -Os -Wall -Wextra -mmcu=$(MCU) $(CTUNING) ; +CXXFLAGS = $(CFLAGS) $(CXXTUNING) ; +LDFLAGS = -Os -lm -Wl,--gc-sections -mmcu=atmega328p ; + +# Search everywhere for headers +HDRS = $(PROJECT_DIR) $(ARDUINO_AVR) $(ARDUINO_CORE) [ GLOB $(ARDUINO_LIB) $(SKETCH_LIB) : [^.]* ] ; + +# Grab everything from the core directory +CORE_MODULES = [ GLOB $(ARDUINO_CORE) : *.c *.cpp ] ; + +# Grab everything from libraries. To avoid this "grab everything" behaviour, you +# can specify specific modules to pick up in PROJECT_MODULES +LIB_MODULES = [ GLOB $(ARDUINO_LIB)/$(PROJECT_LIBS) $(SKETCH_LIB)/$(PROJECT_LIBS) : *.cpp ] ; + +# In addition to explicitly-specified program modules, pick up anything from the current +# dir. +PROJECT_MODULES += [ GLOB $(PROJECT_DIR) : *.c *.cpp *.pde ] ; + +# Shortcut for the out files +OUT = $(OUT_DIR)/$(PROJECT_NAME) ; + +# AvrDude setup +AVRDUDE_FLAGS = -V -F -D -C $(AVRDUDECONFIG_PATH)/avrdude.conf -p $(MCU) -c $(AVRDUDE_PROTOCOL) -b $(UPLOAD_RATE) ; + +rule GitVersion +{ + Always $(<) ; + Depends all : $(<) ; +} + +actions GitVersion +{ + echo "const char program_version[] = \"\\" > $(<) + git log -1 --pretty=format:%h >> $(<) + echo "\";" >> $(<) +} + +GitVersion version.h ; + +rule AvrCc +{ + Depends $(<) : $(>) ; + Depends $(<) : $(<:D) ; + Clean clean : $(<) ; + + CCHDRS on $(<) = [ on $(<) FIncludes $(HDRS) ] ; + CCDEFS on $(<) = [ on $(<) FDefines $(DEFINES) ] ; +} + +actions AvrCc +{ + $(AVR_CC) -c -o $(<) $(CCHDRS) $(CCDEFS) $(CFLAGS) $(>) +} + +rule AvrC++ +{ + Depends $(<) : $(>) ; + Depends $(<) : $(<:D) ; + Clean clean : $(<) ; + + CCHDRS on $(<) = [ on $(<) FIncludes $(HDRS) ] ; + CCDEFS on $(<) = [ on $(<) FDefines $(DEFINES) ] ; +} + +actions AvrC++ +{ + $(AVR_CXX) -c -o $(<) $(CCHDRS) $(CCDEFS) $(CXXFLAGS) $(>) +} + +rule Pde +{ + Depends $(<) : $(>) ; + Depends $(<) : $(<:D) ; + Clean clean : $(<) ; + +} + +actions Pde +{ + echo "#include " > $(<) + echo "#line 1 \"$(>)\"" >> $(<) + cat $(>) >> $(<) +} + +rule AvrPde +{ + local _CPP = $(OUT_DIR)/$(_I:B).cpp ; + Pde $(_CPP) : $(>) ; + AvrC++ $(<) : $(_CPP) ; +} + +rule AvrObject +{ + switch $(>:S) + { + case .c : AvrCc $(<) : $(>) ; + case .cpp : AvrC++ $(<) : $(>) ; + case .pde : AvrPde $(<) : $(>) ; + } +} + +rule AvrObjects +{ + for _I in $(<) + { + AvrObject $(OUT_DIR)/$(_I:B).o : $(_I) ; + } +} + +rule AvrMainFromObjects +{ + Depends $(<) : $(>) ; + Depends $(<) : $(<:D) ; + MkDir $(<:D) ; + Depends all : $(<) ; + Clean clean : $(<) ; +} + +actions AvrMainFromObjects +{ + $(AVR_LD) $(LDFLAGS) -o $(<) $(>) +} + +rule AvrMain +{ + AvrMainFromObjects $(<) : $(OUT_DIR)/$(>:B).o ; + AvrObjects $(>) ; +} + +rule AvrHex +{ + Depends $(<) : $(>) ; + Depends $(<) : $(<:D) ; + Depends hex : $(<) ; + Clean clean : $(<) ; +} + +actions AvrHex +{ + $(AVR_OBJCOPY) -O ihex -R .eeprom $(>) $(<) +} + +rule AvrUpload +{ + Depends $(1) : $(2) ; + Depends $(2) : $(3) ; + NotFile $(1) ; + Always $(1) ; + Always $(2) ; + AvrUploadAction $(2) : $(3) ; +} + +actions AvrUploadAction +{ + $(AVRDUDE) $(AVRDUDE_FLAGS) -P $(<) $(AVRDUDE_WRITE_FLASH) -U flash:w:$(>):i +} + +AvrMain $(OUT).elf : $(CORE_MODULES) $(LIB_MODULES) $(PROJECT_MODULES) ; +AvrHex $(OUT).hex : $(OUT).elf ; + +AvrUpload p6 : /dev/tty.usbserial-A600eHIs : $(OUT).hex ; +AvrUpload p4 : /dev/tty.usbserial-A40081RP : $(OUT).hex ; +AvrUpload p9 : /dev/tty.usbserial-A9007LmI : $(OUT).hex ; + diff --git a/RC_Turrel/libraries/RF24-master/examples/Usage/led_remote/led_remote.pde b/RC_Turrel/libraries/RF24-master/examples/Usage/led_remote/led_remote.pde new file mode 100644 index 0000000..e4ba6d7 --- /dev/null +++ b/RC_Turrel/libraries/RF24-master/examples/Usage/led_remote/led_remote.pde @@ -0,0 +1,254 @@ +/* + Copyright (C) 2011 J. Coliz + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + */ + +/** + * Example LED Remote + * + * This is an example of how to use the RF24 class to control a remote + * bank of LED's using buttons on a remote control. + * + * On the 'remote', connect any number of buttons or switches from + * an arduino pin to ground. Update 'button_pins' to reflect the + * pins used. + * + * On the 'led' board, connect the same number of LED's from an + * arduino pin to a resistor to ground. Update 'led_pins' to reflect + * the pins used. Also connect a separate pin to ground and change + * the 'role_pin'. This tells the sketch it's running on the LED board. + * + * Every time the buttons change on the remote, the entire state of + * buttons is send to the led board, which displays the state. + */ + +#include +#include "RF24.h" +#include "printf.h" + +// +// Hardware configuration +// + +// Set up nRF24L01 radio on SPI bus plus pins 9 & 10 + +RF24 radio(9,10); + +// sets the role of this unit in hardware. Connect to GND to be the 'led' board receiver +// Leave open to be the 'remote' transmitter +const int role_pin = A4; + +// Pins on the remote for buttons +const uint8_t button_pins[] = { 2,3,4,5,6,7 }; +const uint8_t num_button_pins = sizeof(button_pins); + +// Pins on the LED board for LED's +const uint8_t led_pins[] = { 2,3,4,5,6,7 }; +const uint8_t num_led_pins = sizeof(led_pins); + +// +// Topology +// + +// Single radio pipe address for the 2 nodes to communicate. +const uint64_t pipe = 0xE8E8F0F0E1LL; + +// +// Role management +// +// Set up role. This sketch uses the same software for all the nodes in this +// system. Doing so greatly simplifies testing. The hardware itself specifies +// which node it is. +// +// This is done through the role_pin +// + +// The various roles supported by this sketch +typedef enum { role_remote = 1, role_led } role_e; + +// The debug-friendly names of those roles +const char* role_friendly_name[] = { "invalid", "Remote", "LED Board"}; + +// The role of the current running sketch +role_e role; + +// +// Payload +// + +uint8_t button_states[num_button_pins]; +uint8_t led_states[num_led_pins]; + +// +// Setup +// + +void setup(void) +{ + // + // Role + // + + // set up the role pin + pinMode(role_pin, INPUT); + digitalWrite(role_pin,HIGH); + delay(20); // Just to get a solid reading on the role pin + + // read the address pin, establish our role + if ( digitalRead(role_pin) ) + role = role_remote; + else + role = role_led; + + // + // Print preamble + // + + Serial.begin(57600); + printf_begin(); + printf("\n\rRF24/examples/led_remote/\n\r"); + printf("ROLE: %s\n\r",role_friendly_name[role]); + + // + // Setup and configure rf radio + // + + radio.begin(); + + // + // Open pipes to other nodes for communication + // + + // This simple sketch opens a single pipes for these two nodes to communicate + // back and forth. One listens on it, the other talks to it. + + if ( role == role_remote ) + { + radio.openWritingPipe(pipe); + } + else + { + radio.openReadingPipe(1,pipe); + } + + // + // Start listening + // + + if ( role == role_led ) + radio.startListening(); + + // + // Dump the configuration of the rf unit for debugging + // + + radio.printDetails(); + + // + // Set up buttons / LED's + // + + // Set pull-up resistors for all buttons + if ( role == role_remote ) + { + int i = num_button_pins; + while(i--) + { + pinMode(button_pins[i],INPUT); + digitalWrite(button_pins[i],HIGH); + } + } + + // Turn LED's ON until we start getting keys + if ( role == role_led ) + { + int i = num_led_pins; + while(i--) + { + pinMode(led_pins[i],OUTPUT); + led_states[i] = HIGH; + digitalWrite(led_pins[i],led_states[i]); + } + } + +} + +// +// Loop +// + +void loop(void) +{ + // + // Remote role. If the state of any button has changed, send the whole state of + // all buttons. + // + + if ( role == role_remote ) + { + // Get the current state of buttons, and + // Test if the current state is different from the last state we sent + int i = num_button_pins; + bool different = false; + while(i--) + { + uint8_t state = ! digitalRead(button_pins[i]); + if ( state != button_states[i] ) + { + different = true; + button_states[i] = state; + } + } + + // Send the state of the buttons to the LED board + if ( different ) + { + printf("Now sending..."); + bool ok = radio.write( button_states, num_button_pins ); + if (ok) + printf("ok\n\r"); + else + printf("failed\n\r"); + } + + // Try again in a short while + delay(20); + } + + // + // LED role. Receive the state of all buttons, and reflect that in the LEDs + // + + if ( role == role_led ) + { + // if there is data ready + if ( radio.available() ) + { + // Dump the payloads until we've gotten everything + bool done = false; + while (!done) + { + // Fetch the payload, and see if this was the last one. + done = radio.read( button_states, num_button_pins ); + + // Spew it + printf("Got buttons\n\r"); + + // For each button, if the button now on, then toggle the LED + int i = num_led_pins; + while(i--) + { + if ( button_states[i] ) + { + led_states[i] ^= HIGH; + digitalWrite(led_pins[i],led_states[i]); + } + } + } + } + } +} +// vim:ai:cin:sts=2 sw=2 ft=cpp diff --git a/RC_Turrel/libraries/RF24-master/examples/Usage/nordic_fob/Jamfile b/RC_Turrel/libraries/RF24-master/examples/Usage/nordic_fob/Jamfile new file mode 100644 index 0000000..ec519f7 --- /dev/null +++ b/RC_Turrel/libraries/RF24-master/examples/Usage/nordic_fob/Jamfile @@ -0,0 +1,219 @@ +# (1) Project Information + +PROJECT_LIBS = RF24 SPI ; +PROJECT_DIRS = $(PWD) ; + +# (2) Board Information + +UPLOAD_PROTOCOL ?= stk500v1 ; +UPLOAD_SPEED ?= 115200 ; +MCU ?= atmega328p ; +F_CPU ?= 16000000 ; +CORE ?= arduino ; +VARIANT ?= standard ; +ARDUINO_VERSION ?= 100 ; + +# (3) USB Ports + +PORTS = p4 p6 p9 u0 u1 u2 ; +PORT_p6 = /dev/tty.usbserial-A600eHIs ; +PORT_p4 = /dev/tty.usbserial-A40081RP ; +PORT_p9 = /dev/tty.usbserial-A9007LmI ; +PORT_u0 = /dev/ttyUSB0 ; +PORT_u1 = /dev/ttyUSB1 ; +PORT_u2 = /dev/ttyUSB2 ; + +# (4) Location of AVR tools +# +# This configuration assumes using avr-tools that were obtained separate from the Arduino +# distribution. + +if $(OS) = MACOSX +{ + AVR_BIN = /usr/local/avrtools/bin ; + AVR_ETC = /usr/local/avrtools/etc ; + AVR_INCLUDE = /usr/local/avrtools/include ; +} +else +{ + AVR_BIN = /usr/bin ; + AVR_INCLUDE = /usr/lib/avr/include ; + AVR_ETC = /etc ; +} + +# (5) Directories where Arduino core and libraries are located + +ARDUINO_DIR ?= /opt/Arduino ; +ARDUINO_CORE = $(ARDUINO_DIR)/hardware/arduino/cores/$(CORE) $(ARDUINO_DIR)/hardware/arduino/variants/$(VARIANT) ; +ARDUINO_LIB = $(ARDUINO_DIR)/libraries ; +SKETCH_LIB = $(HOME)/Source/Arduino/libraries ; + +# +# -------------------------------------------------- +# Below this line usually never needs to be modified +# + +# Tool locations + +CC = $(AVR_BIN)/avr-gcc ; +C++ = $(AVR_BIN)/avr-g++ ; +LINK = $(AVR_BIN)/avr-gcc ; +AR = $(AVR_BIN)/avr-ar rcs ; +RANLIB = ; +OBJCOPY = $(AVR_BIN)/avr-objcopy ; +AVRDUDE = $(AVR_BIN)/avrdude ; + +# Flags + +DEFINES += F_CPU=$(F_CPU)L ARDUINO=$(ARDUINO_VERSION) VERSION_H ; +OPTIM = -Os ; +CCFLAGS = -Wall -Wextra -Wno-strict-aliasing -mmcu=$(MCU) -ffunction-sections -fdata-sections ; +C++FLAGS = $(CCFLAGS) -fno-exceptions -fno-strict-aliasing ; +LINKFLAGS = $(OPTIM) -lm -Wl,--gc-sections -mmcu=$(MCU) ; +AVRDUDEFLAGS = -V -F -D -C $(AVR_ETC)/avrdude.conf -p $(MCU) -c $(UPLOAD_PROTOCOL) -b $(UPLOAD_SPEED) ; + +# Search everywhere for headers + +HDRS = $(PROJECT_DIRS) $(AVR_INCLUDE) $(ARDUINO_CORE) $(ARDUINO_LIB)/$(PROJECT_LIBS) $(ARDUINO_LIB)/$(PROJECT_LIBS)/utility $(SKETCH_LIB)/$(PROJECT_LIBS) ; + +# Output locations + +LOCATE_TARGET = $(F_CPU) ; +LOCATE_SOURCE = $(F_CPU) ; + +# +# Custom rules +# + +rule GitVersion +{ + Always $(<) ; + Depends all : $(<) ; +} + +actions GitVersion +{ + echo "const char program_version[] = \"\\" > $(<) + git log -1 --pretty=format:%h >> $(<) + echo "\";" >> $(<) +} + +GitVersion version.h ; + +rule Pde +{ + Depends $(<) : $(>) ; + MakeLocate $(<) : $(LOCATE_SOURCE) ; + Clean clean : $(<) ; +} + +if ( $(ARDUINO_VERSION) < 100 ) +{ + ARDUINO_H = WProgram.h ; +} +else +{ + ARDUINO_H = Arduino.h ; +} + +actions Pde +{ + echo "#include <$(ARDUINO_H)>" > $(<) + echo "#line 1 \"$(>)\"" >> $(<) + cat $(>) >> $(<) +} + +rule C++Pde +{ + local _CPP = $(>:B).cpp ; + Pde $(_CPP) : $(>) ; + C++ $(<) : $(_CPP) ; +} + +rule UserObject +{ + switch $(>:S) + { + case .ino : C++Pde $(<) : $(>) ; + case .pde : C++Pde $(<) : $(>) ; + } +} + +rule Objects +{ + local _i ; + + for _i in [ FGristFiles $(<) ] + { + local _b = $(_i:B)$(SUFOBJ) ; + local _o = $(_b:G=$(SOURCE_GRIST:E)) ; + Object $(_o) : $(_i) ; + Depends obj : $(_o) ; + } +} + +rule Library +{ + LibraryFromObjects $(<) : $(>:B)$(SUFOBJ) ; + Objects $(>) ; +} + +rule Main +{ + MainFromObjects $(<) : $(>:B)$(SUFOBJ) ; + Objects $(>) ; +} + +rule Hex +{ + Depends $(<) : $(>) ; + MakeLocate $(<) : $(LOCATE_TARGET) ; + Depends hex : $(<) ; + Clean clean : $(<) ; +} + +actions Hex +{ + $(OBJCOPY) -O ihex -R .eeprom $(>) $(<) +} + +rule Upload +{ + Depends $(1) : $(2) ; + Depends $(2) : $(3) ; + NotFile $(1) ; + Always $(1) ; + Always $(2) ; + UploadAction $(2) : $(3) ; +} + +actions UploadAction +{ + $(AVRDUDE) $(AVRDUDEFLAGS) -P $(<) $(AVRDUDE_WRITE_FLASH) -U flash:w:$(>):i +} + +rule Arduino +{ + LINKFLAGS on $(<) = $(LINKFLAGS) -Wl,-Map=$(LOCATE_TARGET)/$(<:B).map ; + Main $(<) : $(>) ; + LinkLibraries $(<) : libs core ; + Hex $(<:B).hex : $(<) ; + for _p in $(PORTS) + { + Upload $(_p) : $(PORT_$(_p)) : $(<:B).hex ; + } +} + +# +# Targets +# + +# Grab everything from the core directory +Library core : [ GLOB $(ARDUINO_CORE) : *.c *.cpp ] ; + +# Grab everything from libraries. To avoid this "grab everything" behaviour, you +# can specify specific modules to pick up in PROJECT_MODULES +Library libs : [ GLOB $(ARDUINO_LIB)/$(PROJECT_LIBS) $(ARDUINO_LIB)/$(PROJECT_LIBS)/utility $(SKETCH_LIB)/$(PROJECT_LIBS) : *.cpp *.c ] ; + +# Main output executable +Arduino $(PWD:B).elf : $(PROJECT_MODULES) [ GLOB $(PROJECT_DIRS) : *.c *.cpp *.pde *.ino ] ; diff --git a/RC_Turrel/libraries/RF24-master/examples/Usage/nordic_fob/nordic_fob.pde b/RC_Turrel/libraries/RF24-master/examples/Usage/nordic_fob/nordic_fob.pde new file mode 100644 index 0000000..5a316a0 --- /dev/null +++ b/RC_Turrel/libraries/RF24-master/examples/Usage/nordic_fob/nordic_fob.pde @@ -0,0 +1,142 @@ +/* + Copyright (C) 2012 J. Coliz + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + */ + +/** + * Example Nordic FOB Receiver + * + * This is an example of how to use the RF24 class to receive signals from the + * Sparkfun Nordic FOB. Thanks to Kirk Mower for providing test hardware. + * + * See blog post at http://maniacbug.wordpress.com/2012/01/08/nordic-fob/ + */ + +#include +#include +#include "nRF24L01.h" +#include "printf.h" + +// +// Hardware configuration +// + +// Set up nRF24L01 radio on SPI bus plus pins 9 & 10 + +RF24 radio(9,10); + +// +// Payload +// + +struct payload_t +{ + uint8_t buttons; + uint16_t id; + uint8_t empty; +}; + +const char* button_names[] = { "Up", "Down", "Left", "Right", "Center" }; +const int num_buttons = 5; + +// +// Forward declarations +// + +uint16_t flip_endian(uint16_t in); + +// +// Setup +// + +void setup(void) +{ + // + // Print preamble + // + + Serial.begin(57600); + printf_begin(); + printf("\r\nRF24/examples/nordic_fob/\r\n"); + + // + // Setup and configure rf radio according to the built-in parameters + // of the FOB. + // + + radio.begin(); + radio.setChannel(2); + radio.setPayloadSize(4); + radio.setAutoAck(false); + radio.setCRCLength(RF24_CRC_8); + radio.openReadingPipe(1,0xE7E7E7E7E7LL); + + // + // Start listening + // + + radio.startListening(); + + // + // Dump the configuration of the rf unit for debugging + // + + radio.printDetails(); +} + +// +// Loop +// + +void loop(void) +{ + // + // Receive each packet, dump it out + // + + // if there is data ready + if ( radio.available() ) + { + // Get the packet from the radio + payload_t payload; + radio.read( &payload, sizeof(payload) ); + + // Print the ID of this message. Note that the message + // is sent 'big-endian', so we have to flip it. + printf("#%05u Buttons ",flip_endian(payload.id)); + + // Print the name of each button + int i = num_buttons; + while (i--) + { + if ( ! ( payload.buttons & _BV(i) ) ) + { + printf("%s ",button_names[i]); + } + } + + // If no buttons, print None + if ( payload.buttons == _BV(num_buttons) - 1 ) + printf("None"); + + printf("\r\n"); + } +} + +// +// Helper functions +// + +// Change a big-endian word into a little-endian +uint16_t flip_endian(uint16_t in) +{ + uint16_t low = in >> 8; + uint16_t high = in << 8; + + return high | low; +} + +// vim:cin:ai:sts=2 sw=2 ft=cpp diff --git a/RC_Turrel/libraries/RF24-master/examples/Usage/pingpair_maple/Jamfile b/RC_Turrel/libraries/RF24-master/examples/Usage/pingpair_maple/Jamfile new file mode 100644 index 0000000..798096c --- /dev/null +++ b/RC_Turrel/libraries/RF24-master/examples/Usage/pingpair_maple/Jamfile @@ -0,0 +1,182 @@ +MCU = cortex-m3 ; +CHIP = STM32F103ZE ; +BOARD = maple_native ; + +#CHIP = at91sam3u4 ; +#BOARD = sam3u-ek ; + +if ! $(TOOLSET) +{ + TOOLSET = devkit ; + Echo "Assuming TOOLSET=devkit" ; +} + +if $(TOOLSET) = yagarto +{ + TOOLS_PATH = ~/Source/yagarto-4.6.2/bin ; + TOOLS_ARCH = arm-none-eabi- ; +} +if $(TOOLSET) = yagarto-install +{ + TOOLS_PATH = ~/Source/yagarto/install/bin ; + TOOLS_ARCH = arm-none-eabi- ; +} +else if $(TOOLSET) = devkit +{ + TOOLS_PATH = /opt/devkitARM/bin ; + TOOLS_ARCH = arm-eabi- ; +} +else if $(TOOLSET) = maple +{ + TOOLS_PATH = /opt/Maple/Resources/Java/hardware/tools/arm/bin ; + TOOLS_ARCH = arm-none-eabi- ; +} +else if $(TOOLSET) = ports +{ + TOOLS_PATH = /opt/local/bin ; + TOOLS_ARCH = arm-none-eabi- ; +} + +CC = $(TOOLS_PATH)/$(TOOLS_ARCH)gcc ; +C++ = $(TOOLS_PATH)/$(TOOLS_ARCH)g++ ; +AS = $(TOOLS_PATH)/$(TOOLS_ARCH)gcc -c ; +LINK = $(TOOLS_PATH)/$(TOOLS_ARCH)g++ ; +OBJCOPY = $(TOOLS_PATH)/$(TOOLS_ARCH)objcopy ; +DFU = dfu-util ; + +DEFINES += VECT_TAB_FLASH BOARD_$(BOARD) MCU_$(CHIP) ERROR_LED_PORT=GPIOC ERROR_LED_PIN=15 STM32_HIGH_DENSITY MAPLE_IDE ; +OPTIM = -Os ; +MFLAGS = cpu=$(MCU) thumb arch=armv7-m ; +CCFLAGS = -Wall -m$(MFLAGS) -g -nostdlib -ffunction-sections -fdata-sections -Wl,--gc-sections ; +C++FLAGS = $(CCFLAGS) -fno-rtti -fno-exceptions ; +LINKFLAGS += -m$(MFLAGS) -Xlinker --gc-sections ; +DFUFLAGS = -a1 -d 0x1eaf:0x0003 -R ; + +MAPLE_DIR = $(HOME)/Source/SAM3U/libmaple ; +MAPLE_LIBS = Servo LiquidCrystal Wire FreeRTOS ; +MAPLE_SUBDIRS = wirish wirish/comm wirish/boards libmaple libmaple/usb libmaple/usb/usb_lib ; + +SKETCH_DIR = $(HOME)/Source/Arduino ; +SKETCH_LIBS = RF24 ; + +MODULE_DIRS = . $(MAPLE_DIR)/$(MAPLE_SUBDIRS) $(MAPLE_DIR)/libraries/$(MAPLE_LIBS) $(SKETCH_DIR)/libraries/$(SKETCH_LIBS) ; +HDRS = $(MODULE_DIRS) ; +LOCATE_TARGET = out/$(TOOLSET) ; +LOCATE_SOURCE = $(LOCATE_TARGET) ; + +rule Pde +{ + Depends $(<) : $(>) ; + MakeLocate $(<) : $(LOCATE_SOURCE) ; + Clean clean : $(<) ; +} + +if ( $(ARDUINO_VERSION) < 100 ) +{ + ARDUINO_H = WProgram.h ; +} +else +{ + ARDUINO_H = Arduino.h ; +} + +actions Pde +{ + echo "#include <$(ARDUINO_H)>" > $(<) + echo "#line 1 \"$(>)\"" >> $(<) + cat $(>) >> $(<) +} + +rule C++Pde +{ + local _CPP = $(>:B).cpp ; + Pde $(_CPP) : $(>) ; + C++ $(<) : $(_CPP) ; +} + +rule Hex +{ + Depends $(<) : $(>) ; + MakeLocate $(<) : $(LOCATE_TARGET) ; + Depends hex : $(<) ; + Clean clean : $(<) ; +} + +actions Hex +{ + $(OBJCOPY) -O ihex $(>) $(<) +} + +rule Binary +{ + Depends $(<) : $(>) ; + MakeLocate $(<) : $(LOCATE_TARGET) ; + Depends binary : $(<) ; + Clean clean : $(<) ; +} + +actions Binary +{ + $(OBJCOPY) -O binary $(>) $(<) +} + +rule UserObject +{ + switch $(>:S) + { + case .S : As $(<) : $(>) ; + case .ino : C++Pde $(<) : $(>) ; + case .pde : C++Pde $(<) : $(>) ; + } +} + +rule Upload +{ + Depends up : $(<) ; + NotFile up ; + Always $(<) ; + Always up ; +} + +actions Upload +{ + $(DFU) $(DFUFLAGS) -D $(<) +} + +# Override base objects rule, so all output can go in the output dir +rule Objects +{ + local _i ; + + for _i in [ FGristFiles $(<) ] + { + local _b = $(_i:B)$(SUFOBJ) ; + local _o = $(_b:G=$(SOURCE_GRIST:E)) ; + Object $(_o) : $(_i) ; + Depends obj : $(_o) ; + } +} + +# Override base main rule, so all output can go in the output dir +rule Main +{ + MainFromObjects $(<) : $(>:B)$(SUFOBJ) ; + Objects $(>) ; +} + +# Modules +MODULES = [ GLOB $(MODULE_DIRS) : *.pde *.c *.cpp *.S ] ; + +# Main output executable +MAIN = $(PWD:B).elf ; + +# Linker script +LINK_DIR = $(MAPLE_DIR)/support/ld ; +LINKSCRIPT = $(LINK_DIR)/$(BOARD)/flash.ld ; + +# Bring in the map and link script +LINKFLAGS += -Wl,-Map=$(LOCATE_TARGET)/$(MAIN:B).map -T$(LINKSCRIPT) -L$(LINK_DIR) ; + +Main $(MAIN) : $(MODULES) ; +Binary $(MAIN:B).bin : $(MAIN) ; +Upload $(MAIN:B).bin ; diff --git a/RC_Turrel/libraries/RF24-master/examples/Usage/pingpair_maple/main.cpp b/RC_Turrel/libraries/RF24-master/examples/Usage/pingpair_maple/main.cpp new file mode 100644 index 0000000..b4f976d --- /dev/null +++ b/RC_Turrel/libraries/RF24-master/examples/Usage/pingpair_maple/main.cpp @@ -0,0 +1,87 @@ +#ifdef MAPLE_IDE + +#include +#include "wirish.h" + +extern void setup(void); +extern void loop(void); + +void board_start(const char* program_name) +{ + // Set up the LED to steady on + pinMode(BOARD_LED_PIN, OUTPUT); + digitalWrite(BOARD_LED_PIN, HIGH); + + // Setup the button as input + pinMode(BOARD_BUTTON_PIN, INPUT); + digitalWrite(BOARD_BUTTON_PIN, HIGH); + + SerialUSB.begin(); + SerialUSB.println("Press BUT"); + + // Wait for button press + while ( !isButtonPressed() ) + { + } + + SerialUSB.println("Welcome!"); + SerialUSB.println(program_name); + + int i = 11; + while (i--) + { + toggleLED(); + delay(50); + } +} + +/** + * Custom version of _write, which will print to the USB. + * In order to use it you MUST ADD __attribute__((weak)) + * to _write in libmaple/syscalls.c +*/ +extern "C" int _write (int file, char * ptr, int len) +{ + if ( (file != 1) && (file != 2) ) + return 0; + else + SerialUSB.write(ptr,len); + return len; +} + +/** + * Re-entrant version of _write. Yagarto and Devkit now use + * the re-entrant newlib, so these get called instead of the + * non_r versions. + */ +extern "C" int _write_r (void*, int file, char * ptr, int len) +{ + return _write( file, ptr, len); +} + +__attribute__((constructor)) __attribute__ ((weak)) void premain() +{ + init(); +} + +__attribute__((weak)) void setup(void) +{ + board_start("No program defined"); +} + +__attribute__((weak)) void loop(void) +{ +} + +__attribute__((weak)) int main(void) +{ + setup(); + + while (true) + { + loop(); + } + return 0; +} +#endif // ifdef MAPLE_IDE +// vim:cin:ai:sts=2 sw=2 ft=cpp diff --git a/RC_Turrel/libraries/RF24-master/examples/Usage/pingpair_maple/pingpair_maple.pde b/RC_Turrel/libraries/RF24-master/examples/Usage/pingpair_maple/pingpair_maple.pde new file mode 100644 index 0000000..2d3925b --- /dev/null +++ b/RC_Turrel/libraries/RF24-master/examples/Usage/pingpair_maple/pingpair_maple.pde @@ -0,0 +1,242 @@ +/* + Copyright (C) 2011 J. Coliz + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + */ + +/** + * Example RF Radio Ping Pair ... for Maple + * + * This is an example of how to use the RF24 class. Write this sketch to two different nodes, + * connect the role_pin to ground on one. The ping node sends the current time to the pong node, + * which responds by sending the value back. The ping node can then see how long the whole cycle + * took. + */ + +#include "WProgram.h" +#include +#include "nRF24L01.h" +#include "RF24.h" + +// +// Maple specific setup. Other than this section, the sketch is the same on Maple as on +// Arduino +// + +#ifdef MAPLE_IDE + +// External startup function +extern void board_start(const char* program_name); + +// Use SPI #2. +HardwareSPI SPI(2); + +#else +#define board_startup printf +#define toggleLED(x) (x) +#endif + +// +// Hardware configuration +// + +// Set up nRF24L01 radio on SPI bus plus pins 7 & 6 +// (This works for the Getting Started board plugged into the +// Maple Native backwards.) + +RF24 radio(7,6); + +// sets the role of this unit in hardware. Connect to GND to be the 'pong' receiver +// Leave open to be the 'ping' transmitter +const int role_pin = 10; + +// +// Topology +// + +// Radio pipe addresses for the 2 nodes to communicate. +const uint64_t pipes[2] = { 0xF0F0F0F0E1LL, 0xF0F0F0F0D2LL }; + +// +// Role management +// +// Set up role. This sketch uses the same software for all the nodes +// in this system. Doing so greatly simplifies testing. The hardware itself specifies +// which node it is. +// +// This is done through the role_pin +// + +// The various roles supported by this sketch +typedef enum { role_ping_out = 1, role_pong_back } role_e; + +// The debug-friendly names of those roles +const char* role_friendly_name[] = { "invalid", "Ping out", "Pong back"}; + +// The role of the current running sketch +role_e role; + +void setup(void) +{ + // + // Role + // + + // set up the role pin + pinMode(role_pin, INPUT); + digitalWrite(role_pin,HIGH); + delay(20); // Just to get a solid reading on the role pin + + // read the address pin, establish our role + if ( digitalRead(role_pin) ) + role = role_ping_out; + else + role = role_pong_back; + + // + // Print preamble + // + + board_start("\n\rRF24/examples/pingpair/\n\r"); + printf("ROLE: %s\n\r",role_friendly_name[role]); + + // + // Setup and configure rf radio + // + + radio.begin(); + + // optionally, increase the delay between retries & # of retries + radio.setRetries(15,15); + + // optionally, reduce the payload size. seems to + // improve reliability + radio.setPayloadSize(8); + + // + // Open pipes to other nodes for communication + // + + // This simple sketch opens two pipes for these two nodes to communicate + // back and forth. + // Open 'our' pipe for writing + // Open the 'other' pipe for reading, in position #1 (we can have up to 5 pipes open for reading) + + if ( role == role_ping_out ) + { + radio.openWritingPipe(pipes[0]); + radio.openReadingPipe(1,pipes[1]); + } + else + { + radio.openWritingPipe(pipes[1]); + radio.openReadingPipe(1,pipes[0]); + } + + // + // Start listening + // + + radio.startListening(); + + // + // Dump the configuration of the rf unit for debugging + // + + radio.printDetails(); +} + +void loop(void) +{ + // + // Ping out role. Repeatedly send the current time + // + + if (role == role_ping_out) + { + toggleLED(); + + // First, stop listening so we can talk. + radio.stopListening(); + + // Take the time, and send it. This will block until complete + unsigned long time = millis(); + printf("Now sending %lu...",time); + bool ok = radio.write( &time, sizeof(unsigned long) ); + + if (ok) + printf("ok...\r\n"); + else + printf("failed.\r\n"); + + // Now, continue listening + radio.startListening(); + + // Wait here until we get a response, or timeout (250ms) + unsigned long started_waiting_at = millis(); + bool timeout = false; + while ( ! radio.available() && ! timeout ) + if (millis() - started_waiting_at > 200 ) + timeout = true; + + // Describe the results + if ( timeout ) + { + printf("Failed, response timed out.\r\n"); + } + else + { + // Grab the response, compare, and send to debugging spew + unsigned long got_time; + radio.read( &got_time, sizeof(unsigned long) ); + + // Spew it + printf("Got response %lu, round-trip delay: %lu\r\n",got_time,millis()-got_time); + } + + toggleLED(); + + // Try again 1s later + delay(1000); + } + + // + // Pong back role. Receive each packet, dump it out, and send it back + // + + if ( role == role_pong_back ) + { + // if there is data ready + if ( radio.available() ) + { + // Dump the payloads until we've gotten everything + unsigned long got_time; + bool done = false; + while (!done) + { + // Fetch the payload, and see if this was the last one. + done = radio.read( &got_time, sizeof(unsigned long) ); + + // Spew it + printf("Got payload %lu...",got_time); + + // Delay just a little bit to let the other unit + // make the transition to receiver + delay(20); + } + + // First, stop listening so we can talk + radio.stopListening(); + + // Send the final one back. + radio.write( &got_time, sizeof(unsigned long) ); + printf("Sent response.\r\n"); + + // Now, resume listening so we catch the next packets. + radio.startListening(); + } + } +} +// vim:cin:ai:sts=2 sw=2 ft=cpp diff --git a/RC_Turrel/libraries/RF24-master/examples/pingpair_ack/pingpair_ack.ino b/RC_Turrel/libraries/RF24-master/examples/pingpair_ack/pingpair_ack.ino new file mode 100644 index 0000000..2d26da9 --- /dev/null +++ b/RC_Turrel/libraries/RF24-master/examples/pingpair_ack/pingpair_ack.ino @@ -0,0 +1,130 @@ +/* + // March 2014 - TMRh20 - Updated along with High Speed RF24 Library fork + // Parts derived from examples by J. Coliz +*/ +/** + * Example for efficient call-response using ack-payloads + * + * This example continues to make use of all the normal functionality of the radios including + * the auto-ack and auto-retry features, but allows ack-payloads to be written optionlly as well. + * This allows very fast call-response communication, with the responding radio never having to + * switch out of Primary Receiver mode to send back a payload, but having the option to if wanting + * to initiate communication instead of respond to a commmunication. + */ + + + +#include +#include "nRF24L01.h" +#include "RF24.h" +#include "printf.h" + +// Hardware configuration: Set up nRF24L01 radio on SPI bus plus pins CE 8, CSN 9 +// This is for UNO Adapter, pin 10 is Vcc +RF24 radio(8,9); + +// Topology +const uint64_t pipes[2] = { 0xABCDABCD71LL, 0x544d52687CLL }; // Radio pipe addresses for the 2 nodes to communicate. + +// Role management: Set up role. This sketch uses the same software for all the nodes +// in this system. Doing so greatly simplifies testing. + +typedef enum { role_ping_out = 1, role_pong_back } role_e; // The various roles supported by this sketch +const char* role_friendly_name[] = { "invalid", "Ping out", "Pong back"}; // The debug-friendly names of those roles +role_e role = role_pong_back; // The role of the current running sketch + +// A single byte to keep track of the data being sent back and forth +byte counter = 1; + +void setup(){ + +// Simple codes for UNO nRF adapter that uses pin 10 as Vcc + pinMode(10,OUTPUT); + digitalWrite(10,HIGH); + delay(500); + + + Serial.begin(57600); + printf_begin(); + printf("\n\rRF24/examples/GettingStarted/\n\r"); + printf("ROLE: %s\n\r",role_friendly_name[role]); + printf("*** PRESS 'T' to begin transmitting to the other node\n\r"); + + // Setup and configure rf radio + + radio.begin(); + radio.setAutoAck(1); // Ensure autoACK is enabled + radio.enableAckPayload(); // Allow optional ack payloads + radio.setRetries(0,15); // Smallest time between retries, max no. of retries + radio.setPayloadSize(1); // Here we are sending 1-byte payloads to test the call-response speed + radio.openWritingPipe(pipes[1]); // Both radios listen on the same pipes by default, and switch when writing + radio.openReadingPipe(1,pipes[0]); + radio.startListening(); // Start listening + radio.printDetails(); // Dump the configuration of the rf unit for debugging +} + +void loop(void) { + + if (role == role_ping_out){ + + radio.stopListening(); // First, stop listening so we can talk. + + printf("Now sending %d as payload. ",counter); + byte gotByte; + unsigned long time = micros(); // Take the time, and send it. This will block until complete + //Called when STANDBY-I mode is engaged (User is finished sending) + if (!radio.write( &counter, 1 )){ + printf("failed.\n\r"); + }else{ + + if(!radio.available()){ + printf("Blank Payload Received\n\r"); + }else{ + while(radio.available() ){ + unsigned long tim = micros(); + radio.read( &gotByte, 1 ); + printf("Got response %d, round-trip delay: %lu microseconds\n\r",gotByte,tim-time); + counter++; + } + } + + } + // Try again later + delay(1000); + } + + // Pong back role. Receive each packet, dump it out, and send it back + + if ( role == role_pong_back ) { + byte pipeNo; + byte gotByte; // Dump the payloads until we've gotten everything + while( radio.available(&pipeNo)){ + radio.read( &gotByte, 1 ); + radio.writeAckPayload(pipeNo,&gotByte, 1 ); + } + } + + // Change roles + + if ( Serial.available() ) + { + char c = toupper(Serial.read()); + if ( c == 'T' && role == role_pong_back ) + { + printf("*** CHANGING TO TRANSMIT ROLE -- PRESS 'R' TO SWITCH BACK\n\r"); + + role = role_ping_out; // Become the primary transmitter (ping out) + radio.openWritingPipe(pipes[0]); + radio.openReadingPipe(1,pipes[1]); + } + else if ( c == 'R' && role == role_ping_out ) + { + printf("*** CHANGING TO RECEIVE ROLE -- PRESS 'T' TO SWITCH BACK\n\r"); + + role = role_pong_back; // Become the primary receiver (pong back) + radio.openWritingPipe(pipes[1]); + radio.openReadingPipe(1,pipes[0]); + radio.startListening(); + } + } +} diff --git a/RC_Turrel/libraries/RF24-master/examples/pingpair_dyn/pingpair_dyn.ino b/RC_Turrel/libraries/RF24-master/examples/pingpair_dyn/pingpair_dyn.ino new file mode 100644 index 0000000..58f9d48 --- /dev/null +++ b/RC_Turrel/libraries/RF24-master/examples/pingpair_dyn/pingpair_dyn.ino @@ -0,0 +1,242 @@ +/* + Copyright (C) 2011 J. Coliz + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + */ + +/** + * Example using Dynamic Payloads + * + * This is an example of how to use payloads of a varying (dynamic) size. + */ + +#include +#include "RF24.h" +#include "printf.h" + +// +// Hardware configuration +// + +// Set up nRF24L01 radio on SPI bus plus pins +// CE = 8, CSN = 9 +RF24 radio(8,9); + +// sets the role of this unit in hardware. Connect to GND to be the 'pong' receiver +// Leave open to be the 'ping' transmitter +const int role_pin = 5; + +// +// Topology +// + +// Radio pipe addresses for the 2 nodes to communicate. +const uint64_t pipes[2] = { 0xEEFDFDFDECLL, 0xEEFDFDF0DFLL }; + +// +// Role management +// +// Set up role. This sketch uses the same software for all the nodes +// in this system. Doing so greatly simplifies testing. The hardware itself specifies +// which node it is. +// +// This is done through the role_pin +// + +// The various roles supported by this sketch +typedef enum { role_ping_out = 1, role_pong_back } role_e; + +// The debug-friendly names of those roles +const char* role_friendly_name[] = { "invalid", "Ping out", "Pong back"}; + +// The role of the current running sketch +role_e role; + +// +// Payload +// + +const int min_payload_size = 1; +const int max_payload_size = 32; +const int payload_size_increments_by = 1; +int next_payload_size = min_payload_size; + +char receive_payload[max_payload_size+1]; // +1 to allow room for a terminating NULL char + +void setup(void) +{ + +// Simple codes for UNO nRF adapter that uses pin 10 as Vcc + +pinMode(10,OUTPUT); +digitalWrite(10,HIGH); +delay(500); + + // + // Role + // + + // set up the role pin + pinMode(role_pin, INPUT); + digitalWrite(role_pin,HIGH); + delay(20); // Just to get a solid reading on the role pin + + // read the address pin, establish our role + if ( digitalRead(role_pin) ) + role = role_ping_out; + else + role = role_pong_back; + + // + // Print preamble + // + + Serial.begin(57600); + printf_begin(); + printf("\n\rRF24/examples/pingpair_dyn/\n\r"); + printf("ROLE: %s\n\r",role_friendly_name[role]); + + // + // Setup and configure rf radio + // + + radio.begin(); + + // enable dynamic payloads + radio.setCRCLength( RF24_CRC_16 ) ; + radio.enableDynamicPayloads(); + + // optionally, increase the delay between retries & # of retries + radio.setAutoAck( true ) ; + radio.setPALevel( RF24_PA_HIGH ) ; + + radio.setRetries(5,15); + + // + // Open pipes to other nodes for communication + // + + // This simple sketch opens two pipes for these two nodes to communicate + // back and forth. + // Open 'our' pipe for writing + // Open the 'other' pipe for reading, in position #1 (we can have up to 5 pipes open for reading) + + if ( role == role_ping_out ) + { + radio.openWritingPipe(pipes[0]); + radio.openReadingPipe(1,pipes[1]); + } + else + { + radio.openWritingPipe(pipes[1]); + radio.openReadingPipe(1,pipes[0]); + } + + // + // Start listening + // + + radio.startListening(); + + // + // Dump the configuration of the rf unit for debugging + // + + radio.printDetails(); +} + +void loop(void) +{ + // + // Ping out role. Repeatedly send the current time + // + + if (role == role_ping_out) + { + // The payload will always be the same, what will change is how much of it we send. + static char send_payload[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ789012"; + + // First, stop listening so we can talk. + radio.stopListening(); + + // Take the time, and send it. This will block until complete + printf("Now sending length %i...",next_payload_size); + radio.write( send_payload, next_payload_size, false ); + + // Now, continue listening + radio.startListening(); + + // Wait here until we get a response, or timeout + unsigned long started_waiting_at = millis(); + bool timeout = false; + while ( ! radio.available() && ! timeout ) + if (millis() - started_waiting_at > 1 + 5000/1000 ) + timeout = true; + + // Describe the results + if ( timeout ) + { + printf("Failed, response timed out.\n\r"); + } + else + { + // Grab the response, compare, and send to debugging spew + uint8_t len = radio.getDynamicPayloadSize(); + radio.read( receive_payload, len ); + + // Put a zero at the end for easy printing + receive_payload[len] = 0; + + // Spew it + printf("Got response size=%i value=%s\n\r",len,receive_payload); + } + + // Update size for next time. + next_payload_size += payload_size_increments_by; + if ( next_payload_size > max_payload_size ) + next_payload_size = min_payload_size; + + // Try again 1s later + delay(100); + } + + // + // Pong back role. Receive each packet, dump it out, and send it back + // + + if ( role == role_pong_back ) + { + // if there is data ready + if ( radio.available() ) + { + // Dump the payloads until we've gotten everything + uint8_t len; + bool done = false; + while (radio.available()) + { + // Fetch the payload, and see if this was the last one. + len = radio.getDynamicPayloadSize(); + radio.read( receive_payload, len ); + + // Put a zero at the end for easy printing + receive_payload[len] = 0; + + // Spew it + printf("Got payload size=%i value=%s\n\r",len,receive_payload); + } + + // First, stop listening so we can talk + radio.stopListening(); + + // Send the final one back. + radio.write( receive_payload, len ); + printf("Sent response.\n\r"); + + // Now, resume listening so we catch the next packets. + radio.startListening(); + } + } +} +// vim:cin:ai:sts=2 sw=2 ft=cpp \ No newline at end of file diff --git a/RC_Turrel/libraries/RF24-master/examples/pingpair_dyn/printf.h b/RC_Turrel/libraries/RF24-master/examples/pingpair_dyn/printf.h new file mode 100644 index 0000000..c2d9153 --- /dev/null +++ b/RC_Turrel/libraries/RF24-master/examples/pingpair_dyn/printf.h @@ -0,0 +1,37 @@ +/* + Copyright (C) 2011 J. Coliz + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + */ + +/** + * @file printf.h + * + * Setup necessary to direct stdout to the Arduino Serial library, which + * enables 'printf' + */ + +#ifndef __PRINTF_H__ +#define __PRINTF_H__ + + +#ifdef ARDUINO +int serial_putc( char c, FILE * ) +{ + Serial.write( c ); + + return c; +} + +void printf_begin(void) +{ + fdevopen( &serial_putc, 0 ); +} + +#else +#error This example is only for use on Arduino. +#endif // ARDUINO + +#endif // __PRINTF_H__ diff --git a/RC_Turrel/libraries/RF24-master/examples/pingpair_irq/pingpair_irq.ino b/RC_Turrel/libraries/RF24-master/examples/pingpair_irq/pingpair_irq.ino new file mode 100644 index 0000000..fb3f429 --- /dev/null +++ b/RC_Turrel/libraries/RF24-master/examples/pingpair_irq/pingpair_irq.ino @@ -0,0 +1,137 @@ +/* + Copyright (C) 2011 J. Coliz + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + Update 2014 - TMRh20 + */ + +/** + * Example of using interrupts + * + * This is an example of how to user interrupts to interact with the radio, and a demonstration + * of how to use them to sleep when receiving, and not miss any payloads. + * The pingpair_sleepy example expands on sleep functionality with a timed sleep option for the transmitter. + * Sleep functionality is built directly into my fork of the RF24Network library + */ + +#include +#include "nRF24L01.h" +#include "RF24.h" +#include "printf.h" +#include +#include + +// Hardware configuration +RF24 radio(7,8); // Set up nRF24L01 radio on SPI bus plus pins 9 & 10 + +const short role_pin = 5; // sets the role of this unit in hardware. Connect to GND to be the 'pong' receiver + // Leave open to be the 'ping' transmitter + + const uint64_t address[2] = {0xABCDABCD71LL, 0x544d52687CLL}; // Radio pipe addresses for the 2 nodes to communicate. + +// Role management + +// Set up role. This sketch uses the same software for all the nodes in this +// system. Doing so greatly simplifies testing. The hardware itself specifies +// which node it is. +// This is done through the role_pin +typedef enum { role_sender = 1, role_receiver } role_e; // The various roles supported by this sketch +const char* role_friendly_name[] = { "invalid", "Sender", "Receiver"}; // The debug-friendly names of those roles +role_e role; // The role of the current running sketch + +boolean gotMsg = 0; // So we know when to go to sleep + +/********************** Setup *********************/ +void setup(){ + + pinMode(role_pin, INPUT); // set up the role pin + digitalWrite(role_pin,HIGH); // Change this to LOW/HIGH instead of using an external pin + delay(20); // Just to get a solid reading on the role pin + + if ( digitalRead(role_pin) ) // read the address pin, establish our role + role = role_sender; + else + role = role_receiver; + + + Serial.begin(115200); + printf_begin(); + printf("\n\rRF24/examples/pingpair_irq/\n\r"); + printf("ROLE: %s\n\r",role_friendly_name[role]); + + // Setup and configure rf radio + radio.begin(); + radio.enableAckPayload(); // We will be using the Ack Payload feature, so please enable it + // Open pipes to other node for communication + if ( role == role_sender ) { // This simple sketch opens a pipe on a single address for these two nodes to + radio.openWritingPipe(address[0]); // communicate back and forth. One listens on it, the other talks to it. + radio.openReadingPipe(1,address[1]); + }else{ + radio.openWritingPipe(address[1]); + radio.openReadingPipe(1,address[0]); + radio.startListening(); + } + radio.printDetails(); // Dump the configuration of the rf unit for debugging + delay(50); + attachInterrupt(0, check_radio, FALLING); // Attach interrupt handler to interrupt #0 (using pin 2) on BOTH the sender and receiver +} + +static uint32_t message_count = 0; + + +/********************** Main Loop *********************/ +void loop() { + + + if (role == role_sender) { // Sender role. Repeatedly send the current time + unsigned long time = millis(); // Take the time, and send it. + printf("Now sending %lu\n\r",time); + radio.startWrite( &time, sizeof(unsigned long) ,0); + delay(2000); // Try again soon + } + + + if(role == role_receiver){ // Receiver does nothing except in IRQ + } +} + + +/********************** Interrupt *********************/ + +void check_radio(void) // Receiver role: Does nothing! All the work is in IRQ +{ + + bool tx,fail,rx; + radio.whatHappened(tx,fail,rx); // What happened? + + if ( tx ) { // Have we successfully transmitted? + if ( role == role_sender ){ printf("Send:OK\n\r"); } + if ( role == role_receiver ){ printf("Ack Payload:Sent\n\r"); } + } + + if ( fail ) { // Have we failed to transmit? + if ( role == role_sender ){ printf("Send:Failed\n\r"); } + if ( role == role_receiver ){ printf("Ack Payload:Failed\n\r"); } + } + + if ( rx || radio.available()){ // Did we receive a message? + + if ( role == role_sender ) { // If we're the sender, we've received an ack payload + radio.read(&message_count,sizeof(message_count)); + printf("Ack:%lu\n\r",message_count); + } + + + if ( role == role_receiver ) { // If we're the receiver, we've received a time message + static unsigned long got_time; // Get this payload and dump it + radio.read( &got_time, sizeof(got_time) ); + printf("Got payload %lu\n\r",got_time); + radio.writeAckPayload( 1, &message_count, sizeof(message_count) ); // Add an ack packet for the next time around. This is a simple + ++message_count; // packet counter + + } + } +} diff --git a/RC_Turrel/libraries/RF24-master/examples/pingpair_irq/pingpair_irq.pde b/RC_Turrel/libraries/RF24-master/examples/pingpair_irq/pingpair_irq.pde new file mode 100644 index 0000000..6e7b105 --- /dev/null +++ b/RC_Turrel/libraries/RF24-master/examples/pingpair_irq/pingpair_irq.pde @@ -0,0 +1,217 @@ +/* + Copyright (C) 2011 J. Coliz + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + */ + +/** + * Example of using interrupts + * + * This is an example of how to user interrupts to interact with the radio. + * It builds on the pingpair_pl example, and uses ack payloads. + */ + +#include +#include "nRF24L01.h" +#include "RF24.h" +#include "printf.h" + +// +// Hardware configuration +// + +// Set up nRF24L01 radio on SPI bus plus pins 9 & 10 + +RF24 radio(8,9); + +// sets the role of this unit in hardware. Connect to GND to be the 'pong' receiver +// Leave open to be the 'ping' transmitter +const short role_pin = 7; + +// +// Topology +// + +// Single radio pipe address for the 2 nodes to communicate. +const uint64_t pipe = 0xE8E8F0F0E1LL; + +// +// Role management +// +// Set up role. This sketch uses the same software for all the nodes in this +// system. Doing so greatly simplifies testing. The hardware itself specifies +// which node it is. +// +// This is done through the role_pin +// + +// The various roles supported by this sketch +typedef enum { role_sender = 1, role_receiver } role_e; + +// The debug-friendly names of those roles +const char* role_friendly_name[] = { "invalid", "Sender", "Receiver"}; + +// The role of the current running sketch +role_e role; + +// Interrupt handler, check the radio because we got an IRQ +void check_radio(void); + +void setup(void) +{ + // + // Role + // + + // set up the role pin + pinMode(role_pin, INPUT); + digitalWrite(role_pin,HIGH); + delay(20); // Just to get a solid reading on the role pin + + // read the address pin, establish our role + if ( digitalRead(role_pin) ) + role = role_sender; + else + role = role_receiver; + + // + // Print preamble + // + + Serial.begin(57600); + printf_begin(); + printf("\n\rRF24/examples/pingpair_irq/\n\r"); + printf("ROLE: %s\n\r",role_friendly_name[role]); + + // + // Setup and configure rf radio + // + + radio.begin(); + + // We will be using the Ack Payload feature, so please enable it + radio.enableAckPayload(); + + // + // Open pipes to other nodes for communication + // + + // This simple sketch opens a single pipe for these two nodes to communicate + // back and forth. One listens on it, the other talks to it. + + if ( role == role_sender ) + { + radio.openWritingPipe(pipe); + } + else + { + radio.openReadingPipe(1,pipe); + } + + // + // Start listening + // + + if ( role == role_receiver ) + radio.startListening(); + + // + // Dump the configuration of the rf unit for debugging + // + + radio.printDetails(); + + // + // Attach interrupt handler to interrupt #0 (using pin 2) + // on BOTH the sender and receiver + // + + attachInterrupt(0, check_radio, FALLING); +} + +static uint32_t message_count = 0; + +void loop(void) +{ + // + // Sender role. Repeatedly send the current time + // + + if (role == role_sender) + { + // Take the time, and send it. + unsigned long time = millis(); + printf("Now sending %lu\n\r",time); + radio.powerUp() ; + radio.startWrite( &time, sizeof(unsigned long) ); + + // Try again soon + delay(1000); + } + + // + // Receiver role: Does nothing! All the work is in IRQ + // + +} + +void check_radio(void) +{ + // What happened? + bool tx,fail,rx; + radio.whatHappened(tx,fail,rx); + + // Have we successfully transmitted? + if ( tx ) + { + if ( role == role_sender ) + printf("Send:OK\n\r"); + + if ( role == role_receiver ) + printf("Ack Payload:Sent\n\r"); + } + + // Have we failed to transmit? + if ( fail ) + { + if ( role == role_sender ) + printf("Send:Failed\n\r"); + + if ( role == role_receiver ) + printf("Ack Payload:Failed\n\r"); + } + + // Transmitter can power down for now, because + // the transmission is done. + if ( ( tx || fail ) && ( role == role_sender ) ) + radio.powerDown(); + + // Did we receive a message? + if ( rx ) + { + // If we're the sender, we've received an ack payload + if ( role == role_sender ) + { + radio.read(&message_count,sizeof(message_count)); + printf("Ack:%lu\n\r",message_count); + } + + // If we're the receiver, we've received a time message + if ( role == role_receiver ) + { + // Get this payload and dump it + static unsigned long got_time; + radio.read( &got_time, sizeof(got_time) ); + printf("Got payload %lu\n\r",got_time); + + // Add an ack packet for the next time around. This is a simple + // packet counter + radio.writeAckPayload( 1, &message_count, sizeof(message_count) ); + ++message_count; + } + } +} + +// vim:ai:cin:sts=2 sw=2 ft=cpp diff --git a/RC_Turrel/libraries/RF24-master/examples/pingpair_irq/printf.h b/RC_Turrel/libraries/RF24-master/examples/pingpair_irq/printf.h new file mode 100644 index 0000000..f549c1a --- /dev/null +++ b/RC_Turrel/libraries/RF24-master/examples/pingpair_irq/printf.h @@ -0,0 +1,40 @@ +/* + Copyright (C) 2011 J. Coliz + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + */ + +/** + * @file printf.h + * + * Setup necessary to direct stdout to the Arduino Serial library, which + * enables 'printf' + */ + +#ifndef __PRINTF_H__ +#define __PRINTF_H__ + +<<<<<<< HEAD +#ifdef ARDUINO +======= +>>>>>>> 828add79a5375479cd29a7433c598b8ce56ee60b + +int serial_putc( char c, FILE * ) +{ + Serial.write( c ); + + return c; +} + +void printf_begin(void) +{ + fdevopen( &serial_putc, 0 ); +} + +#else +#error This example is only for use on Arduino. +#endif // ARDUINO + +#endif // __PRINTF_H__ diff --git a/RC_Turrel/libraries/RF24-master/examples/pingpair_multi_dyn/Jamfile b/RC_Turrel/libraries/RF24-master/examples/pingpair_multi_dyn/Jamfile new file mode 100644 index 0000000..901f8da --- /dev/null +++ b/RC_Turrel/libraries/RF24-master/examples/pingpair_multi_dyn/Jamfile @@ -0,0 +1,206 @@ +PROJECT_NAME = $(PWD:B) ; +PROJECT_DIR = . ; +PROJECT_LIBS = SPI RF24 ; + +OUT_DIR = ojam ; +F_CPU = 16000000 ; +MCU = atmega328p ; +PORTS = /dev/tty.usbserial-A600eHIs /dev/tty.usbserial-A40081RP /dev/tty.usbserial-A9007LmI ; + +UPLOAD_RATE = 57600 ; +AVRDUDE_PROTOCOL = stk500v1 ; +COM = 33 ; + +# Host-specific overrides for locations +if $(OS) = MACOSX +{ +ARDUINO_VERSION = 22 ; +OLD_DIR = /opt/arduino-0021 ; +AVR_TOOLS_PATH = $(OLD_DIR)/hardware/tools/avr/bin ; +AVRDUDECONFIG_PATH = $(OLD_DIR)/hardware/tools/avr/etc ; +ARDUINO_DIR = /opt/Arduino ; +ARDUINO_AVR = /usr/lib/avr/include ; +} + +# Where is everything? +ARDUINO_VERSION ?= 22 ; +AVR_TOOLS_PATH ?= /usr/bin ; +ARDUINO_DIR ?= /opt/arduino-00$(ARDUINO_VERSION) ; +ARDUINO_AVR ?= $(ARDUINO_DIR)/hardware/tools/avr/avr/include/avr ; +AVRDUDECONFIG_PATH ?= $(ARDUINO_DIR)/hardware/tools ; +ARDUINO_CORE = $(ARDUINO_DIR)/hardware/arduino/cores/arduino ; +ARDUINO_LIB = $(ARDUINO_DIR)/libraries ; +SKETCH_LIB = $(HOME)/Source/Arduino/libraries ; +AVR_CC = $(AVR_TOOLS_PATH)/avr-gcc ; +AVR_CXX = $(AVR_TOOLS_PATH)/avr-g++ ; +AVR_LD = $(AVR_TOOLS_PATH)/avr-gcc ; +AVR_OBJCOPY = $(AVR_TOOLS_PATH)/avr-objcopy ; +AVRDUDE = $(AVR_TOOLS_PATH)/avrdude ; + +DEFINES = F_CPU=$(F_CPU)L ARDUINO=$(ARDUINO_VERSION) VERSION_H ; +CTUNING = -ffunction-sections -fdata-sections ; +CXXTUNING = -fno-exceptions -fno-strict-aliasing ; +CFLAGS = -Os -Wall -Wextra -mmcu=$(MCU) $(CTUNING) ; +CXXFLAGS = $(CFLAGS) $(CXXTUNING) ; +LDFLAGS = -Os -lm -Wl,--gc-sections -mmcu=atmega328p ; + +# Search everywhere for headers +HDRS = $(PROJECT_DIR) $(ARDUINO_AVR) $(ARDUINO_CORE) [ GLOB $(ARDUINO_LIB) $(SKETCH_LIB) : [^.]* ] ; + +# Grab everything from the core directory +CORE_MODULES = [ GLOB $(ARDUINO_CORE) : *.c *.cpp ] ; + +# Grab everything from libraries. To avoid this "grab everything" behaviour, you +# can specify specific modules to pick up in PROJECT_MODULES +LIB_MODULES = [ GLOB $(ARDUINO_LIB)/$(PROJECT_LIBS) $(SKETCH_LIB)/$(PROJECT_LIBS) : *.cpp ] ; + +# In addition to explicitly-specified program modules, pick up anything from the current +# dir. +PROJECT_MODULES += [ GLOB $(PROJECT_DIR) : *.c *.cpp *.pde ] ; + +# Shortcut for the out files +OUT = $(OUT_DIR)/$(PROJECT_NAME) ; + +# AvrDude setup +AVRDUDE_FLAGS = -V -F -D -C $(AVRDUDECONFIG_PATH)/avrdude.conf -p $(MCU) -c $(AVRDUDE_PROTOCOL) -b $(UPLOAD_RATE) ; + +rule GitVersion +{ + Always $(<) ; + Depends all : $(<) ; +} + +actions GitVersion +{ + echo "const char program_version[] = \"\\" > $(<) + git log -1 --pretty=format:%h >> $(<) + echo "\";" >> $(<) +} + +GitVersion version.h ; + +rule AvrCc +{ + Depends $(<) : $(>) ; + Depends $(<) : $(<:D) ; + Clean clean : $(<) ; + + CCHDRS on $(<) = [ on $(<) FIncludes $(HDRS) ] ; + CCDEFS on $(<) = [ on $(<) FDefines $(DEFINES) ] ; +} + +actions AvrCc +{ + $(AVR_CC) -c -o $(<) $(CCHDRS) $(CCDEFS) $(CFLAGS) $(>) +} + +rule AvrC++ +{ + Depends $(<) : $(>) ; + Depends $(<) : $(<:D) ; + Clean clean : $(<) ; + + CCHDRS on $(<) = [ on $(<) FIncludes $(HDRS) ] ; + CCDEFS on $(<) = [ on $(<) FDefines $(DEFINES) ] ; +} + +actions AvrC++ +{ + $(AVR_CXX) -c -o $(<) $(CCHDRS) $(CCDEFS) $(CXXFLAGS) $(>) +} + +rule Pde +{ + Depends $(<) : $(>) ; + Depends $(<) : $(<:D) ; + Clean clean : $(<) ; + +} + +actions Pde +{ + echo "#include " > $(<) + echo "#line 1 \"$(>)\"" >> $(<) + cat $(>) >> $(<) +} + +rule AvrPde +{ + local _CPP = $(OUT_DIR)/$(_I:B).cpp ; + Pde $(_CPP) : $(>) ; + AvrC++ $(<) : $(_CPP) ; +} + +rule AvrObject +{ + switch $(>:S) + { + case .c : AvrCc $(<) : $(>) ; + case .cpp : AvrC++ $(<) : $(>) ; + case .pde : AvrPde $(<) : $(>) ; + } +} + +rule AvrObjects +{ + for _I in $(<) + { + AvrObject $(OUT_DIR)/$(_I:B).o : $(_I) ; + } +} + +rule AvrMainFromObjects +{ + Depends $(<) : $(>) ; + Depends $(<) : $(<:D) ; + MkDir $(<:D) ; + Depends all : $(<) ; + Clean clean : $(<) ; +} + +actions AvrMainFromObjects +{ + $(AVR_LD) $(LDFLAGS) -o $(<) $(>) +} + +rule AvrMain +{ + AvrMainFromObjects $(<) : $(OUT_DIR)/$(>:B).o ; + AvrObjects $(>) ; +} + +rule AvrHex +{ + Depends $(<) : $(>) ; + Depends $(<) : $(<:D) ; + Depends hex : $(<) ; + Clean clean : $(<) ; +} + +actions AvrHex +{ + $(AVR_OBJCOPY) -O ihex -R .eeprom $(>) $(<) +} + +rule AvrUpload +{ + Depends $(1) : $(2) ; + Depends $(2) : $(3) ; + NotFile $(1) ; + Always $(1) ; + Always $(2) ; + AvrUploadAction $(2) : $(3) ; +} + +actions AvrUploadAction +{ + $(AVRDUDE) $(AVRDUDE_FLAGS) -P $(<) $(AVRDUDE_WRITE_FLASH) -U flash:w:$(>):i +} + +AvrMain $(OUT).elf : $(CORE_MODULES) $(LIB_MODULES) $(PROJECT_MODULES) ; +AvrHex $(OUT).hex : $(OUT).elf ; + +AvrUpload p6 : /dev/tty.usbserial-A600eHIs : $(OUT).hex ; +AvrUpload p4 : /dev/tty.usbserial-A40081RP : $(OUT).hex ; +AvrUpload p9 : /dev/tty.usbserial-A9007LmI : $(OUT).hex ; + diff --git a/RC_Turrel/libraries/RF24-master/examples/pingpair_multi_dyn/pingpair_multi_dyn.pde b/RC_Turrel/libraries/RF24-master/examples/pingpair_multi_dyn/pingpair_multi_dyn.pde new file mode 100644 index 0000000..8809023 --- /dev/null +++ b/RC_Turrel/libraries/RF24-master/examples/pingpair_multi_dyn/pingpair_multi_dyn.pde @@ -0,0 +1,253 @@ +/* + Copyright (C) 2011 James Coliz, Jr. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + */ + +/** + * Example using Dynamic Payloads + * + * This is an example of how to use payloads of a varying (dynamic) size. + */ + +#include +#include "RF24.h" +#include "printf.h" + +// +// Hardware configuration +// + +// Set up nRF24L01 radio on SPI bus plus pins 8 & 9 +RF24 radio(8,9); + +// Use multicast? +// sets the multicast behavior this unit in hardware. Connect to GND to use unicast +// Leave open (default) to use multicast. +const int multicast_pin = 6 ; + +// sets the role of this unit in hardware. Connect to GND to be the 'pong' receiver +// Leave open to be the 'ping' transmitter +const int role_pin = 7; +bool multicast = true ; + +// +// Topology +// + +// Radio pipe addresses for the 2 nodes to communicate. +const uint64_t pipes[2] = { 0xEEFAFDFDEELL, 0xEEFDFAF50DFLL }; + +// +// Role management +// +// Set up role. This sketch uses the same software for all the nodes +// in this system. Doing so greatly simplifies testing. The hardware itself specifies +// which node it is. +// +// This is done through the role_pin +// + +// The various roles supported by this sketch +typedef enum { role_ping_out = 1, role_pong_back } role_e; + +// The debug-friendly names of those roles +const char* role_friendly_name[] = { "invalid", "Ping out", "Pong back"}; + +// The role of the current running sketch +role_e role; + +// +// Payload +// + +const int min_payload_size = 1; +const int max_payload_size = 32; +const int payload_size_increments_by = 1; +int next_payload_size = min_payload_size; + +char receive_payload[max_payload_size+1]; // +1 to allow room for a terminating NULL char + +void setup(void) +{ + // + // Multicast + // + pinMode(multicast_pin, INPUT); + digitalWrite(multicast_pin,HIGH); + delay( 20 ) ; + + // read multicast role, LOW for unicast + if( digitalRead( multicast_pin ) ) + multicast = true ; + else + multicast = false ; + + + // + // Role + // + + // set up the role pin + pinMode(role_pin, INPUT); + digitalWrite(role_pin,HIGH); + delay( 20 ); // Just to get a solid reading on the role pin + + // read the address pin, establish our role + if ( digitalRead(role_pin) ) + role = role_ping_out; + else + role = role_pong_back; + + // + // Print preamble + // + + Serial.begin(57600); + printf_begin(); + printf("\n\rRF24/examples/pingpair_multi_dyn/\n\r"); + printf("ROLE: %s\n\r",role_friendly_name[role]); + printf("MULTICAST: %s\r\n",(multicast?"true (unreliable)":"false (reliable)")); + // + // Setup and configure rf radio + // + + radio.begin(); + + // enable dynamic payloads + radio.enableDynamicPayloads(); + radio.setCRCLength( RF24_CRC_16 ) ; + + // optionally, increase the delay between retries & # of retries + radio.setRetries( 15, 5 ) ; + radio.setAutoAck( true ) ; + //radio.setPALevel( RF24_PA_LOW ) ; + + // + // Open pipes to other nodes for communication + // + + // This simple sketch opens two pipes for these two nodes to communicate + // back and forth. + // Open 'our' pipe for writing + // Open the 'other' pipe for reading, in position #1 (we can have up to 5 pipes open for reading) + + if ( role == role_ping_out ) + { + radio.openWritingPipe(pipes[0]); + radio.openReadingPipe(1,pipes[1]); + } + else + { + radio.openWritingPipe(pipes[1]); + radio.openReadingPipe(1,pipes[0]); + } + + // + // Start listening + // + radio.powerUp() ; + radio.startListening(); + + // + // Dump the configuration of the rf unit for debugging + // + + radio.printDetails(); +} + +void loop(void) +{ + // + // Ping out role. Repeatedly send the current time + // + + if (role == role_ping_out) + { + // The payload will always be the same, what will change is how much of it we send. + static char send_payload[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ789012"; + + // First, stop listening so we can talk. + radio.stopListening(); + + // Take the time, and send it. This will block until complete + printf("Now sending length %i...",next_payload_size); + radio.write( send_payload, next_payload_size, multicast ); + + // Now, continue listening + radio.startListening(); + + // Wait here until we get a response, or timeout + unsigned long started_waiting_at = millis(); + bool timeout = false; + while ( ! radio.available() && ! timeout ) + if (millis() - started_waiting_at > 1 + radio.getMaxTimeout()/1000 ) + timeout = true; + + // Describe the results + if ( timeout ) + { + printf("Failed, response timed out.\n\r"); + } + else + { + // Grab the response, compare, and send to debugging spew + uint8_t len = radio.getDynamicPayloadSize(); + radio.read( receive_payload, len ); + + // Put a zero at the end for easy printing + receive_payload[len] = 0; + + // Spew it + printf("Got response size=%i value=%s\n\r",len,receive_payload); + } + + // Update size for next time. + next_payload_size += payload_size_increments_by; + if ( next_payload_size > max_payload_size ) + next_payload_size = min_payload_size; + + // Try again 1s later + delay(250); + } + + // + // Pong back role. Receive each packet, dump it out, and send it back + // + + if ( role == role_pong_back ) + { + // if there is data ready + if ( radio.available() ) + { + // Dump the payloads until we've gotten everything + uint8_t len; + bool done = false; + while (!done) + { + // Fetch the payload, and see if this was the last one. + len = radio.getDynamicPayloadSize(); + done = radio.read( receive_payload, len ); + + // Put a zero at the end for easy printing + receive_payload[len] = 0; + + // Spew it + printf("Got payload size=%i value=%s\n\r",len,receive_payload); + } + + // First, stop listening so we can talk + radio.stopListening(); + + // Send the final one back. + radio.write( receive_payload, len, multicast ); + printf("Sent response.\n\r"); + + // Now, resume listening so we catch the next packets. + radio.startListening(); + } + } +} +// vim:cin:ai:sts=2 sw=2 ft=cpp diff --git a/RC_Turrel/libraries/RF24-master/examples/pingpair_multi_dyn/printf.h b/RC_Turrel/libraries/RF24-master/examples/pingpair_multi_dyn/printf.h new file mode 100644 index 0000000..1b853db --- /dev/null +++ b/RC_Turrel/libraries/RF24-master/examples/pingpair_multi_dyn/printf.h @@ -0,0 +1,31 @@ +/* + Copyright (C) 2011 James Coliz, Jr. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + */ + +/** + * @file printf.h + * + * Setup necessary to direct stdout to the Arduino Serial library, which + * enables 'printf' + */ + +#ifndef __PRINTF_H__ +#define __PRINTF_H__ + +int serial_putc( char c, FILE * ) +{ + Serial.write( c ); + + return c; +} + +void printf_begin(void) +{ + fdevopen( &serial_putc, 0 ); +} + +#endif // __PRINTF_H__ diff --git a/RC_Turrel/libraries/RF24-master/examples/pingpair_sleepy/pingpair_sleepy.ino b/RC_Turrel/libraries/RF24-master/examples/pingpair_sleepy/pingpair_sleepy.ino new file mode 100644 index 0000000..8a8bc4e --- /dev/null +++ b/RC_Turrel/libraries/RF24-master/examples/pingpair_sleepy/pingpair_sleepy.ino @@ -0,0 +1,225 @@ +/* + Copyright (C) 2011 J. Coliz + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + + TMRh20 2014 - Updates to the library allow sleeping both in TX and RX modes: + TX Mode: The radio can be powered down (.9uA current) and the Arduino slept using the watchdog timer + RX Mode: The radio can be left in standby mode (22uA current) and the Arduino slept using an interrupt pin + */ + +/** + * Example RF Radio Ping Pair which Sleeps between Sends + * + * This is an example of how to use the RF24 class to create a battery- + * efficient system. It is just like the GettingStarted_CallResponse example, but the + * ping node powers down the radio and sleeps the MCU after every + * ping/pong cycle, and the receiver sleeps between payloads. + * + * Write this sketch to two different nodes, + * connect the role_pin to ground on one. The ping node sends the current + * time to the pong node, which responds by sending the value back. The ping + * node can then see how long the whole cycle took. + */ + +#include +#include +#include +#include "nRF24L01.h" +#include "RF24.h" +#include "printf.h" + + +// Set up nRF24L01 radio on SPI bus plus pins 9 & 10 +RF24 radio(7,8); + +// sets the role of this unit in hardware. Connect to GND to be the 'pong' receiver +// Leave open to be the 'ping' transmitter +const int role_pin = 5; + +const uint64_t pipes[2] = { 0xF0F0F0F0E1LL, 0xF0F0F0F0D2LL }; // Radio pipe addresses for the 2 nodes to communicate. + +// Role management +// Set up role. This sketch uses the same software for all the nodes +// in this system. Doing so greatly simplifies testing. The hardware itself specifies +// which node it is. + +// The various roles supported by this sketch +typedef enum { role_ping_out = 1, role_pong_back } role_e; + +// The debug-friendly names of those roles +const char* role_friendly_name[] = { "invalid", "Ping out", "Pong back"}; + +// The role of the current running sketch +role_e role; + + +// Sleep declarations +typedef enum { wdt_16ms = 0, wdt_32ms, wdt_64ms, wdt_128ms, wdt_250ms, wdt_500ms, wdt_1s, wdt_2s, wdt_4s, wdt_8s } wdt_prescalar_e; + +void setup_watchdog(uint8_t prescalar); +void do_sleep(void); + +const short sleep_cycles_per_transmission = 4; +volatile short sleep_cycles_remaining = sleep_cycles_per_transmission; + + + +void setup(){ + + // set up the role pin + pinMode(role_pin, INPUT); + digitalWrite(role_pin,HIGH); + delay(20); // Just to get a solid reading on the role pin + + // read the address pin, establish our role + if ( digitalRead(role_pin) ) + role = role_ping_out; + else + role = role_pong_back; + + Serial.begin(57600); + printf_begin(); + printf("\n\rRF24/examples/pingpair_sleepy/\n\r"); + printf("ROLE: %s\n\r",role_friendly_name[role]); + + // Prepare sleep parameters + // Only the ping out role uses WDT. Wake up every 4s to send a ping + //if ( role == role_ping_out ) + setup_watchdog(wdt_4s); + + // Setup and configure rf radio + + radio.begin(); + + // Open pipes to other nodes for communication + + // This simple sketch opens two pipes for these two nodes to communicate + // back and forth. + // Open 'our' pipe for writing + // Open the 'other' pipe for reading, in position #1 (we can have up to 5 pipes open for reading) + + if ( role == role_ping_out ) { + radio.openWritingPipe(pipes[0]); + radio.openReadingPipe(1,pipes[1]); + } else { + radio.openWritingPipe(pipes[1]); + radio.openReadingPipe(1,pipes[0]); + } + + // Start listening + radio.startListening(); + + // Dump the configuration of the rf unit for debugging + //radio.printDetails(); +} + +void loop(){ + + + if (role == role_ping_out) { // Ping out role. Repeatedly send the current time + radio.powerUp(); // Power up the radio after sleeping + radio.stopListening(); // First, stop listening so we can talk. + + unsigned long time = millis(); // Take the time, and send it. + printf("Now sending... %lu \n\r",time); + + radio.write( &time, sizeof(unsigned long) ); + + radio.startListening(); // Now, continue listening + + unsigned long started_waiting_at = millis(); // Wait here until we get a response, or timeout (250ms) + bool timeout = false; + while ( ! radio.available() ){ + if (millis() - started_waiting_at > 250 ){ // Break out of the while loop if nothing available + timeout = true; + break; + } + } + + if ( timeout ) { // Describe the results + printf("Failed, response timed out.\n\r"); + }else{ + unsigned long got_time; // Grab the response, compare, and send to debugging spew + radio.read( &got_time, sizeof(unsigned long) ); + + printf("Got response %lu, round-trip delay: %lu\n\r",got_time,millis()-got_time); + } + + // Shut down the system + delay(500); // Experiment with some delay here to see if it has an effect + // Power down the radio. + radio.powerDown(); // NOTE: The radio MUST be powered back up again manually + + // Sleep the MCU. + do_sleep(); + + + } + + + // Pong back role. Receive each packet, dump it out, and send it back + if ( role == role_pong_back ) { + + if ( radio.available() ) { // if there is data ready + + unsigned long got_time; + while (radio.available()) { // Dump the payloads until we've gotten everything + radio.read( &got_time, sizeof(unsigned long) ); // Get the payload, and see if this was the last one. + // Spew it. Include our time, because the ping_out millis counter is unreliable + printf("Got payload %lu @ %lu...",got_time,millis()); // due to it sleeping + } + + radio.stopListening(); // First, stop listening so we can talk + radio.write( &got_time, sizeof(unsigned long) ); // Send the final one back. + printf("Sent response.\n\r"); + radio.startListening(); // Now, resume listening so we catch the next packets. + }else{ + Serial.println("Sleeping"); + delay(50); // Delay so the serial data can print out + do_sleep(); + + } + } +} + +void wakeUp(){ + sleep_disable(); +} + +// Sleep helpers + +//Prescaler values +// 0=16ms, 1=32ms,2=64ms,3=125ms,4=250ms,5=500ms +// 6=1 sec,7=2 sec, 8=4 sec, 9= 8sec + +void setup_watchdog(uint8_t prescalar){ + + uint8_t wdtcsr = prescalar & 7; + if ( prescalar & 8 ) + wdtcsr |= _BV(WDP3); + MCUSR &= ~_BV(WDRF); // Clear the WD System Reset Flag + WDTCSR = _BV(WDCE) | _BV(WDE); // Write the WD Change enable bit to enable changing the prescaler and enable system reset + WDTCSR = _BV(WDCE) | wdtcsr | _BV(WDIE); // Write the prescalar bits (how long to sleep, enable the interrupt to wake the MCU +} + +ISR(WDT_vect) +{ + //--sleep_cycles_remaining; + Serial.println("WDT"); +} + +void do_sleep(void) +{ + set_sleep_mode(SLEEP_MODE_PWR_DOWN); // sleep mode is set here + sleep_enable(); + attachInterrupt(0,wakeUp,LOW); + WDTCSR |= _BV(WDIE); + sleep_mode(); // System sleeps here + // The WDT_vect interrupt wakes the MCU from here + sleep_disable(); // System continues execution here when watchdog timed out + detachInterrupt(0); + WDTCSR &= ~_BV(WDIE); +} diff --git a/RC_Turrel/libraries/RF24-master/examples/pingpair_sleepy/pingpair_sleepy.pde b/RC_Turrel/libraries/RF24-master/examples/pingpair_sleepy/pingpair_sleepy.pde new file mode 100644 index 0000000..4e1af31 --- /dev/null +++ b/RC_Turrel/libraries/RF24-master/examples/pingpair_sleepy/pingpair_sleepy.pde @@ -0,0 +1,288 @@ +/* + Copyright (C) 2011 J. Coliz + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + */ + +/** + * Example RF Radio Ping Pair which Sleeps between Sends + * + * This is an example of how to use the RF24 class to create a battery- + * efficient system. It is just like the pingpair.pde example, but the + * ping node powers down the radio and sleeps the MCU after every + * ping/pong cycle. + * + * As with the pingpair.pde example, write this sketch to two different nodes, + * connect the role_pin to ground on one. The ping node sends the current + * time to the pong node, which responds by sending the value back. The ping + * node can then see how long the whole cycle took. + */ + +#include +#include +#include +#include "RF24.h" +#include "printf.h" + +// +// Hardware configuration +// + +// Set up nRF24L01 radio on SPI bus plus pins 9 & 10 + +RF24 radio(9,10); + +// sets the role of this unit in hardware. Connect to GND to be the 'pong' receiver +// Leave open to be the 'ping' transmitter +const int role_pin = 7; + +// +// Topology +// + +// Radio pipe addresses for the 2 nodes to communicate. +const uint64_t pipes[2] = { 0xF0F0F0F0E1LL, 0xF0F0F0F0D2LL }; + +// +// Role management +// +// Set up role. This sketch uses the same software for all the nodes +// in this system. Doing so greatly simplifies testing. The hardware itself specifies +// which node it is. +// +// This is done through the role_pin +// + +// The various roles supported by this sketch +typedef enum { role_ping_out = 1, role_pong_back } role_e; + +// The debug-friendly names of those roles +const char* role_friendly_name[] = { "invalid", "Ping out", "Pong back"}; + +// The role of the current running sketch +role_e role; + +// +// Sleep declarations +// + +typedef enum { wdt_16ms = 0, wdt_32ms, wdt_64ms, wdt_128ms, wdt_250ms, wdt_500ms, wdt_1s, wdt_2s, wdt_4s, wdt_8s } wdt_prescalar_e; + +void setup_watchdog(uint8_t prescalar); +void do_sleep(void); + +const short sleep_cycles_per_transmission = 4; +volatile short sleep_cycles_remaining = sleep_cycles_per_transmission; + +// +// Normal operation +// + +void setup(void) +{ + // + // Role + // + + // set up the role pin + pinMode(role_pin, INPUT); + digitalWrite(role_pin,HIGH); + delay(20); // Just to get a solid reading on the role pin + + // read the address pin, establish our role + if ( digitalRead(role_pin) ) + role = role_ping_out; + else + role = role_pong_back; + + // + // Print preamble + // + + Serial.begin(57600); + printf_begin(); + printf("\n\rRF24/examples/pingpair_sleepy/\n\r"); + printf("ROLE: %s\n\r",role_friendly_name[role]); + + // + // Prepare sleep parameters + // + + // Only the ping out role sleeps. Wake up every 4s to send a ping + if ( role == role_ping_out ) + setup_watchdog(wdt_1s); + + // + // Setup and configure rf radio + // + + radio.begin(); + + // + // Open pipes to other nodes for communication + // + + // This simple sketch opens two pipes for these two nodes to communicate + // back and forth. + // Open 'our' pipe for writing + // Open the 'other' pipe for reading, in position #1 (we can have up to 5 pipes open for reading) + + if ( role == role_ping_out ) + { + radio.openWritingPipe(pipes[0]); + radio.openReadingPipe(1,pipes[1]); + } + else + { + radio.openWritingPipe(pipes[1]); + radio.openReadingPipe(1,pipes[0]); + } + + // + // Start listening + // + + radio.startListening(); + + // + // Dump the configuration of the rf unit for debugging + // + + radio.printDetails(); +} + +void loop(void) +{ + // + // Ping out role. Repeatedly send the current time + // + + if (role == role_ping_out) + { + // First, stop listening so we can talk. + radio.stopListening(); + + // Take the time, and send it. This will block until complete + unsigned long time = millis(); + printf("Now sending %lu...",time); + radio.write( &time, sizeof(unsigned long) ); + + // Now, continue listening + radio.startListening(); + + // Wait here until we get a response, or timeout (250ms) + unsigned long started_waiting_at = millis(); + bool timeout = false; + while ( ! radio.available() && ! timeout ) + if (millis() - started_waiting_at > 250 ) + timeout = true; + + // Describe the results + if ( timeout ) + { + printf("Failed, response timed out.\n\r"); + } + else + { + // Grab the response, compare, and send to debugging spew + unsigned long got_time; + radio.read( &got_time, sizeof(unsigned long) ); + + // Spew it + printf("Got response %lu, round-trip delay: %lu\n\r",got_time,millis()-got_time); + } + + // + // Shut down the system + // + + // Experiment with some delay here to see if it has an effect + delay(500); + + // Power down the radio. Note that the radio will get powered back up + // on the next write() call. + radio.powerDown(); + + // Sleep the MCU. The watchdog timer will awaken in a short while, and + // continue execution here. + while( sleep_cycles_remaining ) + do_sleep(); + + sleep_cycles_remaining = sleep_cycles_per_transmission; + } + + // + // Pong back role. Receive each packet, dump it out, and send it back + // + // This is untouched from the pingpair example. + // + + if ( role == role_pong_back ) + { + // if there is data ready + if ( radio.available() ) + { + // Dump the payloads until we've gotten everything + unsigned long got_time; + bool done = false; + while (!done) + { + // Fetch the payload, and see if this was the last one. + done = radio.read( &got_time, sizeof(unsigned long) ); + + // Spew it. Include our time, because the ping_out millis counter is unreliable + // due to it sleeping + printf("Got payload %lu @ %lu...",got_time,millis()); + } + + // First, stop listening so we can talk + radio.stopListening(); + + // Send the final one back. + radio.write( &got_time, sizeof(unsigned long) ); + printf("Sent response.\n\r"); + + // Now, resume listening so we catch the next packets. + radio.startListening(); + } + } +} + +// +// Sleep helpers +// + +// 0=16ms, 1=32ms,2=64ms,3=125ms,4=250ms,5=500ms +// 6=1 sec,7=2 sec, 8=4 sec, 9= 8sec + +void setup_watchdog(uint8_t prescalar) +{ + prescalar = min(9,prescalar); + uint8_t wdtcsr = prescalar & 7; + if ( prescalar & 8 ) + wdtcsr |= _BV(WDP3); + + MCUSR &= ~_BV(WDRF); + WDTCSR = _BV(WDCE) | _BV(WDE); + WDTCSR = _BV(WDCE) | wdtcsr | _BV(WDIE); +} + +ISR(WDT_vect) +{ + --sleep_cycles_remaining; +} + +void do_sleep(void) +{ + set_sleep_mode(SLEEP_MODE_PWR_DOWN); // sleep mode is set here + sleep_enable(); + + sleep_mode(); // System sleeps here + + sleep_disable(); // System continues execution here when watchdog timed out + radio.powerUp() ; +} + +// vim:ai:cin:sts=2 sw=2 ft=cpp diff --git a/RC_Turrel/libraries/RF24-master/examples/pingpair_sleepy/printf.h b/RC_Turrel/libraries/RF24-master/examples/pingpair_sleepy/printf.h new file mode 100644 index 0000000..1a67f2b --- /dev/null +++ b/RC_Turrel/libraries/RF24-master/examples/pingpair_sleepy/printf.h @@ -0,0 +1,40 @@ +/* + Copyright (C) 2011 J. Coliz + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + */ + +/** + * @file printf.h + * + * Setup necessary to direct stdout to the Arduino Serial library, which + * enables 'printf' + */ + +#ifndef __PRINTF_H__ +#define __PRINTF_H__ + +<<<<<<< HEAD +#ifdef ARDUINO + +======= +>>>>>>> 828add79a5375479cd29a7433c598b8ce56ee60b +int serial_putc( char c, FILE * ) +{ + Serial.write( c ); + + return c; +} + +void printf_begin(void) +{ + fdevopen( &serial_putc, 0 ); +} + +#else +#error This example is only for use on Arduino. +#endif // ARDUINO + +#endif // __PRINTF_H__ diff --git a/RC_Turrel/libraries/RF24-master/examples/scanner/Jamfile b/RC_Turrel/libraries/RF24-master/examples/scanner/Jamfile new file mode 100644 index 0000000..1bf541e --- /dev/null +++ b/RC_Turrel/libraries/RF24-master/examples/scanner/Jamfile @@ -0,0 +1,210 @@ +# (1) Project Information + +PROJECT_LIBS = SPI RF24 ; + +# (2) Board Information + +UPLOAD_PROTOCOL ?= stk500v1 ; +UPLOAD_SPEED ?= 57600 ; +MCU ?= atmega328p ; +F_CPU ?= 16000000 ; +CORE ?= arduino ; +VARIANT ?= standard ; +ARDUINO_VERSION ?= 100 ; + +# (3) USB Ports + +PORTS = p4 p6 p9 u0 u1 u2 ; +PORT_p6 = /dev/tty.usbserial-A600eHIs ; +PORT_p4 = /dev/tty.usbserial-A40081RP ; +PORT_p9 = /dev/tty.usbserial-A9007LmI ; +PORT_u0 = /dev/ttyUSB0 ; +PORT_u1 = /dev/ttyUSB1 ; +PORT_u2 = /dev/ttyUSB2 ; + +# (4) Location of AVR tools +# +# This configuration assumes using avr-tools that were obtained separate from the Arduino +# distribution. + +if $(OS) = MACOSX +{ + AVR_BIN = /usr/local/avrtools/bin ; + AVR_ETC = /usr/local/avrtools/etc ; + AVR_INCLUDE = /usr/local/avrtools/include ; +} +else +{ + AVR_BIN = /usr/bin ; + AVR_INCLUDE = /usr/lib/avr/include ; + AVR_ETC = /etc ; +} + +# (5) Directories where Arduino core and libraries are located + +ARDUINO_DIR ?= /opt/Arduino ; +ARDUINO_CORE = $(ARDUINO_DIR)/hardware/arduino/cores/$(CORE) $(ARDUINO_DIR)/hardware/arduino/variants/$(VARIANT) ; +ARDUINO_LIB = $(ARDUINO_DIR)/libraries ; +SKETCH_LIB = $(HOME)/Source/Arduino/libraries ; + +# +# -------------------------------------------------- +# Below this line usually never needs to be modified +# + +# Tool locations + +CC = $(AVR_BIN)/avr-gcc ; +C++ = $(AVR_BIN)/avr-g++ ; +LINK = $(AVR_BIN)/avr-gcc ; +OBJCOPY = $(AVR_BIN)/avr-objcopy ; +AVRDUDE = $(AVR_BIN)/avrdude ; + +# Flags + +DEFINES += F_CPU=$(F_CPU)L ARDUINO=$(ARDUINO_VERSION) VERSION_H ; +OPTIM = -Os ; +CCFLAGS = -Wall -Wextra -mmcu=$(MCU) -ffunction-sections -fdata-sections ; +C++FLAGS = $(CCFLAGS) -fno-exceptions -fno-strict-aliasing ; +LINKFLAGS = $(OPTIM) -lm -Wl,--gc-sections -mmcu=$(MCU) ; +AVRDUDEFLAGS = -V -F -D -C $(AVR_ETC)/avrdude.conf -p $(MCU) -c $(UPLOAD_PROTOCOL) -b $(UPLOAD_SPEED) ; + +# Search everywhere for headers + +HDRS = $(PWD) $(AVR_INCLUDE) $(ARDUINO_CORE) $(ARDUINO_LIB)/$(PROJECT_LIBS) $(ARDUINO_LIB)/$(PROJECT_LIBS)/utility $(SKETCH_LIB)/$(PROJECT_LIBS) ; + +# Output locations + +LOCATE_TARGET = $(F_CPU) ; +LOCATE_SOURCE = $(F_CPU) ; + +# +# Custom rules +# + +rule GitVersion +{ + Always $(<) ; + Depends all : $(<) ; +} + +actions GitVersion +{ + echo "const char program_version[] = \"\\" > $(<) + git log -1 --pretty=format:%h >> $(<) + echo "\";" >> $(<) +} + +GitVersion version.h ; + +rule Pde +{ + Depends $(<) : $(>) ; + MakeLocate $(<) : $(LOCATE_SOURCE) ; + Clean clean : $(<) ; +} + +if ( $(ARDUINO_VERSION) < 100 ) +{ + ARDUINO_H = WProgram.h ; +} +else +{ + ARDUINO_H = Arduino.h ; +} + +actions Pde +{ + echo "#include <$(ARDUINO_H)>" > $(<) + echo "#line 1 \"$(>)\"" >> $(<) + cat $(>) >> $(<) +} + +rule C++Pde +{ + local _CPP = $(>:B).cpp ; + Pde $(_CPP) : $(>) ; + C++ $(<) : $(_CPP) ; +} + +rule UserObject +{ + switch $(>:S) + { + case .ino : C++Pde $(<) : $(>) ; + case .pde : C++Pde $(<) : $(>) ; + } +} + +rule Objects +{ + local _i ; + + for _i in [ FGristFiles $(<) ] + { + local _b = $(_i:B)$(SUFOBJ) ; + local _o = $(_b:G=$(SOURCE_GRIST:E)) ; + Object $(_o) : $(_i) ; + Depends obj : $(_o) ; + } +} + +rule Main +{ + MainFromObjects $(<) : $(>:B)$(SUFOBJ) ; + Objects $(>) ; +} + +rule Hex +{ + Depends $(<) : $(>) ; + MakeLocate $(<) : $(LOCATE_TARGET) ; + Depends hex : $(<) ; + Clean clean : $(<) ; +} + +actions Hex +{ + $(OBJCOPY) -O ihex -R .eeprom $(>) $(<) +} + +rule Upload +{ + Depends $(1) : $(2) ; + Depends $(2) : $(3) ; + NotFile $(1) ; + Always $(1) ; + Always $(2) ; + UploadAction $(2) : $(3) ; +} + +actions UploadAction +{ + $(AVRDUDE) $(AVRDUDEFLAGS) -P $(<) $(AVRDUDE_WRITE_FLASH) -U flash:w:$(>):i +} + +# +# Targets +# + +# Grab everything from the core directory +CORE_MODULES = [ GLOB $(ARDUINO_CORE) : *.c *.cpp ] ; + +# Grab everything from libraries. To avoid this "grab everything" behaviour, you +# can specify specific modules to pick up in PROJECT_MODULES +LIB_MODULES = [ GLOB $(ARDUINO_LIB)/$(PROJECT_LIBS) $(ARDUINO_LIB)/$(PROJECT_LIBS)/utility $(SKETCH_LIB)/$(PROJECT_LIBS) : *.cpp *.c ] ; + +# Grab everything from the current dir +PROJECT_MODULES += [ GLOB $(PWD) : *.c *.cpp *.pde *.ino ] ; + +# Main output executable +MAIN = $(PWD:B).elf ; + +Main $(MAIN) : $(CORE_MODULES) $(LIB_MODULES) $(PROJECT_MODULES) ; +Hex $(MAIN:B).hex : $(MAIN) ; + +# Upload targets +for _p in $(PORTS) +{ + Upload $(_p) : $(PORT_$(_p)) : $(MAIN:B).hex ; +} diff --git a/RC_Turrel/libraries/RF24-master/examples/scanner/output/core.a b/RC_Turrel/libraries/RF24-master/examples/scanner/output/core.a new file mode 100644 index 0000000..6ae105d Binary files /dev/null and b/RC_Turrel/libraries/RF24-master/examples/scanner/output/core.a differ diff --git a/RC_Turrel/libraries/RF24-master/examples/scanner/output/scanner.cpp b/RC_Turrel/libraries/RF24-master/examples/scanner/output/scanner.cpp new file mode 100644 index 0000000..5eb1627 --- /dev/null +++ b/RC_Turrel/libraries/RF24-master/examples/scanner/output/scanner.cpp @@ -0,0 +1,128 @@ +#include +#line 1 "scanner.pde" + +/* + Copyright (C) 2011 James Coliz, Jr. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + */ + +/** + * Channel scanner + * + * Example to detect interference on the various channels available. + * This is a good diagnostic tool to check whether you're picking a + * good channel for your application. + * + * Inspired by cpixip. + * See http://arduino.cc/forum/index.php/topic,54795.0.html + */ + +#include +#include "nRF24L01.h" +#include "RF24.h" +#include "printf.h" + +// +// Hardware configuration +// + +// Set up nRF24L01 radio on SPI bus plus pins 8 & 9 + +RF24 radio(8,9); + +// +// Channel info +// + +const short num_channels = 128; +short values[num_channels]; + +// +// Setup +// + +void setup(void) +{ + // + // Print preamble + // + + Serial.begin(57600); + printf_begin(); + printf("\n\rRF24/examples/scanner/\n\r"); + + // + // Setup and configure rf radio + // + + radio.begin(); + radio.setAutoAck(false); + + // Get into standby mode + radio.startListening(); + radio.stopListening(); + + // Print out header, high then low digit + int i = 0; + while ( i < num_channels ) + { + printf("%x",i>>4); + ++i; + } + printf("\n\r"); + i = 0; + while ( i < num_channels ) + { + printf("%x",i&0xf); + ++i; + } + printf("\n\r"); +} + +// +// Loop +// + +const short num_reps = 100; + +void loop(void) +{ + // Clear measurement values + memset(values,0,num_channels); + + // Scan all channels num_reps times + int rep_counter = num_reps; + while (rep_counter--) + { + int i = num_channels; + while (i--) + { + // Select this channel + radio.setChannel(i); + + // Listen for a little + radio.startListening(); + delayMicroseconds(128); + radio.stopListening(); + + // Did we get a carrier? + if ( radio.testCarrier() ) + ++values[i]; + } + } + + // Print out channel measurements, clamped to a single hex digit + int i = 0; + while ( i < num_channels ) + { + printf("%x",min(0xf,values[i]&0xf)); + ++i; + } + printf("\n\r"); +} + + +// vim:ai:cin:sts=2 sw=2 ft=cpp diff --git a/RC_Turrel/libraries/RF24-master/examples/scanner/output/scanner.elf b/RC_Turrel/libraries/RF24-master/examples/scanner/output/scanner.elf new file mode 100644 index 0000000..5e0f4b1 Binary files /dev/null and b/RC_Turrel/libraries/RF24-master/examples/scanner/output/scanner.elf differ diff --git a/RC_Turrel/libraries/RF24-master/examples/scanner/output/scanner.hex b/RC_Turrel/libraries/RF24-master/examples/scanner/output/scanner.hex new file mode 100644 index 0000000..45c37db --- /dev/null +++ b/RC_Turrel/libraries/RF24-master/examples/scanner/output/scanner.hex @@ -0,0 +1,325 @@ +:100000000C9463000C948B000C948B000C948B006C +:100010000C948B000C948B000C948B000C948B0034 +:100020000C948B000C948B000C948B000C948B0024 +:100030000C948B000C948B000C948B000C948B0014 +:100040000C948F050C948B000C9423060C948B005D +:100050000C948B000C948B000C948B000C948B00F4 +:100060000C948B000C948B000000000024002700EF +:100070002A0000000000250028002B0000000000DE +:1000800023002600290004040404040404040202DA +:100090000202020203030303030301020408102007 +:1000A0004080010204081020010204081020000012 +:1000B0000007000201000003040600000000000029 +:1000C000000090043B0711241FBECFEFD8E0DEBF35 +:1000D000CDBF11E0A0E0B1E0E6EFF3E102C0059092 +:1000E0000D92AA33B107D9F712E0AAE3B1E001C03B +:1000F0001D92A13FB107E1F710E0C6ECD0E004C0CB +:100100002297FE010E94F509C23CD107C9F70E945F +:100110001C060C94F9090C9400000F931F93CF93C5 +:10012000DF938C01EB01009731F46115710519F42F +:1001300020E030E038C081E090E06EE070E00E94A6 +:10014000CB02FC019C01009771F180E8838320972A +:1001500071F0D387C28781E883838091E702909111 +:10016000E802892B21F4F093E802E093E7020115FD +:100170001105C9F011870087838182608383809194 +:10018000E9029091EA02892B71F4F093EA02E0937C +:10019000E9028091EB029091EC02892B21F4F0931B +:1001A000EC02E093EB02C901DF91CF911F910F9117 +:1001B0000895A0E0B0E0EFEDF0E00C94CC09FE0172 +:1001C0003596619171918091E9029091EA02AF01B7 +:1001D0000E94EE002096E2E00C94E809ABE0B0E06B +:1001E000E4EFF0E00C94BC093C012B015A01FC0146 +:1001F00017821682838181FD03C06FEF7FEFC6C136 +:100200009AE0892E1E010894211C311CF3012381E0 +:10021000F20123FD859123FF81912F01882309F4A9 +:10022000B2C1853239F423FD859123FF81912F01DD +:10023000853229F490E0B3010E940604E7CF982F9D +:10024000FF24EE249924FFE1FF15D0F09B3269F0E2 +:100250009C3228F4903259F0933291F40EC09D32C2 +:1002600049F0903369F441E024C052E0F52A84E07B +:10027000F82A28C098E0F92A25C0E0E1FE2A22C029 +:10028000F7FC29C0892F80538A3070F4F6FE05C030 +:10029000989C902C1124980E15C0E89CE02C1124F9 +:1002A000E80EF0E2FF2A0EC09E3229F4F6FC6BC184 +:1002B00040E4F42A07C09C3619F450E8F52A02C03D +:1002C000983649F4F20123FD959123FF91912F0176 +:1002D000992309F0B8CF892F8554833018F08052C4 +:1002E000833038F444E050E0A40EB51E5FE3598338 +:1002F0000FC0933631F0933779F0933509F056C03B +:1003000020C0F5018081898342E050E0A40EB51E33 +:10031000610101E010E012C0F501C080D180F6FC5F +:1003200003C06FEF7FEF02C0692D70E042E050E044 +:10033000A40EB51EC6010E94FB038C015FE7F522E7 +:1003400014C0F501C080D180F6FC03C06FEF7FEFD1 +:1003500002C0692D70E042E050E0A40EB51EC60157 +:100360000E94E9038C0150E8F52AF3FE07C01AC089 +:1003700080E290E0B3010E940604EA948E2D90E0A2 +:1003800008171907A8F30EC0F601F7FC8591F7FED0 +:1003900081916F0190E0B3010E940604E110EA949C +:1003A000015010400115110579F7EAC0943611F09B +:1003B000993669F5F7FE08C0F50120813181428147 +:1003C000538184E090E00AC0F501808191819C0115 +:1003D000442737FD4095542F82E090E0A80EB91EC7 +:1003E0009FE6F92257FF09C0509540953095219519 +:1003F0003F4F4F4F5F4FE0E8FE2ACA01B901A1010C +:100400002AE030E00E943204D82ED21840C095373E +:1004100029F41F2D1F7E2AE030E01DC01F2D197FFB +:100420009F3661F0903720F4983509F0ACC00FC0CA +:10043000903739F0983709F0A6C004C028E030E0C2 +:100440000AC0106114FD146020E130E004C014FD06 +:10045000166020E132E017FF08C0F501608171816C +:100460008281938144E050E008C0F5018081918150 +:10047000BC0180E090E042E050E0A40EB51EA10176 +:100480000E943204D82ED2188FE7F82EF122F6FE01 +:100490000BC05EEFF522D91438F4F4FE07C0F2FC6D +:1004A00005C08FEEF82202C01D2D01C0192DF4FEEB +:1004B0000DC0FE01ED0DF11D8081803319F499EE20 +:1004C000F92208C01F5FF2FE05C003C08F2D867899 +:1004D00009F01F5F0F2DF3FC14C0F0FE0FC01E15B6 +:1004E00010F09D2C0BC09D2C9E0C911A1E2D06C049 +:1004F00080E290E0B3010E9406041F5F1E15C0F366 +:1005000004C01E1510F4E11A01C0EE2404FF0FC050 +:1005100080E390E0B3010E94060402FF1DC001FDCC +:1005200003C088E790E00EC088E590E00BC0802F04 +:10053000867891F001FF02C08BE201C080E2F7FCF7 +:100540008DE290E0B3010E94060406C080E390E0D3 +:10055000B3010E9406049A94D914C0F3DA94F1010D +:10056000ED0DF11D808190E0B3010E940604DD20B5 +:10057000A9F706C080E290E0B3010E940604EA9465 +:10058000EE20C1F743CEF30166817781CB012B9634 +:10059000E2E10C94D8090F931F93CF93DF93689FE8 +:1005A0008001699F100D789F100D1124C8010E94D1 +:1005B000E702EC01009729F060E070E0A8010E94DA +:1005C000F403CE01DF91CF911F910F910895CF9346 +:1005D000DF93BC018230910510F462E070E0A091DD +:1005E000EF02B091F002ED01E0E0F0E040E050E019 +:1005F00021C0888199818617970769F48A819B8138 +:10060000309719F09383828304C09093F002809313 +:10061000EF02FE0134C06817790738F4411551051F +:1006200019F08417950708F4AC01FE018A819B81BB +:100630009C01E9012097E9F641155105A9F1CA018C +:10064000861B970B049708F4BA01E0E0F0E02AC09B +:100650008D919C91119784179507F9F4641775078C +:1006600081F412968D919C911397309719F0938392 +:10067000828304C09093F0028093EF02FD013296D2 +:100680004CC0CA01861B970BFD01E80FF91F61934F +:10069000719302978D939C9340C0FD018281938159 +:1006A0009C01D9011097A1F68091ED029091EE0284 +:1006B000892B41F480912301909124019093EE02C3 +:1006C0008093ED024091250150912601411551057D +:1006D00041F44DB75EB78091210190912201481BF2 +:1006E000590B2091ED023091EE02CA01821B930B4F +:1006F0008617970780F0AB014E5F5F4F8417950711 +:1007000050F0420F531F5093EE024093ED02F90157 +:100710006193719302C0E0E0F0E0CF01DF91CF91EF +:100720000895CF93DF93009709F450C0EC0122970E +:100730001B821A82A091EF02B091F002109709F18A +:1007400040E050E0AC17BD0708F1BB83AA83FE016F +:1007500021913191E20FF31FAE17BF0779F48D910C +:100760009C911197280F391F2E5F3F4F39832883A3 +:1007700012968D919C9113979B838A834115510505 +:1007800071F4D093F002C093EF0220C012968D91C5 +:100790009C911397AD01009711F0DC01D3CFFA01C2 +:1007A000D383C28321913191E20FF31FCE17DF076C +:1007B00069F488819981280F391F2E5F3F4FFA0114 +:1007C000318320838A819B8193838283DF91CF91C0 +:1007D0000895FC010590615070400110D8F7809594 +:1007E00090958E0F9F1F0895DC0101C06D934150BD +:1007F0005040E0F70895FC016150704001900110F5 +:10080000D8F7809590958E0F9F1F08950F931F9393 +:10081000CF93DF938C01EB018B8181FF1BC082FFA3 +:100820000DC02E813F818C819D812817390764F48A +:10083000E881F9810193F983E88306C0E885F985A9 +:10084000802F0995892B31F48E819F8101969F839A +:100850008E8302C00FEF1FEFC801DF91CF911F9170 +:100860000F910895FA01AA27283051F1203181F122 +:10087000E8946F936E7F6E5F7F4F8F4F9F4FAF4FA8 +:10088000B1E03ED0B4E03CD0670F781F891F9A1FBB +:10089000A11D680F791F8A1F911DA11D6A0F711D6F +:1008A000811D911DA11D20D009F468943F912AE07B +:1008B000269F11243019305D3193DEF6CF01089563 +:1008C000462F4770405D4193B3E00FD0C9F7F6CF94 +:1008D000462F4F70405D4A3318F0495D31FD40525C +:1008E000419302D0A9F7EACFB4E0A69597958795F2 +:1008F00077956795BA95C9F70097610571050895D1 +:100900009B01AC010A2E069457954795379527957C +:10091000BA95C9F7620F731F841F951FA01D089514 +:100920008AE391E068E049E00E9475070895FF922C +:100930000F931F93CF93DF9380E8E7E4F1E0DF01AB +:100940001D928A95E9F704E610E021C08AE391E060 +:100950006F2D0E94F2078AE391E00E94840880E8EC +:1009600090E00E94D7058AE391E00E947C078AE329 +:1009700091E00E944608882329F088819981019698 +:10098000998388832297FA94BFEFFB16F9F60150FA +:100990001040EFEF0F3F1E0729F0C5E4D2E08FE7CC +:1009A000F82ED4CFC7E4D1E000E011E000D000D0B1 +:1009B000ADB7BEB712961C930E931197899199917A +:1009C0008F70907014969C938E9313970E94D90009 +:1009D0000F900F900F900F90B2E0C734DB0731F704 +:1009E00000D083E091E0EDB7FEB7928381830E944F +:1009F000D9000F900F90DF91CF911F910F91FF9031 +:100A0000089580E895E060E070E00E948D00089510 +:100A10000F931F93CF93DF9384ED92E040E051EE6C +:100A200060E070E00E9454060E94010500D086E05C +:100A300091E0EDB7FEB7928381830E94D9000F90B9 +:100A40000F908AE391E00E944B088AE391E060E016 +:100A50000E94E8078AE391E00E9484088AE391E01B +:100A60000E947C07C0E0D0E000E011E000D000D0A0 +:100A7000EDB7FEB712830183CE0124E095958795EB +:100A80002A95E1F7948383830E94D90021960F90E1 +:100A90000F900F900F90C038D10541F700D083E040 +:100AA00091E0EDB7FEB7928381830E94D900C0E048 +:100AB000D0E00F900F9000D000D0EDB7FEB70183CB +:100AC0001283CE018F709070948383830E94D9002B +:100AD00021960F900F900F900F90C038D10559F7C5 +:100AE00000D083E091E0EDB7FEB7928381830E944E +:100AF000D9000F900F90DF91CF911F910F91089522 +:100B00000F931F93082F84ED92E0602F0E94280717 +:100B1000112707FD1095C8011F910F9108951F928D +:100B20000F920FB60F9211242F933F938F939F93A1 +:100B3000AF93BF9380914B0290914C02A0914D02D4 +:100B4000B0914E0230914F020196A11DB11D232F8D +:100B50002D5F2D3720F02D570196A11DB11D20933B +:100B60004F0280934B0290934C02A0934D02B0939E +:100B70004E028091470290914802A0914902B091A3 +:100B80004A020196A11DB11D80934702909348022D +:100B9000A0934902B0934A02BF91AF919F918F9168 +:100BA0003F912F910F900FBE0F901F9018950197B6 +:100BB00039F0880F991F880F991F02970197F1F755 +:100BC0000895789484B5826084BD84B5816084BDC5 +:100BD00085B5826085BD85B5816085BDEEE6F0E0B6 +:100BE000808181608083E1E8F0E010828081826012 +:100BF0008083808181608083E0E8F0E08081816093 +:100C00008083E1EBF0E0808184608083E0EBF0E0C2 +:100C1000808181608083EAE7F0E080818460808366 +:100C20008081826080838081816080838081806810 +:100C300080831092C10008950E94E1050E9408057A +:100C40000E949704FDCF1F920F920FB60F921124AE +:100C50002F933F934F938F939F93EF93FF934091E5 +:100C6000C600E091D002F091D10231969F012F771A +:100C7000307031978091D2029091D30228173907B2 +:100C800039F0E05BFD4F40833093D1022093D002D6 +:100C9000FF91EF919F918F914F913F912F910F90E5 +:100CA0000FBE0F901F901895AF92BF92DF92EF92F8 +:100CB000FF920F931F93CF93DF93EC017A018B0187 +:100CC000DD24403081EE580780E0680780E0780737 +:100CD00011F0DD24D39491E0A92EB12CE885F9859B +:100CE000DD2069F0C5010A8802C0880F991F0A94A7 +:100CF000E2F7808360E079E08DE390E005C0108248 +:100D000060E874E88EE190E0A80197010E949A09DA +:100D10002150304040405040569547953795279593 +:100D200080E12030380720F0DD2011F0DD24D6CF1F +:100D3000EC81FD813083EE81FF812083EA85FB8594 +:100D4000208141E050E0CA010E8402C0880F991F43 +:100D50000A94E2F7282B2083EA85FB852081CA01CB +:100D60000F8402C0880F991F0A94E2F7282B208372 +:100D7000EA85FB858081088802C0440F551F0A94CC +:100D8000E2F7842B8083DF91CF911F910F91FF9029 +:100D9000EF90DF90BF90AF900895DC011296ED9137 +:100DA000FC911397E058FF4F2191319180819181FF +:100DB000281B390B2F773070C9010895DC0112967A +:100DC000ED91FC911397EE57FF4F20813181929165 +:100DD0008291E058F0408217930719F42FEF3FEF0C +:100DE00005C0E20FF31F8081282F30E0C90108956C +:100DF000DC011296ED91FC911397DF01AE57BF4FC6 +:100E00002D913C911197E058FF4F80819181E058DE +:100E1000F0408217930719F42FEF3FEF0BC0E20F5A +:100E2000F31F80812F5F3F4F2F7730702D933C93BE +:100E3000282F30E0C9010895DC011296ED91FC9154 +:100E40001397EE57FF4F808191819293829308957B +:100E5000FC01A085B18521898C9190E0022E02C011 +:100E6000959587950A94E2F780FFF6CF0484F5857F +:100E7000E02D608308958BE291E09093D5028093FA +:100E8000D40280E592E09093D7028093D60285EC5D +:100E900090E09093D9028093D80284EC90E09093F4 +:100EA000DB028093DA0280EC90E09093DD02809385 +:100EB000DC0281EC90E09093DF028093DE0286EC0E +:100EC00090E09093E1028093E00284E08093E2025C +:100ED00083E08093E30287E08093E40285E08093DF +:100EE000E50281E08093E6020895FC01608341837E +:100EF00080E2828313820895FC01808160E00E9479 +:100F0000CD080895FF920F931F938C01F62E80E079 +:100F10000E94650985E00E946A09F80181816F2DB0 +:100F20000E94CD081F910F91FF9008951F93CF93BA +:100F3000DF93EC0160E070E00E94820781EE8EBDDD +:100F40000DB407FEFDCF1EB5CE0161E070E00E943A +:100F50008207812FDF91CF911F9108951F93CF9327 +:100F6000DF93EC0160E070E00E94820782EE8EBDAC +:100F70000DB407FEFDCF1EB5CE0161E070E00E940A +:100F80008207812FDF91CF911F9108950F931F93B7 +:100F9000CF93DF93EC01162F042F60E070E00E94E6 +:100FA00082071F7110621EBD0DB407FEFDCF1EB576 +:100FB0000EBD0DB407FEFDCF8EB5CE0161E070E031 +:100FC0000E948207812FDF91CF911F910F91089589 +:100FD000662319F061E04FE302C061E040E00E9447 +:100FE000C6070895462F603808F04FE765E00E9475 +:100FF000C6070895EF92FF920F931F93CF93DF934D +:101000007C01162FEA01022F60E070E00E94820747 +:101010001F7110621EBD0DB407FEFDCF1EB508C0C6 +:1010200088818EBD0DB407FEFDCF21968EB501508F +:101030000023B1F7C70161E070E00E948207812FB1 +:10104000DF91CF911F910F91FF90EF9008951F9323 +:10105000CF93DF93EC01162F60E070E00E948207CF +:101060001F711EBD0DB407FEFDCF8EB58FEF8EBD77 +:101070000DB407FEFDCF1EB5CE0161E070E00E9409 +:101080008207812FDF91CF911F91089569E00E941F +:101090002708817008950F931F938C01FC018081B4 +:1010A00061E00E94A708F801818161E00E94A70821 +:1010B000F801808160E00E94CD08C80161E070E025 +:1010C0000E9482070E947B0981E00E945C0980E007 +:1010D0000E94650985E00E946A09C80164E04FEF3B +:1010E0000E94C607C80167E040E70E94C607C80122 +:1010F0000E94AE07C8010E949607C80161E00E94E5 +:10110000F2071F910F9108950F931F938C0160E0D8 +:101110004BE00E94C607C80167E040E70E94C6078F +:10112000A8014B5F5F4FC8016AE025E00E94FA0703 +:10113000C8010E94AE07F801808161E00E94CD08DD +:1011400082E890E00E94D7051F910F910895482FE3 +:1011500050E0CA0186569F4FFC0124914A575F4FC9 +:10116000FA0184918823C1F0E82FF0E0EE0FFF1F11 +:10117000E859FF4FA591B491662341F49FB7F894C5 +:101180008C91209582238C939FBF08959FB7F894EC +:101190008C91822B8C939FBF0895482F50E0CA01F9 +:1011A00082559F4FFC012491CA0186569F4FFC0136 +:1011B00034914A575F4FFA019491992309F444C03E +:1011C000222351F1233071F0243028F42130A1F092 +:1011D000223011F514C02630B1F02730C1F0243090 +:1011E000D9F404C0809180008F7703C08091800083 +:1011F0008F7D8093800010C084B58F7702C084B546 +:101200008F7D84BD09C08091B0008F7703C080912D +:10121000B0008F7D8093B000E92FF0E0EE0FFF1F4C +:10122000EE58FF4FA591B491662341F49FB7F8940F +:101230008C91309583238C939FBF08959FB7F8942A +:101240008C91832B8C939FBF08950F931F93CF9303 +:10125000DF938C01EB0109C02196D801ED91FC913F +:101260000190F081E02DC801099568816623A1F7FE +:10127000DF91CF911F910F910895EF92FF920F93FD +:101280001F93CF93DF938C017B01EA010CC0D70140 +:101290006D917D01D801ED91FC910190F081E02DDF +:1012A000C80109952197209791F7DF91CF911F9160 +:1012B0000F91FF90EF900895882319F48CB5806208 +:1012C00002C08CB58F7D8CBD08959CB5937F982B03 +:1012D0009CBD08952CB5382F33702C7F322B3CBD2C +:1012E0002DB590E0959587959595879581702E7F82 +:1012F000822B8DBD08958DE061E00E94A7088BE0F0 +:1013000061E00E94A7088AE061E00E94A7088DE0E2 +:1013100060E00E94CD088BE060E00E94CD088AE08A +:1013200061E00E94CD088CB580618CBD8CB5806475 +:101330008CBD0895A1E21A2EAA1BBB1BFD010DC096 +:10134000AA1FBB1FEE1FFF1FA217B307E407F50775 +:1013500020F0A21BB30BE40BF50B661F771F881F51 +:10136000991F1A9469F760957095809590959B01E7 +:10137000AC01BD01CF0108952F923F924F925F9231 +:101380006F927F928F929F92AF92BF92CF92DF9295 +:10139000EF92FF920F931F93CF93DF93CDB7DEB7FA +:1013A000CA1BDB0B0FB6F894DEBF0FBECDBF09948E +:1013B0002A88398848885F846E847D848C849B84E5 +:1013C000AA84B984C884DF80EE80FD800C811B81F3 +:1013D000AA81B981CE0FD11D0FB6F894DEBF0FBE22 +:1013E000CDBFED010895EE0FFF1F0590F491E02DA4 +:0613F0000994F894FFCF00 +:1013F6002578000A0D000A0D524632342F657861B1 +:101406006D706C65732F7363616E6E65722F0A0D56 +:10141600002000F102000000000000280725093D19 +:0A14260009CD06F806DE061C0700DB +:00000001FF diff --git a/RC_Turrel/libraries/RF24-master/examples/scanner/scanner.ino b/RC_Turrel/libraries/RF24-master/examples/scanner/scanner.ino new file mode 100644 index 0000000..e4aca24 --- /dev/null +++ b/RC_Turrel/libraries/RF24-master/examples/scanner/scanner.ino @@ -0,0 +1,126 @@ +/* + Copyright (C) 2011 J. Coliz + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + */ + +/** + * Channel scanner + * + * Example to detect interference on the various channels available. + * This is a good diagnostic tool to check whether you're picking a + * good channel for your application. + * + * Inspired by cpixip. + * See http://arduino.cc/forum/index.php/topic,54795.0.html + */ + +#include +#include "nRF24L01.h" +#include "RF24.h" +#include "printf.h" + +// +// Hardware configuration +// + +// Set up nRF24L01 radio on SPI bus plus pins 9 & 10 + +RF24 radio(9,10); + +// +// Channel info +// + +const uint8_t num_channels = 128; +uint8_t values[num_channels]; + +// +// Setup +// + +void setup(void) +{ + // + // Print preamble + // + + Serial.begin(57600); + printf_begin(); + printf("\n\rRF24/examples/scanner/\n\r"); + + // + // Setup and configure rf radio + // + + radio.begin(); + radio.setAutoAck(false); + + // Get into standby mode + radio.startListening(); + radio.stopListening(); + + // Print out header, high then low digit + int i = 0; + while ( i < num_channels ) + { + printf("%x",i>>4); + ++i; + } + printf("\n\r"); + i = 0; + while ( i < num_channels ) + { + printf("%x",i&0xf); + ++i; + } + printf("\n\r"); +} + +// +// Loop +// + +const int num_reps = 100; + +void loop(void) +{ + // Clear measurement values + memset(values,0,sizeof(values)); + + // Scan all channels num_reps times + int rep_counter = num_reps; + while (rep_counter--) + { + int i = num_channels; + while (i--) + { + // Select this channel + radio.setChannel(i); + + // Listen for a little + radio.startListening(); + delayMicroseconds(225); + + + // Did we get a carrier? + if ( radio.testCarrier() ){ + ++values[i]; + } + radio.stopListening(); + } + } + + // Print out channel measurements, clamped to a single hex digit + int i = 0; + while ( i < num_channels ) + { + printf("%x",min(0xf,values[i]&0xf)); + ++i; + } + printf("\n\r"); +} + +// vim:ai:cin:sts=2 sw=2 ft=cpp \ No newline at end of file diff --git a/RC_Turrel/libraries/RF24-master/examples/starping/Jamfile b/RC_Turrel/libraries/RF24-master/examples/starping/Jamfile new file mode 100644 index 0000000..de9b1f6 --- /dev/null +++ b/RC_Turrel/libraries/RF24-master/examples/starping/Jamfile @@ -0,0 +1,206 @@ +PROJECT_NAME = $(PWD:B) ; +PROJECT_DIR = . ; +PROJECT_LIBS = EEPROM SPI RF24 ; + +OUT_DIR = ojam ; +F_CPU = 16000000 ; +MCU = atmega328p ; +PORTS = /dev/tty.usbserial-A600eHIs /dev/tty.usbserial-A40081RP /dev/tty.usbserial-A9007LmI ; + +UPLOAD_RATE = 57600 ; +AVRDUDE_PROTOCOL = stk500v1 ; +COM = 33 ; + +# Host-specific overrides for locations +if $(OS) = MACOSX +{ +ARDUINO_VERSION = 22 ; +OLD_DIR = /opt/arduino-0021 ; +AVR_TOOLS_PATH = $(OLD_DIR)/hardware/tools/avr/bin ; +AVRDUDECONFIG_PATH = $(OLD_DIR)/hardware/tools/avr/etc ; +ARDUINO_DIR = /opt/Arduino ; +ARDUINO_AVR = /usr/lib/avr/include ; +} + +# Where is everything? +ARDUINO_VERSION ?= 22 ; +AVR_TOOLS_PATH ?= /usr/bin ; +ARDUINO_DIR ?= /opt/arduino-00$(ARDUINO_VERSION) ; +ARDUINO_AVR ?= $(ARDUINO_DIR)/hardware/tools/avr/avr/include/avr ; +AVRDUDECONFIG_PATH ?= $(ARDUINO_DIR)/hardware/tools ; +ARDUINO_CORE = $(ARDUINO_DIR)/hardware/arduino/cores/arduino ; +ARDUINO_LIB = $(ARDUINO_DIR)/libraries ; +SKETCH_LIB = $(HOME)/Source/Arduino/libraries ; +AVR_CC = $(AVR_TOOLS_PATH)/avr-gcc ; +AVR_CXX = $(AVR_TOOLS_PATH)/avr-g++ ; +AVR_LD = $(AVR_TOOLS_PATH)/avr-gcc ; +AVR_OBJCOPY = $(AVR_TOOLS_PATH)/avr-objcopy ; +AVRDUDE = $(AVR_TOOLS_PATH)/avrdude ; + +DEFINES = F_CPU=$(F_CPU)L ARDUINO=$(ARDUINO_VERSION) VERSION_H ; +CTUNING = -ffunction-sections -fdata-sections ; +CXXTUNING = -fno-exceptions -fno-strict-aliasing ; +CFLAGS = -Os -Wall -Wextra -mmcu=$(MCU) $(CTUNING) ; +CXXFLAGS = $(CFLAGS) $(CXXTUNING) ; +LDFLAGS = -Os -lm -Wl,--gc-sections -mmcu=atmega328p ; + +# Search everywhere for headers +HDRS = $(PROJECT_DIR) $(ARDUINO_AVR) $(ARDUINO_CORE) [ GLOB $(ARDUINO_LIB) $(SKETCH_LIB) : [^.]* ] ; + +# Grab everything from the core directory +CORE_MODULES = [ GLOB $(ARDUINO_CORE) : *.c *.cpp ] ; + +# Grab everything from libraries. To avoid this "grab everything" behaviour, you +# can specify specific modules to pick up in PROJECT_MODULES +LIB_MODULES = [ GLOB $(ARDUINO_LIB)/$(PROJECT_LIBS) $(SKETCH_LIB)/$(PROJECT_LIBS) : *.cpp ] ; + +# In addition to explicitly-specified program modules, pick up anything from the current +# dir. +PROJECT_MODULES += [ GLOB $(PROJECT_DIR) : *.c *.cpp *.pde ] ; + +# Shortcut for the out files +OUT = $(OUT_DIR)/$(PROJECT_NAME) ; + +# AvrDude setup +AVRDUDE_FLAGS = -V -F -D -C $(AVRDUDECONFIG_PATH)/avrdude.conf -p $(MCU) -c $(AVRDUDE_PROTOCOL) -b $(UPLOAD_RATE) ; + +rule GitVersion +{ + Always $(<) ; + Depends all : $(<) ; +} + +actions GitVersion +{ + echo "const char program_version[] = \"\\" > $(<) + git log -1 --pretty=format:%h >> $(<) + echo "\";" >> $(<) +} + +GitVersion version.h ; + +rule AvrCc +{ + Depends $(<) : $(>) ; + Depends $(<) : $(<:D) ; + Clean clean : $(<) ; + + CCHDRS on $(<) = [ on $(<) FIncludes $(HDRS) ] ; + CCDEFS on $(<) = [ on $(<) FDefines $(DEFINES) ] ; +} + +actions AvrCc +{ + $(AVR_CC) -c -o $(<) $(CCHDRS) $(CCDEFS) $(CFLAGS) $(>) +} + +rule AvrC++ +{ + Depends $(<) : $(>) ; + Depends $(<) : $(<:D) ; + Clean clean : $(<) ; + + CCHDRS on $(<) = [ on $(<) FIncludes $(HDRS) ] ; + CCDEFS on $(<) = [ on $(<) FDefines $(DEFINES) ] ; +} + +actions AvrC++ +{ + $(AVR_CXX) -c -o $(<) $(CCHDRS) $(CCDEFS) $(CXXFLAGS) $(>) +} + +rule Pde +{ + Depends $(<) : $(>) ; + Depends $(<) : $(<:D) ; + Clean clean : $(<) ; + +} + +actions Pde +{ + echo "#include " > $(<) + echo "#line 1 \"$(>)\"" >> $(<) + cat $(>) >> $(<) +} + +rule AvrPde +{ + local _CPP = $(OUT_DIR)/$(_I:B).cpp ; + Pde $(_CPP) : $(>) ; + AvrC++ $(<) : $(_CPP) ; +} + +rule AvrObject +{ + switch $(>:S) + { + case .c : AvrCc $(<) : $(>) ; + case .cpp : AvrC++ $(<) : $(>) ; + case .pde : AvrPde $(<) : $(>) ; + } +} + +rule AvrObjects +{ + for _I in $(<) + { + AvrObject $(OUT_DIR)/$(_I:B).o : $(_I) ; + } +} + +rule AvrMainFromObjects +{ + Depends $(<) : $(>) ; + Depends $(<) : $(<:D) ; + MkDir $(<:D) ; + Depends all : $(<) ; + Clean clean : $(<) ; +} + +actions AvrMainFromObjects +{ + $(AVR_LD) $(LDFLAGS) -o $(<) $(>) +} + +rule AvrMain +{ + AvrMainFromObjects $(<) : $(OUT_DIR)/$(>:B).o ; + AvrObjects $(>) ; +} + +rule AvrHex +{ + Depends $(<) : $(>) ; + Depends $(<) : $(<:D) ; + Depends hex : $(<) ; + Clean clean : $(<) ; +} + +actions AvrHex +{ + $(AVR_OBJCOPY) -O ihex -R .eeprom $(>) $(<) +} + +rule AvrUpload +{ + Depends $(1) : $(2) ; + Depends $(2) : $(3) ; + NotFile $(1) ; + Always $(1) ; + Always $(2) ; + AvrUploadAction $(2) : $(3) ; +} + +actions AvrUploadAction +{ + $(AVRDUDE) $(AVRDUDE_FLAGS) -P $(<) $(AVRDUDE_WRITE_FLASH) -U flash:w:$(>):i +} + +AvrMain $(OUT).elf : $(CORE_MODULES) $(LIB_MODULES) $(PROJECT_MODULES) ; +AvrHex $(OUT).hex : $(OUT).elf ; + +AvrUpload p6 : /dev/tty.usbserial-A600eHIs : $(OUT).hex ; +AvrUpload p4 : /dev/tty.usbserial-A40081RP : $(OUT).hex ; +AvrUpload p9 : /dev/tty.usbserial-A9007LmI : $(OUT).hex ; + diff --git a/RC_Turrel/libraries/RF24-master/examples/starping/printf.h b/RC_Turrel/libraries/RF24-master/examples/starping/printf.h new file mode 100644 index 0000000..1a67f2b --- /dev/null +++ b/RC_Turrel/libraries/RF24-master/examples/starping/printf.h @@ -0,0 +1,40 @@ +/* + Copyright (C) 2011 J. Coliz + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + */ + +/** + * @file printf.h + * + * Setup necessary to direct stdout to the Arduino Serial library, which + * enables 'printf' + */ + +#ifndef __PRINTF_H__ +#define __PRINTF_H__ + +<<<<<<< HEAD +#ifdef ARDUINO + +======= +>>>>>>> 828add79a5375479cd29a7433c598b8ce56ee60b +int serial_putc( char c, FILE * ) +{ + Serial.write( c ); + + return c; +} + +void printf_begin(void) +{ + fdevopen( &serial_putc, 0 ); +} + +#else +#error This example is only for use on Arduino. +#endif // ARDUINO + +#endif // __PRINTF_H__ diff --git a/RC_Turrel/libraries/RF24-master/examples/starping/starping.pde b/RC_Turrel/libraries/RF24-master/examples/starping/starping.pde new file mode 100644 index 0000000..4813a77 --- /dev/null +++ b/RC_Turrel/libraries/RF24-master/examples/starping/starping.pde @@ -0,0 +1,293 @@ +/* + Copyright (C) 2011 J. Coliz + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + */ + +/** + * Example RF Radio Ping Star Group + * + * This sketch is a more complex example of using the RF24 library for Arduino. + * Deploy this on up to six nodes. Set one as the 'pong receiver' by tying the + * role_pin low, and the others will be 'ping transmit' units. The ping units + * unit will send out the value of millis() once a second. The pong unit will + * respond back with a copy of the value. Each ping unit can get that response + * back, and determine how long the whole cycle took. + * + * This example requires a bit more complexity to determine which unit is which. + * The pong receiver is identified by having its role_pin tied to ground. + * The ping senders are further differentiated by a byte in eeprom. + */ + +#include +#include +#include "nRF24L01.h" +#include "RF24.h" +#include "printf.h" + +// +// Hardware configuration +// + +// Set up nRF24L01 radio on SPI bus plus pins 9 & 10 + +RF24 radio(9,10); + +// sets the role of this unit in hardware. Connect to GND to be the 'pong' receiver +// Leave open to be the 'pong' receiver. +const int role_pin = 7; + +// +// Topology +// + +// Radio pipe addresses for the nodes to communicate. Only ping nodes need +// dedicated pipes in this topology. Each ping node has a talking pipe +// that it will ping into, and a listening pipe that it will listen for +// the pong. The pong node listens on all the ping node talking pipes +// and sends the pong back on the sending node's specific listening pipe. + +const uint64_t talking_pipes[5] = { 0xF0F0F0F0D2LL, 0xF0F0F0F0C3LL, 0xF0F0F0F0B4LL, 0xF0F0F0F0A5LL, 0xF0F0F0F096LL }; +const uint64_t listening_pipes[5] = { 0x3A3A3A3AD2LL, 0x3A3A3A3AC3LL, 0x3A3A3A3AB4LL, 0x3A3A3A3AA5LL, 0x3A3A3A3A96LL }; + +// +// Role management +// +// Set up role. This sketch uses the same software for all the nodes +// in this system. Doing so greatly simplifies testing. The hardware itself specifies +// which node it is. +// +// This is done through the role_pin +// + +// The various roles supported by this sketch +typedef enum { role_invalid = 0, role_ping_out, role_pong_back } role_e; + +// The debug-friendly names of those roles +const char* role_friendly_name[] = { "invalid", "Ping out", "Pong back"}; + +// The role of the current running sketch +role_e role; + +// +// Address management +// + +// Where in EEPROM is the address stored? +const uint8_t address_at_eeprom_location = 0; + +// What is our address (SRAM cache of the address from EEPROM) +// Note that zero is an INVALID address. The pong back unit takes address +// 1, and the rest are 2-6 +uint8_t node_address; + +void setup(void) +{ + // + // Role + // + + // set up the role pin + pinMode(role_pin, INPUT); + digitalWrite(role_pin,HIGH); + delay(20); // Just to get a solid reading on the role pin + + // read the address pin, establish our role + if ( digitalRead(role_pin) ) + role = role_ping_out; + else + role = role_pong_back; + + // + // Address + // + + if ( role == role_pong_back ) + node_address = 1; + else + { + // Read the address from EEPROM + uint8_t reading = EEPROM.read(address_at_eeprom_location); + + // If it is in a valid range for node addresses, it is our + // address. + if ( reading >= 2 && reading <= 6 ) + node_address = reading; + + // Otherwise, it is invalid, so set our address AND ROLE to 'invalid' + else + { + node_address = 0; + role = role_invalid; + } + } + + // + // Print preamble + // + + Serial.begin(57600); + printf_begin(); + printf("\n\rRF24/examples/starping/\n\r"); + printf("ROLE: %s\n\r",role_friendly_name[role]); + printf("ADDRESS: %i\n\r",node_address); + + // + // Setup and configure rf radio + // + + radio.begin(); + + // + // Open pipes to other nodes for communication + // + + // The pong node listens on all the ping node talking pipes + // and sends the pong back on the sending node's specific listening pipe. + if ( role == role_pong_back ) + { + radio.openReadingPipe(1,talking_pipes[0]); + radio.openReadingPipe(2,talking_pipes[1]); + radio.openReadingPipe(3,talking_pipes[2]); + radio.openReadingPipe(4,talking_pipes[3]); + radio.openReadingPipe(5,talking_pipes[4]); + } + + // Each ping node has a talking pipe that it will ping into, and a listening + // pipe that it will listen for the pong. + if ( role == role_ping_out ) + { + // Write on our talking pipe + radio.openWritingPipe(talking_pipes[node_address-2]); + // Listen on our listening pipe + radio.openReadingPipe(1,listening_pipes[node_address-2]); + } + + // + // Start listening + // + + radio.startListening(); + + // + // Dump the configuration of the rf unit for debugging + // + + radio.printDetails(); + + // + // Prompt the user to assign a node address if we don't have one + // + + if ( role == role_invalid ) + { + printf("\n\r*** NO NODE ADDRESS ASSIGNED *** Send 1 through 6 to assign an address\n\r"); + } +} + +void loop(void) +{ + // + // Ping out role. Repeatedly send the current time + // + + if (role == role_ping_out) + { + // First, stop listening so we can talk. + radio.stopListening(); + + // Take the time, and send it. This will block until complete + unsigned long time = millis(); + printf("Now sending %lu...",time); + radio.write( &time, sizeof(unsigned long) ); + + // Now, continue listening + radio.startListening(); + + // Wait here until we get a response, or timeout (250ms) + unsigned long started_waiting_at = millis(); + bool timeout = false; + while ( ! radio.available() && ! timeout ) + if (millis() - started_waiting_at > 250 ) + timeout = true; + + // Describe the results + if ( timeout ) + { + printf("Failed, response timed out.\n\r"); + } + else + { + // Grab the response, compare, and send to debugging spew + unsigned long got_time; + radio.read( &got_time, sizeof(unsigned long) ); + + // Spew it + printf("Got response %lu, round-trip delay: %lu\n\r",got_time,millis()-got_time); + } + + // Try again 1s later + delay(1000); + } + + // + // Pong back role. Receive each packet, dump it out, and send it back + // + + if ( role == role_pong_back ) + { + // if there is data ready + uint8_t pipe_num; + if ( radio.available(&pipe_num) ) + { + // Dump the payloads until we've gotten everything + unsigned long got_time; + bool done = false; + while (!done) + { + // Fetch the payload, and see if this was the last one. + done = radio.read( &got_time, sizeof(unsigned long) ); + + // Spew it + printf("Got payload %lu from node %i...",got_time,pipe_num+1); + } + + // First, stop listening so we can talk + radio.stopListening(); + + // Open the correct pipe for writing + radio.openWritingPipe(listening_pipes[pipe_num-1]); + + // Retain the low 2 bytes to identify the pipe for the spew + uint16_t pipe_id = listening_pipes[pipe_num-1] & 0xffff; + + // Send the final one back. + radio.write( &got_time, sizeof(unsigned long) ); + printf("Sent response to %04x.\n\r",pipe_id); + + // Now, resume listening so we catch the next packets. + radio.startListening(); + } + } + + // + // Listen for serial input, which is how we set the address + // + if (Serial.available()) + { + // If the character on serial input is in a valid range... + char c = Serial.read(); + if ( c >= '1' && c <= '6' ) + { + // It is our address + EEPROM.write(address_at_eeprom_location,c-'0'); + + // And we are done right now (no easy way to soft reset) + printf("\n\rManually reset address to: %c\n\rPress RESET to continue!",c); + while(1) ; + } + } +} +// vim:ai:ci sts=2 sw=2 ft=cpp diff --git a/RC_Turrel/libraries/RF24-master/keywords.txt b/RC_Turrel/libraries/RF24-master/keywords.txt new file mode 100644 index 0000000..dec2a69 --- /dev/null +++ b/RC_Turrel/libraries/RF24-master/keywords.txt @@ -0,0 +1,32 @@ + RF24 KEYWORD1 + begin KEYWORD2 + setDataRate KEYWORD2 + getDataRate KEYWORD2 + powerUp KEYWORD2 + powerDown KEYWORD2 + whatHappened KEYWORD2 + writeAckPayload KEYWORD2 + setChannel KEYWORD2 + setPayloadSize KEYWORD2 + getPayloadSize KEYWORD2 + printDetails KEYWORD2 + startListening KEYWORD2 + stopListening KEYWORD2 + write KEYWORD2 +<<<<<<< HEAD + startWrite KEYWORD2 +======= + writeFast KEYWORD2 + writeBlocking KEYWORD2 + txStandBy KEYWORD2 +>>>>>>> 327f0609cf7b52b70accccc175b5809dd5074704 + available KEYWORD2 + read KEYWORD2 + openWritingPipe KEYWORD2 + openReadingPipe KEYWORD2 + closeReadingPipe KEYWORD2 + enableDynamicPayloads KEYWORD2 + enableAckPayload KEYWORD2 + setAutoAck KEYWORD2 + setCRCLength KEYWORD2 + getCRCLength KEYWORD2 diff --git a/RC_Turrel/libraries/RF24-master/nRF24L01.h b/RC_Turrel/libraries/RF24-master/nRF24L01.h new file mode 100644 index 0000000..132de94 --- /dev/null +++ b/RC_Turrel/libraries/RF24-master/nRF24L01.h @@ -0,0 +1,127 @@ +/* + Copyright (c) 2007 Stefan Engelke + Portions Copyright (C) 2011 Greg Copeland + + Permission is hereby granted, free of charge, to any person + obtaining a copy of this software and associated documentation + files (the "Software"), to deal in the Software without + restriction, including without limitation the rights to use, copy, + modify, merge, publish, distribute, sublicense, and/or sell copies + of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + DEALINGS IN THE SOFTWARE. +*/ + +/* Memory Map */ +#define CONFIG 0x00 +#define EN_AA 0x01 +#define EN_RXADDR 0x02 +#define SETUP_AW 0x03 +#define SETUP_RETR 0x04 +#define RF_CH 0x05 +#define RF_SETUP 0x06 +#define STATUS 0x07 +#define OBSERVE_TX 0x08 +#define CD 0x09 +#define RX_ADDR_P0 0x0A +#define RX_ADDR_P1 0x0B +#define RX_ADDR_P2 0x0C +#define RX_ADDR_P3 0x0D +#define RX_ADDR_P4 0x0E +#define RX_ADDR_P5 0x0F +#define TX_ADDR 0x10 +#define RX_PW_P0 0x11 +#define RX_PW_P1 0x12 +#define RX_PW_P2 0x13 +#define RX_PW_P3 0x14 +#define RX_PW_P4 0x15 +#define RX_PW_P5 0x16 +#define FIFO_STATUS 0x17 +#define DYNPD 0x1C +#define FEATURE 0x1D + +/* Bit Mnemonics */ +#define MASK_RX_DR 6 +#define MASK_TX_DS 5 +#define MASK_MAX_RT 4 +#define EN_CRC 3 +#define CRCO 2 +#define PWR_UP 1 +#define PRIM_RX 0 +#define ENAA_P5 5 +#define ENAA_P4 4 +#define ENAA_P3 3 +#define ENAA_P2 2 +#define ENAA_P1 1 +#define ENAA_P0 0 +#define ERX_P5 5 +#define ERX_P4 4 +#define ERX_P3 3 +#define ERX_P2 2 +#define ERX_P1 1 +#define ERX_P0 0 +#define AW 0 +#define ARD 4 +#define ARC 0 +#define PLL_LOCK 4 +#define RF_DR 3 +#define RF_PWR 6 +#define RX_DR 6 +#define TX_DS 5 +#define MAX_RT 4 +#define RX_P_NO 1 +#define TX_FULL 0 +#define PLOS_CNT 4 +#define ARC_CNT 0 +#define TX_REUSE 6 +#define FIFO_FULL 5 +#define TX_EMPTY 4 +#define RX_FULL 1 +#define RX_EMPTY 0 +#define DPL_P5 5 +#define DPL_P4 4 +#define DPL_P3 3 +#define DPL_P2 2 +#define DPL_P1 1 +#define DPL_P0 0 +#define EN_DPL 2 +#define EN_ACK_PAY 1 +#define EN_DYN_ACK 0 + +/* Instruction Mnemonics */ +#define R_REGISTER 0x00 +#define W_REGISTER 0x20 +#define REGISTER_MASK 0x1F +#define ACTIVATE 0x50 +#define R_RX_PL_WID 0x60 +#define R_RX_PAYLOAD 0x61 +#define W_TX_PAYLOAD 0xA0 +#define W_ACK_PAYLOAD 0xA8 +#define FLUSH_TX 0xE1 +#define FLUSH_RX 0xE2 +#define REUSE_TX_PL 0xE3 +#define NOP 0xFF + +/* Non-P omissions */ +#define LNA_HCURR 0 + +/* P model memory Map */ +#define RPD 0x09 +#define W_TX_PAYLOAD_NO_ACK 0xB0 + +/* P model bit Mnemonics */ +#define RF_DR_LOW 5 +#define RF_DR_HIGH 3 +#define RF_PWR_LOW 1 +#define RF_PWR_HIGH 2 diff --git a/RC_Turrel/libraries/RF24-master/printf.h b/RC_Turrel/libraries/RF24-master/printf.h new file mode 100644 index 0000000..878b089 --- /dev/null +++ b/RC_Turrel/libraries/RF24-master/printf.h @@ -0,0 +1,41 @@ +/* + Copyright (C) 2011 J. Coliz + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + */ + +/** + * @file printf.h + * + * Setup necessary to direct stdout to the Arduino Serial library, which + * enables 'printf' + */ + +#ifndef __PRINTF_H__ +#define __PRINTF_H__ + +#if defined (ARDUINO) && !defined (__arm__) + +int serial_putc( char c, FILE * ) +{ + Serial.write( c ); + + return c; +} + +void printf_begin(void) +{ + fdevopen( &serial_putc, 0 ); +} + +#elif defined (__arm__) + +void printf_begin(void){} + +#else +#error This example is only for use on Arduino. +#endif // ARDUINO + +#endif // __PRINTF_H__