I’ve read your tutorial and code, I’ve simplified it down to this (AVR GCC, ATMEGA644 at 18.432MHz):
#define norChannel 2
//#define norSerDebug
// CS pin
#define csPort PORTB // output port register
#define csDDR DDRB // direction register, 1 = output
#define csPin 1 // pin number
// CE pin
#define cePort PORTB
#define ceDDR DDRB
#define cePin 0
//INT pin
#define intPort PORTB
#define intDDR DDRB
#define intPinIn PINB // port input register
#define intPin 2
#define packetLength 14 // payload width
uint8_t norOutBuffer[packetLength]; // inbox
uint8_t norInBuffer[packetLength]; // outbox
volatile uint8_t norBoolean; // flags
#define TxDone 0
#define TxFailed 1
#define RxDone 3
void norSel()
{
// select by clearing CSN pin
cbi(csPort, csPin);
}
void norDesel()
{
// deselect by setting CSN pin
sbi(csPort, csPin);
}
void norWR(uint8_t reg, uint8_t data)
{
// write register
norSel(); // CSN pin
spiSend(0b00100000 | reg); // write register command
spiSend(data); // put in data
norDesel(); // CSN pin
}
uint8_t norRR(uint8_t reg)
{
uint8_t temp;
// read register
norSel(); // CSN pin
spiSend(0b00000000 | reg); // register read command
spiSend(0);
norDesel(); // CSN pin
temp = spiRead(); // register data here
return temp;
}
void norCE(uint8_t data)
{
// change CE pin state
if(data == 0)
{
cbi(cePort, cePin);
}
else
{
sbi(cePort, cePin);
}
}
void norFlushTx()
{
norSel();
spiSend(0b11100001); // flush Tx FIFO command
norDesel();
}
void norFlushRx()
{
norSel();
spiSend(0b11100010); // flush Rx FIFO command
norDesel();
}
void norRxMode()
{
norWR(0x00, 0b00001011); // IRQ on, AA on, CRC 1, PRX
norCE(1);
}
void norTxMode()
{
norWR(0x00, 0b00001010); // IRQ on, AA on, CRC 1, PTX
norCE(0);
}
void norInit(uint8_t mode)
{
norBoolean = 0; // clear flags
// setup pins
// chip select pin
sbi(csPort, csPin);
sbi(csDDR, csPin);
// chip enable pin
cbi(cePort, cePin);
sbi(ceDDR, cePin);
// IRQ pin input
cbi(intPort, intPin);
cbi(intDDR, intPin);
spiInit(); // initialize SPI, 18.432MHz div 4, mode 00
// reset FIFOs
norFlushTx();
norFlushRx();
// minimal config with AA
norWR(0x01, 0b00000001); // enable AA on pipe 0
norWR(0x05, norChannel); // setup channel
norWR(0x11, packetLength); // pipe 0 payload width
// power up in different modes
if(mode == 1)
{
norRxMode();
}
else
{
norTxMode();
}
_delay_us(1500); // delay for power up
}
void norReadStatus()
{
norSel();
spiSend(255); // Send NOP to check STATUS
uint8_t norStatusVar = spiRead(); // read status
norDesel();
norWR(0x07, norStatusVar & 0b01110000); // clear interrupts
if(bit_is_set(norStatusVar, 6))
{
// New Packet Received
sbi(norBoolean, RxDone);
}
if(bit_is_set(norStatusVar, 5))
{
// Tx Complete
sbi(norBoolean, TxDone);
}
if(bit_is_set(norStatusVar, 4))
{
// Max Retry Reached, Tx Failed
sbi(norBoolean, TxFailed);
}
}
void norLoadTx()
{
// load the Tx Payload
norSel();
spiSend(0b10100000); // W_TX_PAYLOAD command
uint8_t i;
for(i = 0; i < packetLength; i++)
{
// load into FIFO
spiSend(norOutBuffer[i]);
}
norDesel();
}
void norLoadRx()
{
// read the Rx Payload
norSel();
spiSend(0b01100001); // R_RX_PAYLOAD command
uint8_t i;
for(i = 0; i < packetLength; i++)
{
// read from FIFO
spiSend(0);
norInBuffer[i] = spiRead();
}
norDesel();
}
void norTx()
{
norTxMode(); // PTX mode
norLoadTx(); // put the payload into FIFO
norBoolean = 0; // clear flags
norCE(1); // toggle CE
_delay_us(11);
norCE(0);
// wait for either finish or failure
while(bit_is_clear(norBoolean, TxDone) && bit_is_clear(norBoolean, TxFailed))
{
while(bit_is_set(intPinIn, intPin)); // poll interrupt pin
norReadStatus(); // read status
}
if(bit_is_set(norBoolean, TxDone)) // if finished
{
while(bit_is_clear(norBoolean, RxDone)) // wait for finish
{
while(bit_is_set(intPinIn, intPin)); // poll interrupt pin
norReadStatus(); // read status
}
norLoadRx(); // read the Rx payload
}
else if(bit_is_set(norBoolean, TxFailed))
{
norFlushTx(); // if failed, flush FIFO
}
}
void norRx()
{
norLoadTx(); // load reply payload into FIFO
norBoolean = 0; // clear flags
norRxMode(); // PRX mode, CE on
while(bit_is_clear(norBoolean, TxDone)) // wait for finish
{
while(bit_is_set(intPinIn, intPin)); // poll interrupt pin
norReadStatus(); // read status
}
norLoadRx(); // read FIFO
}
The Rx device is on, and waiting, but the Tx still never gets the interrupt.
I have previously been able to send packets without autoack, not with that code though, that was done on a single processor with both radios on one SPI bus.
EDIT:
Wow, I went back to my old code, enhanced shockburst works!
The difference is that CE is tied to VCC… I wonder what’s wrong with my microcontroller pin, my logic probe is telling me that even if I set it to 1, CE pin is pulsing. It’s the PB0 on an atmega644, datasheet says it’s also a clock souce for USRT or a timer/counter0 souce, but neither of those are supposed to be on
I don’t know what happened, but it works on an atmega168 but not 644… seems to be an issue reading data from the radio, MISO is returning 0s all the time…