Ajout initial depuis le projet sonde

This commit is contained in:
arnaud.houdelette 2019-09-06 16:44:33 +02:00
parent a75b521dce
commit 410d7b7395
5 changed files with 575 additions and 0 deletions

125
nRF24L01.h Normal file
View file

@ -0,0 +1,125 @@
/*
Copyright (c) 2007 Stefan Engelke <mbox@stefanengelke.de>
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
/* P model bit Mnemonics */
#define RF_DR_LOW 5
#define RF_DR_HIGH 3
#define RF_PWR_LOW 1
#define RF_PWR_HIGH 2

270
rf24.c Normal file
View file

@ -0,0 +1,270 @@
#include "rf24.h"
#include <util/delay.h>
uint8_t PTX=0;
uint8_t rf24_CONFIG = _BV(EN_CRC) | _BV(CRCO);
uint8_t rf24_EN_AA = 0x3F; //ENAA_P0 - ENAA_P5
uint8_t rf24_EN_RXADDR = _BV(ERX_P0)|_BV(ERX_P1);
uint8_t rf24_SETUP_AW = 0x03; // 5 bytes addresses
uint8_t rf24_SETUP_RETR = 0x03;
uint8_t rf24_RF_CH = 0x02; // Channel
uint8_t rf24_RF_SETUP = _BV(RF_DR_HIGH) | _BV(RF_PWR_LOW) | _BV(RF_PWR_HIGH);
uint8_t rf24_FEATURE = 0;
uint8_t rf24_DYNPD= 0;
uint8_t rf24_RX_PW[6] = { 32,32,0,0,0,0 };
void inline rf24_ceHi(){
//CE_PIN_PORT |= _BV(CE_PIN_BIT);
}
void inline rf24_ceLow(){
//CE_PIN_PORT &= ~_BV(CE_PIN_BIT);
}
void inline rf24_csnHi(){
CSN_PIN_PORT |= _BV(CSN_PIN_BIT);
}
void inline rf24_csnLow(){
CSN_PIN_PORT &= ~_BV(CSN_PIN_BIT);
}
void rf24_init()
{
//CE_PIN_DDR |= _BV(CE_PIN_BIT);
CSN_PIN_DDR |= _BV(CSN_PIN_BIT);
rf24_ceLow();
rf24_csnHi();
// Initialize spi module
spi_begin();
_delay_ms(2);
rf24_configure();
}
void inline rf24_transferSync(uint8_t *dataout,uint8_t *datain,uint8_t len){
uint8_t i;
for(i = 0;i < len;i++){
datain[i] = spi_transfer(dataout[i]);
}
}
void inline rf24_transmitSync(uint8_t *dataout,uint8_t len){
uint8_t i;
for(i = 0;i < len;i++){
spi_transfer(dataout[i]);
}
}
void inline rf24_configRegister(uint8_t reg, uint8_t value)
// Clocks only one byte into the given MiRF register
{
rf24_csnLow();
spi_transfer(W_REGISTER | (REGISTER_MASK & reg));
spi_transfer(value);
rf24_csnHi();
}
void inline rf24_readRegister(uint8_t reg, uint8_t * value, uint8_t len)
// Reads an array of bytes from the given start position in the MiRF registers.
{
rf24_csnLow();
spi_transfer(R_REGISTER | (REGISTER_MASK & reg));
rf24_transferSync(value,value,len);
rf24_csnHi();
}
void inline rf24_writeRegister(uint8_t reg, uint8_t * value, uint8_t len)
// Writes an array of bytes into inte the MiRF registers.
{
rf24_csnLow();
spi_transfer(W_REGISTER | (REGISTER_MASK & reg));
rf24_transmitSync(value,len);
rf24_csnHi();
}
void rf24_getData(uint8_t * data,uint8_t len)
{
rf24_csnLow(); // Pull down chip select
spi_transfer( R_RX_PAYLOAD ); // Send cmd to read rx payload
rf24_transferSync(data,data,len); // Read payload
rf24_csnHi(); // Pull up chip select
// NVI: per product spec, p 67, note c:
// "The RX_DR IRQ is asserted by a new packet arrival event. The procedure
// for handling this interrupt should be: 1) read payload through SPI,
// 2) clear RX_DR IRQ, 3) read FIFO_STATUS to check if there are more
// payloads available in RX FIFO, 4) if there are more data in RX FIFO,
// repeat from step 1)."
// So if we're going to clear RX_DR here, we need to check the RX FIFO
// in the dataReady() function
rf24_configRegister(STATUS,(1<<RX_DR)); // Reset status register
}
uint8_t rf24_getDataDL(uint8_t * data,uint8_t len)
// Reads payload bytes into data array
{
uint8_t to_read;
rf24_csnLow(); // Pull down chip select
spi_transfer( R_RX_PL_WID ); // Send cmd to read rx payload len
to_read = spi_transfer(0); // Read payload
rf24_csnHi(); // Pull up chip select
if(len>to_read && to_read>0 ) len=to_read;
rf24_csnLow(); // Pull down chip select
spi_transfer( R_RX_PAYLOAD ); // Send cmd to read rx payload
rf24_transferSync(data,data,len); // Read payload
if(to_read!=len){
to_read-=len;
while((to_read--)>0) // read remaining
spi_transfer(0);
}
rf24_csnHi(); // Pull up chip select
// NVI: per product spec, p 67, note c:
// "The RX_DR IRQ is asserted by a new packet arrival event. The procedure
// for handling this interrupt should be: 1) read payload through SPI,
// 2) clear RX_DR IRQ, 3) read FIFO_STATUS to check if there are more
// payloads available in RX FIFO, 4) if there are more data in RX FIFO,
// repeat from step 1)."
// So if we're going to clear RX_DR here, we need to check the RX FIFO
// in the dataReady() function
rf24_configRegister(STATUS,(1<<RX_DR)); // Reset status register
return to_read;
}
uint8_t inline rf24_dataReady()
// Checks if data is available for reading
{
// See note in getData() function - just checking RX_DR isn't good enough
uint8_t status = rf24_getStatus();
// We can short circuit on RX_DR, but if it's not set, we still need
// to check the FIFO for any pending packets
if ( status & (1 << RX_DR) ) return 1;
return !rf24_rxFifoEmpty();
}
uint8_t inline rf24_rxFifoEmpty(){
uint8_t fifoStatus;
rf24_readRegister(FIFO_STATUS,&fifoStatus,sizeof(fifoStatus));
return (fifoStatus & (1 << RX_EMPTY));
}
void rf24_send(uint8_t * value,uint8_t len)
// Sends a data package to the default address. Be sure to send the correct
// amount of bytes as configured as payload on the receiver.
{
uint8_t status;
status = rf24_getStatus();
if((status & ((1 << TX_DS) | (1 << MAX_RT)))){
rf24_configRegister(STATUS,(1 << TX_DS) | (1 << MAX_RT));
}
rf24_ceLow();
rf24_powerUpTx(); // Set to transmitter mode , Power up
rf24_csnLow(); // Pull down chip select
spi_transfer( FLUSH_TX ); // Write cmd to flush tx fifo
rf24_csnHi(); // Pull up chip select
rf24_csnLow(); // Pull down chip select
spi_transfer( W_TX_PAYLOAD ); // Write cmd to write payload
rf24_transmitSync(value,len); // Write payload
rf24_csnHi(); // Pull up chip select
rf24_ceHi(); // Start transmission
}
uint8_t inline rf24_isSending(){
uint8_t status;
if(PTX){
status = rf24_getStatus();
/*
* if sending successful (TX_DS) or max retries exceded (MAX_RT).
*/
if((status & ((1 << TX_DS) | (1 << MAX_RT)))){
return 0;
}
return 1;
}
return 0;
}
uint8_t inline rf24_getStatus(){
uint8_t rv;
rf24_csnLow();
rv=spi_transfer(NOP);
rf24_csnHi();
return rv;
}
void inline rf24_powerUpRx(){
PTX = 0;
rf24_ceLow();
rf24_configRegister(CONFIG, rf24_CONFIG | ( (1<<PWR_UP) | (1<<PRIM_RX) ) );
rf24_ceHi();
rf24_configRegister(STATUS,(1 << TX_DS) | (1 << MAX_RT));
}
void inline rf24_flushRx(){
rf24_csnLow();
spi_transfer( FLUSH_RX );
rf24_csnHi();
}
void inline rf24_powerUpTx(){
PTX = 1;
rf24_configRegister(CONFIG, rf24_CONFIG | ( (1<<PWR_UP) | (0<<PRIM_RX) ) );
}
void inline rf24_powerDown(){
rf24_ceLow();
rf24_configRegister(CONFIG, rf24_CONFIG );
}
void rf24_configure(){
uint8_t data;
rf24_configRegister(CONFIG,rf24_CONFIG);
rf24_configRegister(FEATURE,rf24_FEATURE);
// Check Feature register ...
rf24_readRegister(FEATURE,&data,1);
if(rf24_FEATURE != data){ // ACTIVATE & retry
rf24_csnLow();
spi_transfer(ACTIVATE);
spi_transfer(0x73);
rf24_csnHi();
rf24_configRegister(FEATURE,rf24_FEATURE);
}
rf24_configRegister(EN_AA,rf24_EN_AA);
rf24_configRegister(EN_RXADDR,rf24_EN_RXADDR);
rf24_configRegister(SETUP_AW,rf24_SETUP_AW);
rf24_configRegister(SETUP_RETR,rf24_SETUP_RETR);
rf24_configRegister(RF_CH,rf24_RF_CH);
rf24_configRegister(RF_SETUP,rf24_RF_SETUP);
rf24_configRegister(DYNPD,rf24_DYNPD);
for(int i=0; i<6;i++)
rf24_configRegister(RX_PW_P0+i,rf24_RX_PW[i]);
}

72
rf24.h Normal file
View file

@ -0,0 +1,72 @@
#include "nRF24L01.h"
#include "spi.h"
#include <avr/io.h>
#include "defines.h"
#ifdef __cplusplus
extern "C"{
#endif
void rf24_init();
void rf24_configRegister(uint8_t reg, uint8_t value);
void rf24_readRegister(uint8_t reg, uint8_t * value, uint8_t len);
void rf24_writeRegister(uint8_t reg, uint8_t * value, uint8_t len);
void rf24_getData(uint8_t * data,uint8_t len);
uint8_t rf24_getDataDL(uint8_t * data,uint8_t len);
uint8_t rf24_dataReady();
uint8_t rf24_rxFifoEmpty();
void rf24_send(uint8_t * value,uint8_t len);
uint8_t rf24_isSending();
uint8_t rf24_getStatus();
void rf24_powerUpRx();
void rf24_powerUpTx();
void rf24_powerDown();
void rf24_flushRx();
void rf24_configure();
extern uint8_t rf24_CONFIG;
extern uint8_t rf24_EN_AA;
extern uint8_t rf24_EN_RXADDR;
extern uint8_t rf24_SETUP_AW;
extern uint8_t rf24_SETUP_RETR;
extern uint8_t rf24_RF_CH;
extern uint8_t rf24_RF_SETUP;
extern uint8_t rf24_FEATURE;
extern uint8_t rf24_DYNPD;
extern uint8_t rf24_RX_PW[6];
#if defined (__AVR_ATtiny84__) || defined (__AVR_ATtiny84A__)
#define CE_PIN_PORT UNDEF
#define CE_PIN_DDR UNDEF
#define CE_PIN_BIT UNDEF
#define CSN_PIN_PORT PORTB
#define CSN_PIN_DDR DDRB
#define CSN_PIN_BIT PB2
#elif defined(__AVR_ATmega32U4__)
#define CE_PIN_PORT PORTD
#define CE_PIN_DDR DDRD
#define CE_PIN_BIT PD4
#define CSN_PIN_PORT PORTC
#define CSN_PIN_DDR DDRC
#define CSN_PIN_BIT PC6
#endif
#ifdef __cplusplus
} // extern "C"
#endif

79
spi.c Normal file
View file

@ -0,0 +1,79 @@
#include "spi.h"
#include <util/delay.h>
void spi_begin() {
#if defined(SPCR)
#error to write ...
// Set SS to high so a connected chip will be "deselected" by default
digitalWrite(SS, HIGH);
// When the SS pin is set as OUTPUT, it can be used as
// a general purpose output port (it doesn't influence
// SPI operations).
pinMode(SS, OUTPUT);
// Warning: if the SS pin ever becomes a LOW INPUT then SPI
// automatically switches to Slave, so the data direction of
// the SS pin MUST be kept as OUTPUT.
SPCR |= _BV(MSTR);
SPCR |= _BV(SPE);
// Set direction register for SCK and MOSI pin.
// MISO pin automatically overrides to INPUT.
// By doing this AFTER enabling SPI, we avoid accidentally
// clocking in a single bit since the lines go directly
// from "input" to SPI control.
// http://code.google.com/p/arduino/issues/detail?id=888
pinMode(SCK, OUTPUT);
pinMode(MOSI, OUTPUT);
#else
PRR &= ~(_BV(PRUSI));
USICR = _BV(USIWM0);
USCK_DDR |= _BV(USCK_BIT); //set the USCK pin as output
DO_DDR |= _BV(DO_BIT); //set the DO pin as output
DI_DDR &= ~_BV(DI_BIT); //set the DI pin as input
#endif
}
uint8_t spi_transfer(uint8_t b) {
#if defined(SPCR)
SPDR = b;
while (!(SPSR & _BV(SPIF)));
return SPDR;
#else
USIDR = b;
USISR = _BV(USIOIF);
do {
USICR = _BV(USIWM0) | _BV(USICS1) | _BV(USICLK) | _BV(USITC);
// _delay_ms(1);
}while ((USISR & _BV(USIOIF)) == 0);
return USIDR;
#endif
}
void spi_end() {
#if defined(SPCR)
SPCR &= ~_BV(SPE);
#else
USICR &= ~(_BV(USIWM1) | _BV(USIWM0));
#endif
}
void spi_setBitOrder(uint8_t bitOrder)
{
#if defined(SPCR)
if(bitOrder == LSBFIRST) {
SPCR |= _BV(DORD);
} else {
SPCR &= ~(_BV(DORD));
}
#endif
}
void spi_setDataMode(uint8_t mode)
{
#if defined(SPCR)
SPCR = (SPCR & ~SPI_MODE_MASK) | mode;
#else
#endif
}

29
spi.h Normal file
View file

@ -0,0 +1,29 @@
#ifndef tinySPI_h
#define tinySPI_h
#include <stdint.h>
#include <avr/io.h>
#include <util/atomic.h>
#ifdef __cplusplus
extern "C"{
#endif
//SPI data modes
#define SPI_MODE0 0x00
#define SPI_MODE1 0x04
void spi_begin(void);
void spi_setDataMode(uint8_t spiDataMode);
uint8_t spi_transfer(uint8_t spiData);
void spi_end(void);
#ifdef __cplusplus
} // extern "C"
#endif
#endif