// PIC16F877A Configuration Bit Settings
#include <xc.h>
#include <htc.h>
#include "stdint.h"
// #pragma config statements should prece_pinde project file includes.
// Use project enums instead of #define for ON and OFF.
// CONFIG
#pragma config FOSC = HS // Oscillator Selection bits (HS oscillator)
#pragma config WDTE = OFF // Watchdog Timer Enable bit (WDT disabled)
#pragma config PWRTE = OFF // Power-up Timer Enable bit (PWRT disabled)
#pragma config BOREN = ON // Brown-out Reset Enable bit (BOR disabled)
#pragma config LVP = OFF // Low-Voltage (Single-Supply) In-Circuit Serial Programming Enable bit (RB3 is digital I/O, HV on MCLR must be used for programming)
#pragma config CPD = OFF // Data EEPROM Memory Code Protection bit (Data EEPROM code protection off)
#pragma config WRT = OFF // Flash Program Memory Write Enable bits (Write protection off; all program memory may be written to by EECON control)
#pragma config CP = OFF // Flash Program Memory Code Protection bit (Code protection off)
#define _XTAL_FREQ 20000000
#include "stdint.h"
/* 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
/* Bit Mnemonics */
/* configuratio nregister */
#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
/* enable auto acknowledgment */
#define ENAA_P5 5
#define ENAA_P4 4
#define ENAA_P3 3
#define ENAA_P2 2
#define ENAA_P1 1
#define ENAA_P0 0
/* enable rx addresses */
#define ERX_P5 5
#define ERX_P4 4
#define ERX_P3 3
#define ERX_P2 2
#define ERX_P1 1
#define ERX_P0 0
/* setup of address width */
#define AW 0 /* 2 bits */
/* setup of auto re-transmission */
#define ARD 4 /* 4 bits */
#define ARC 0 /* 4 bits */
/* RF setup register */
#define PLL_LOCK 4
#define RF_DR_HIGH 3
#define RF_PWR 1 /* 2 bits */
/* general status register */
#define RX_DR 6
#define TX_DS 5
#define MAX_RT 4
#define RX_P_NO 1 /* 3 bits */
#define TX_FULL 0
/* transmit observe register */
#define PLOS_CNT 4 /* 4 bits */
#define ARC_CNT 0 /* 4 bits */
/* fifo status */
#define TX_REUSE 6
#define FIFO_FULL 5
#define TX_EMPTY 4
#define RX_FULL 1
#define RX_EMPTY 0
/* dynamic length */
#define DPL_P0 0
#define DPL_P1 1
#define DPL_P2 2
#define DPL_P3 3
#define DPL_P4 4
#define DPL_P5 5
/* Instruction Mnemonics */
#define R_REGISTER 0x00 /* last 4 bits will indicate reg. address */
#define W_REGISTER 0x20 /* last 4 bits will indicate reg. address */
#define REGISTER_MASK 0x1F
#define R_RX_PAYLOAD 0x61
#define W_TX_PAYLOAD 0xA0
#define FLUSH_TX 0xE1
#define FLUSH_RX 0xE2
#define REUSE_TX_PL 0xE3
#define ACTIVATE 0x50
#define R_RX_PL_WID 0x60
#define NOP1 0xFF
#define nrf24_CONFIG ((1<<EN_CRC)|(0<<CRCO)) // (1 << MASK_RX_DR)|
/// hardware spi pin defined
#define LED_PIN PORTCbits.RC0 // led test
#define CSN_PIN PORTCbits.RC2// //set port as output
#define ce_pin PORTCbits.RC1 //set port as output
//#define SCK_Pin PORTBbits.RB1 //set port as output
//#define Mosi_Pin PORTBbits.RB2 //set port as output
//#define Miso_Pin PORTBbits.RB3 //set port as input
#define HIGH 1
#define LOW 0
#define payload 1;
void SPI_init()
{
SSPEN = 0;
TRISC = 0; //SCK
CKE = 1;
SSPCON = 0x01; //CKP = 0, SCK = 1MHz
SMP = 1;
SSPEN = 1;
}
unsigned char SPI_transfer(unsigned char data)
{
SSPBUF = data; // Put command into SPI buffer
while (!BF); // Wait for the transfer to finish
return SSPBUF; // Save the read value
}
void nrf24_ce_pin_digitalwrite(uint8_t state)
{
if (state)
{
ce_pin = 1;
}
else
{
ce_pin = 0;
}
}
void nrf24_csn_digitalwrite(uint8_t state)
{
if (state)
{
CSN_PIN = 1;
}
else
{
CSN_PIN = 0;
}
}
/*
void nrf24_sck_digitalwrite(uint8_t state)
{
if (state)
{
SCK_Pin = 1;
}
else
{
SCK_Pin = 0;
}
}
void nrf24_mosi_digitalwrite( uint8_t state)
{
if (state)
{
Mosi_Pin = 1;
}
else
{
Mosi_Pin = 0;
}
}
*/
/* software spi routine
uint8_t SPI_transfer(uint8_t tx)
{
uint8_t i = 0;
uint8_t rs = 0;
nrf24_sck_digitalwrite(LOW);
for(i=0;i<8;i++)
{
if(tx & 0x80) // msbit first spi standard
nrf24_mosi_digitalwrite(HIGH);
else
nrf24_mosi_digitalwrite(LOW);
nrf24_sck_digitalwrite(HIGH);
tx = tx << 1;
if(Miso_Pin == 1)
{
rs |= 0x01;
}
nrf24_sck_digitalwrite(LOW);
nrf24_mosi_digitalwrite(LOW);
}
return rs;
}
*/
/* send and rece_pinive multiple bytes over SPI */ // checked with mirf
void nrf24_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]);
}
}
//send multiple bytes over SPI // checked with mirf
void nrf24_transmitSync(uint8_t *dataout,uint8_t len)
{
uint8_t i;
for(i=0;i<len;i++){
SPI_transfer(dataout[i]);
}
}
void nrf24_configRegister(uint8_t reg, uint8_t value)
{
nrf24_csn_digitalwrite(LOW);
SPI_transfer(W_REGISTER | (REGISTER_MASK & reg));
SPI_transfer(value);
nrf24_csn_digitalwrite(HIGH);
}
void nrf24_powerUpTx() // checked with mirf
{
// PTX = 1;
nrf24_configRegister(CONFIG,nrf24_CONFIG|((1<<PWR_UP)|(0<<PRIM_RX)));
}
void nrf24_init()
{
TRISB = 0b00000000;
TRISA = 0b00000000;
TRISC = 0b00010000;
ADCON1 = 0X00;
// nrf24_ce_pin_digitalwrite(LOW);
// nrf24_csn_digitalwrite(HIGH);
}
void nrf24_send(uint8_t* value) // check with mirf
{
/* Go to Standby-I first */
// nrf24_ce_pin_digitalwrite(LOW);
/* Set to transmitter mode , Power up if needed */
nrf24_powerUpTx();
nrf24_csn_digitalwrite(LOW);
SPI_transfer(FLUSH_TX);
nrf24_csn_digitalwrite(HIGH);
/* Pull down chip select */
nrf24_csn_digitalwrite(LOW);
/* Write cmd to write payload */
SPI_transfer(W_TX_PAYLOAD);
/* Write payload */
nrf24_transmitSync(value,1);
/* Pull up chip select */
nrf24_csn_digitalwrite(HIGH);
/* Start the transmission */
nrf24_ce_pin_digitalwrite(HIGH);
}
/*
void sendarray (uint8_t arg[], uint8_t length) {
for (uint8_t n=0; n<length; ++n)
nrf24_send(arg[n]);
}
*/
void main()
{
TRISB = 0b00000000;
TRISA = 0b00000000;
TRISC = 0b00010000;
SPI_init();
uint8_t data_array = 111;
//int *array_ptr = &data_array[0];
nrf24_configRegister(EN_AA,(0<<ENAA_P0)|(0<<ENAA_P1));
nrf24_init();
nrf24_powerUpTx();
__delay_ms(5);
//LED_PIN = HIGH;
while(1)
{
nrf24_send(&data_array);
__delay_us(20);
nrf24_ce_pin_digitalwrite(LOW);
// Read wl_module status
// nrf24_csn_digitalwrite(LOW); // Pull down chip select
// status = SPI_transfer(NOP1); // Read status register
// nrf24_csn_digitalwrite(HIGH); // Pull up chip select
/*
if (status & (1<<TX_DS)) // IRQ: Package has been sent
{
//nrf24_configRegister(STATUS, (1<<TX_DS)); //Clear Interrupt Bit
//PTX=0;
}
*/
uint8_t status;
nrf24_csn_digitalwrite(LOW); // Pull down chip select
status = SPI_transfer(0xff); // Read status register
nrf24_csn_digitalwrite(HIGH); // Pull up chip select
if (status & (1<<TX_DS)) // IRQ: Package has been sent
{
LED_PIN = HIGH;
nrf24_configRegister(STATUS, (1<<TX_DS)); //Clear Interrupt Bit if this line enabled led will not turn on as it clears TX_DS permanently. // if enable led should see blinking too fast
nrf24_csn_digitalwrite(LOW); // Pull down chip select
SPI_transfer(FLUSH_TX); // Flush TX-FIFO
nrf24_csn_digitalwrite(HIGH);
}
else
{
LED_PIN = LOW;
}
if (status & (1<<MAX_RT)) // IRQ: Package has not been sent, send again
{
nrf24_configRegister(STATUS, (1<<MAX_RT)); // Clear Interrupt Bit
nrf24_ce_pin_digitalwrite(HIGH); // Start transmission
nrf24_ce_pin_digitalwrite(LOW);
}
if (status & (1<<TX_FULL)) //TX_FIFO Full <-- this is not an IRQ
{
__delay_us(50); // resend package
nrf24_ce_pin_digitalwrite(HIGH); // Pull up chip select
}
__delay_ms(20); // wait some time
nrf24_ce_pin_digitalwrite(LOW);
}
}