#include #include #include #include #include #include "led.h" // TODO: for debugging #include "spi.h" #include "nrf24l01.h" #include "nrf24l01_definitions.h" /* TODO * - Send functions * - Interrupt handling for Send */ extern volatile bool nrfInterruptRaised; void Print_Register_Contents(uint8_t address); void Send_TX_Flush_Command(void); void Send_RX_Flush_Command(void); static uint8_t Write_One_Byte(uint8_t byte1); static uint8_t Write_Two_Bytes(uint8_t byte1, uint8_t byte2); static void Write_Byte_And_Buffer(uint8_t byte, uint8_t * buffer, uint8_t length); /* Startup and initial configuration of the NRF24L01 */ void Initialize_NRF24L01(void) { CONFIG_REGISTER configRegisterContents = {.byte = 0x0}; /* Configure the AVR pins for the nrf24l01 */ Set_NRF24L01_Pins(); /* Wait more than 10.3 ms to make sure the nrf24l01 is running */ _delay_ms(11); /* Write the PWR_UP bit of the CONFIG register (EN_CRC is also set) */ configRegisterContents.bits.EN_CRC = 0x1; configRegisterContents.bits.PWR_UP = 0x1; Write_NRF_Register(CONFIG_ADDRESS, configRegisterContents.byte); /* Wait more than 1.5 ms for the change to take effect */ _delay_ms(2); /* The NRF24L01 is now in the mode Standby-I */ /* Flush the FIFOs */ Send_TX_Flush_Command(); Send_RX_Flush_Command(); } void Set_NRF24L01_Pins(void) { /* Set up the NRF24L01 */ NRF_CE_DDR |= (1 << NRF_CE_PIN); NRF_CSN_DDR |= (1 << NRF_CSN_PIN); /* Set the chip select pin to not selected */ NRF_CSN_PORT |= (1 << NRF_CSN_PIN); /* Ensure that the CE pin is set to 0*/ NRF_CE_PORT &= ~(1 << NRF_CE_PIN); /* Set the interrupt pin */ /* TODO: PCINT21 -> PCINT2 */ NRF_IRQ_DDR &= ~(1 << NRF_IRQ_PIN); // Set the pin as input NRF_IRQ_PORT |= (1 << NRF_IRQ_PORT); // Enable the pullup for the pin } void Configure_Transmission(uint8_t moduleId) { SETUP_RETR_REGISTER setupRetrRegisterContents = {.byte = 0x0}; EN_RXADDR_REGISTER enableRxAddressesRegisterContents = {.byte = 0x0}; RX_PW_Pn_REGISTER rxPwPnRegisterContents = {.byte = 0x0}; EN_AA_REGISTER enAaRegister = {.byte = 0x0}; uint8_t txAddress[5] = {0xB3, 0xB3, 0xB3, 0xB3, 0x00}; uint8_t rx1Address[5] = {0xB3, 0xB3, 0xB3, 0xB3, 0x00}; /* Set the frequency to 1450 MHz */ Write_NRF_Register(RF_CH_ADDRESS, 0x32); /* Set up the auto retries */ setupRetrRegisterContents.bits.ARC = 0x3; setupRetrRegisterContents.bits.ARD = 0xF; Write_NRF_Register(SETUP_RETR_ADDRESS, setupRetrRegisterContents.byte); /* Set the TX address */ Set_TX_Address(txAddress, MAX_ADDRESS_LENGTH); /* Set the address of the RX pipe 0 to the one of the base station to receive acks */ Set_RX_P0_Address(txAddress, MAX_ADDRESS_LENGTH); /* Set the address of the RX pipe 1 to the own address to receive messages */ rx1Address[4] = moduleId; // The last byte of the address corresponds to the Id set by the pin programming Set_RX_P1_Address(rx1Address, MAX_ADDRESS_LENGTH); /* Enable the rx addresses for pipe 0 and pipe 1*/ enableRxAddressesRegisterContents.bits.ERX_P0 = 1; enableRxAddressesRegisterContents.bits.ERX_P1 = 1; Write_NRF_Register(EN_RXADDR_ADDRESS, enableRxAddressesRegisterContents.byte); /* Set the payload witth for pipe 1 */ rxPwPnRegisterContents.bits.RX_PW_Pn = 32; Write_NRF_Register(RX_PW_P1_ADDRESS, rxPwPnRegisterContents.byte); rxPwPnRegisterContents.bits.RX_PW_Pn = 0; Write_NRF_Register(RX_PW_P0_ADDRESS, rxPwPnRegisterContents.byte); // auto-ack pipe Write_NRF_Register(RX_PW_P2_ADDRESS, rxPwPnRegisterContents.byte); // not used Write_NRF_Register(RX_PW_P3_ADDRESS, rxPwPnRegisterContents.byte); // not used Write_NRF_Register(RX_PW_P4_ADDRESS, rxPwPnRegisterContents.byte); // not used Write_NRF_Register(RX_PW_P5_ADDRESS, rxPwPnRegisterContents.byte); // not used /* Enable auto acknowledge for pipe 1 */ enAaRegister.bits.ENAA_P0 = 1; enAaRegister.bits.ENAA_P1 = 1; enAaRegister.bits.ENAA_P2 = 1; enAaRegister.bits.ENAA_P3 = 1; enAaRegister.bits.ENAA_P4 = 1; enAaRegister.bits.ENAA_P5 = 1; Write_NRF_Register(EN_AA_ADDRESS, enAaRegister.byte); PCMSK2 |= (1< 32) || (length == 0)) { return success; } PCICR |= (1< 0)) { _delay_ms(1); duration --; }; if (nrfInterruptRaised == true) // check if a message was received { /* A message was received */ LED_PORT |= (1 << LED_PIN); statusRegisterContents.byte = Read_NRF_Status_Register(); if (statusRegisterContents.bits.RX_DR == 1) { fifoStatusRegisterContents.byte = Read_NRF_Status_Register(); if (fifoStatusRegisterContents.bits.RX_EMPTY != 1) { Read_Message_From_RX_FIFO(PACKET_LENGTH, buffer); /* TODO: only possible after CE = 0? */ messageReceived = true; } } nrfInterruptRaised = false; } // Set the NRF to standby NRF_CE_PORT &= ~(1 << NRF_CE_PIN); configRegisterContents.byte = Read_NRF_Register(CONFIG_ADDRESS); configRegisterContents.bits.PRIM_RX = 0x0; Write_NRF_Register(CONFIG_ADDRESS, configRegisterContents.byte); /* Reset the interrupts */ statusRegisterContents.bits.TX_DS = 1; statusRegisterContents.bits.MAX_RT = 1; statusRegisterContents.bits.RX_DR = 1; Write_NRF_Register(STATUS_ADDRESS, statusRegisterContents.byte); return messageReceived; } uint8_t Read_NRF_Status_Register(void) { uint8_t registerContents; registerContents = Write_One_Byte(0x0); return registerContents; } uint8_t Read_NRF_Register(uint8_t address) { uint8_t registerContents; registerContents = Write_Two_Bytes(address, 0x0); return registerContents; } void Write_NRF_Register(uint8_t address, uint8_t registerContents) { Write_Two_Bytes(address | 0x20, registerContents); } void Send_Activate_Command(void) { Write_Two_Bytes(0x50, 0x73); } void Send_TX_Flush_Command(void) { Write_One_Byte(FLUSH_TX_COMMAND); } void Send_RX_Flush_Command(void) { Write_One_Byte(FLUSH_RX_COMMAND); } static uint8_t Write_One_Byte(uint8_t byte1) { uint8_t registerContents = 0; SPI_Start_Transmission(&NRF_CSN_PORT, NRF_CSN_PIN); registerContents = SPI_Transfer_Byte(byte1); SPI_Stop_Transmission(&NRF_CSN_PORT, NRF_CSN_PIN); return registerContents; } static uint8_t Write_Two_Bytes(uint8_t byte1, uint8_t byte2) { uint8_t registerContents = 0; SPI_Start_Transmission(&NRF_CSN_PORT, NRF_CSN_PIN); SPI_Transfer_Byte(byte1); registerContents = SPI_Transfer_Byte(byte2); SPI_Stop_Transmission(&NRF_CSN_PORT, NRF_CSN_PIN); return registerContents; } void Write_Message_To_TX_FIFO(uint8_t length, uint8_t * buffer) { Write_Byte_And_Buffer(W_TX_PAYLOAD_COMMAND, buffer, length); } void Read_Message_From_RX_FIFO(uint8_t length, uint8_t * buffer) { SPI_Start_Transmission(&NRF_CSN_PORT, NRF_CSN_PIN); SPI_Transfer_Byte(R_RX_PAYLOAD_COMMAND); /* Write the data byte */ for (uint8_t i = 0; i < length; i ++) { buffer[i] = SPI_Transfer_Byte(0x0); } SPI_Stop_Transmission(&NRF_CSN_PORT, NRF_CSN_PIN); } void Set_TX_Address(uint8_t * txAddress, uint8_t length) { Write_Byte_And_Buffer(TX_ADDR_ADDRESS | 0x20, txAddress, length); } void Set_RX_P0_Address(uint8_t * rxAddress, uint8_t length) { Write_Byte_And_Buffer(RX_ADDR_P0_ADDRESS | 0x20, rxAddress, length); } void Set_RX_P1_Address(uint8_t * rxAddress, uint8_t length) { Write_Byte_And_Buffer(RX_ADDR_P1_ADDRESS | 0x20, rxAddress, length); } static void Write_Byte_And_Buffer(uint8_t byte, uint8_t * buffer, uint8_t length) { SPI_Start_Transmission(&NRF_CSN_PORT, NRF_CSN_PIN); SPI_Transfer_Byte(byte); /* Write the data byte */ for (uint8_t i = 0; i < length; i ++) { SPI_Transfer_Byte(buffer[i]); } SPI_Stop_Transmission(&NRF_CSN_PORT, NRF_CSN_PIN); }