/* * ad0x0, 2020 * */ #include "RF24.h" //#include "../ad0x0_spi2.h" #include "../usart/ad0x0_usart.h" #include //------------------------------------------------ rf24_spi_regs_t r_spi2_regs; uint8_t NRF_Init(void) { //2E0703002C135737334D4E00 rf24_init_spi2_regs(&r_spi2_regs,AD_NFR24_CE_GPIO_Port, AD_NFR24_CE_Pin); r_spi2_regs.init_pipes(); r_spi2_regs.PTX_init(); // Reset current status. Notice reset and flush is the last thing we do /* write_register(NRF_STATUS, (1 << RX_DR) | (1 << TX_DS) | (1 << MAX_RT)); setChannel(76); flush_rx(); flush_tx(); powerUp(); //Power up by default when begin() is called write_register(NRF_CONFIG, (read_register(NRF_CONFIG)) & ~(1 << PRIM_RX)); */ return 1; } /* bool isChipConnected() { uint8_t setup = read_register(SETUP_AW); if(setup >= 1 && setup <= 3) { return true; } return false; } void startListening(void) { powerUp(); write_register(NRF_CONFIG, read_register(NRF_CONFIG) | (1 << PRIM_RX)); write_register(NRF_STATUS, (1 << RX_DR) | (1 << TX_DS) | (1 << MAX_RT)); ce(HIGH); // Restore the pipe0 adddress, if exists if(pipe0_reading_address[0] > 0) { write_registerMy(RX_ADDR_P0, pipe0_reading_address, addr_width); } else { closeReadingPipe(0); } if(read_register(FEATURE) & (1 << EN_ACK_PAY)) { flush_tx(); } } static const uint8_t child_pipe_enable[] = {ERX_P0, ERX_P1, ERX_P2, ERX_P3, ERX_P4, ERX_P5}; void stopListening(void) { ce(LOW); delay_us(txDelay); if(read_register(FEATURE) & (1 << EN_ACK_PAY)) { delay_us(txDelay); //200 flush_tx(); } write_register(NRF_CONFIG, (read_register(NRF_CONFIG)) & ~(1 << PRIM_RX)); write_register(EN_RXADDR, read_register(EN_RXADDR) | (1 << child_pipe_enable[0])); // Enable RX on pipe0 } void powerDown(void) { ce(LOW); // Guarantee CE is low on powerDown write_register(NRF_CONFIG, read_register(NRF_CONFIG) & ~(1 << PWR_UP)); } //Power up now. Radio will not power down unless instructed by MCU for config changes etc. void powerUp(void) { uint8_t cfg = read_register(NRF_CONFIG); // if not powered up then power up and wait for the radio to initialize if(!(cfg & (1 << PWR_UP))) { write_register(NRF_CONFIG, cfg | (1 << PWR_UP)); HAL_Delay(5); } } //Similar to the previous write, clears the interrupt flags bool write(const void* buf, uint8_t len) { startFastWrite(buf, len, 1, 1); while(!(get_status() & ((1 << TX_DS) | (1 << MAX_RT)))) {} ce(LOW); uint8_t status = write_register(NRF_STATUS, (1 << RX_DR) | (1 << TX_DS) | (1 << MAX_RT)); if(status & (1 << 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; } void startFastWrite(const void* buf, uint8_t len, const bool multicast, bool startTx) { write_payload(buf, len, multicast ? W_TX_PAYLOAD_NO_ACK : W_TX_PAYLOAD); if(startTx) { ce(HIGH); } } void maskIRQ(bool tx, bool fail, bool rx) { uint8_t config = read_register(NRF_CONFIG); config &= ~(1 << MASK_MAX_RT | 1 << MASK_TX_DS | 1 << MASK_RX_DR); //clear the interrupt flags config |= fail << MASK_MAX_RT | tx << MASK_TX_DS | rx << MASK_RX_DR; // set the specified interrupt flags write_register(NRF_CONFIG, config); } uint8_t getDynamicPayloadSize(void) { uint8_t result = 0, addr; csn(LOW); addr = R_RX_PL_WID; HAL_SPI_TransmitReceive(&hspi1, &addr, &result, 1, 1000); HAL_SPI_TransmitReceive(&hspi1, (uint8_t*)0xff, &result, 1, 1000); csn(HIGH); if(result > 32) { flush_rx(); HAL_Delay(2); return 0; } return result; } bool availableMy(void) { return available(NULL); } bool available(uint8_t* pipe_num) { if(!(read_register(FIFO_STATUS) & (1 << RX_EMPTY))) { if(pipe_num) // If the caller wants the pipe number, include that { uint8_t status = get_status(); *pipe_num = (status >> RX_P_NO) & 0x07; } return 1; } return 0; } void read(void* buf, uint8_t len) { read_payload(buf, len); write_register(NRF_STATUS, (1 << RX_DR) | (1 << MAX_RT) | (1 << TX_DS)); } uint8_t whatHappened() { uint8_t status = write_register(NRF_STATUS, (1 << RX_DR) | (1 << TX_DS) | (1 << MAX_RT)); return status; } void openWritingPipe(uint64_t value) { write_registerMy(RX_ADDR_P0, (uint8_t*)&value, addr_width); write_registerMy(TX_ADDR, (uint8_t*)&value, addr_width); write_register(RX_PW_P0, payload_size); } static const uint8_t child_pipe[] = {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[] = {RX_PW_P0, RX_PW_P1, RX_PW_P2, RX_PW_P3, RX_PW_P4, RX_PW_P5}; void openReadingPipe(uint8_t child, uint64_t address) { 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_registerMy(child_pipe[child], (const uint8_t*)&address, addr_width); else write_registerMy(child_pipe[child], (const uint8_t*)&address, 1); write_register(child_payload_size[child], payload_size); write_register(EN_RXADDR, read_register(EN_RXADDR) | (1 << child_pipe_enable[child])); } } void setAddressWidth(uint8_t a_width) { if(a_width -= 2) { write_register(SETUP_AW, a_width%4); addr_width = (a_width%4) + 2; } else { write_register(SETUP_AW, 0); addr_width = 2; } } void closeReadingPipe(uint8_t pipe) { write_register(EN_RXADDR, read_register(EN_RXADDR) & ~(1 << child_pipe_enable[pipe])); } void toggle_features(void) { uint8_t addr = ACTIVATE; csn(LOW); HAL_SPI_Transmit(&hspi1, &addr, 1, 1000); HAL_SPI_Transmit(&hspi1, (uint8_t*)0x73, 1, 1000); csn(HIGH); } void enableDynamicPayloads(void) { write_register(FEATURE, read_register(FEATURE) | (1 << EN_DPL)); write_register(DYNPD, read_register(DYNPD) | (1 << DPL_P5) | (1 << DPL_P4) | (1 << DPL_P3) | (1 << DPL_P2) | (1 << DPL_P1) | (1 << DPL_P0)); dynamic_payloads_enabled = true; } void disableDynamicPayloads(void) { write_register(FEATURE, 0); write_register(DYNPD, 0); dynamic_payloads_enabled = false; } void enableAckPayload(void) { write_register(FEATURE, read_register(FEATURE) | (1 << EN_ACK_PAY) | (1 << EN_DPL)); write_register(DYNPD, read_register(DYNPD) | (1 << DPL_P1) | (1 << DPL_P0)); dynamic_payloads_enabled = true; } void enableDynamicAck(void) { write_register(FEATURE, read_register(FEATURE) | (1 << EN_DYN_ACK)); } void writeAckPayload(uint8_t pipe, const void* buf, uint8_t len) { const uint8_t* current = (const uint8_t*)buf; uint8_t data_len = rf24_min(len, 32); uint8_t addr = W_ACK_PAYLOAD | (pipe & 0x07); csn(LOW); HAL_SPI_Transmit(&hspi1, &addr, 1, 1000); HAL_SPI_Transmit(&hspi1, (uint8_t*)current, data_len, 1000); csn(HIGH); } bool isAckPayloadAvailable(void) { return !(read_register(FIFO_STATUS) & (1 << RX_EMPTY)); } bool isPVariant(void) { return p_variant; } void setAutoAck(bool enable) { if(enable) write_register(EN_AA, 0x3F); else write_register(EN_AA, 0); } void setAutoAckPipe(uint8_t pipe, bool enable) { if(pipe <= 6) { uint8_t en_aa = read_register(EN_AA); if(enable) { en_aa |= (1 << pipe); } else { en_aa &= ~(1 << pipe); } write_register(EN_AA, en_aa); } } uint8_t getPALevel(void) { return (read_register(RF_SETUP) & ((1 << RF_PWR_LOW) | (1 << RF_PWR_HIGH))) >> 1; } bool setDataRate(rf24_datarate_e speed) { bool result = false; uint8_t setup = read_register(RF_SETUP); setup &= ~((1 << RF_DR_LOW) | (1 << RF_DR_HIGH)); txDelay = 85; if(speed == RF24_250KBPS) { setup |= (1 << RF_DR_LOW); txDelay = 155; } else { if(speed == RF24_2MBPS) { setup |= (1 << RF_DR_HIGH); txDelay = 65; } } write_register(RF_SETUP, setup); uint8_t ggg = read_register(RF_SETUP); if(ggg == setup) { result = true; } return result; } rf24_datarate_e getDataRate(void) { rf24_datarate_e result ; uint8_t dr = read_register(RF_SETUP) & ((1 << RF_DR_LOW) | (1 << RF_DR_HIGH)); // switch uses RAM (evil!) // Order matters in our case below if(dr == (1 << RF_DR_LOW)) { result = RF24_250KBPS; } else if(dr == (1 << RF_DR_HIGH)) { result = RF24_2MBPS; } else { result = RF24_1MBPS; } return result; } void setCRCLength(rf24_crclength_e length) { uint8_t config = read_register(NRF_CONFIG) & ~((1 << CRCO) | (1 << EN_CRC)); if(length == RF24_CRC_DISABLED) { // Do nothing, we turned it off above. } else if(length == RF24_CRC_8) { config |= (1 << EN_CRC); } else { config |= (1 << EN_CRC); config |= (1 << CRCO); } write_register(NRF_CONFIG, config); } rf24_crclength_e getCRCLength(void) { rf24_crclength_e result = RF24_CRC_DISABLED; uint8_t config = read_register(NRF_CONFIG) & ((1 << CRCO) | (1 << EN_CRC)); uint8_t AA = read_register(EN_AA); if(config & (1 << EN_CRC) || AA) { if(config & (1 << CRCO)) result = RF24_CRC_16; else result = RF24_CRC_8; } return result; } void disableCRC(void) { uint8_t disable = read_register(NRF_CONFIG) & ~(1 << EN_CRC); write_register(NRF_CONFIG, disable); } */ /*void DWT_Init(void) { SCB_DEMCR |= CoreDebug_DEMCR_TRCENA_Msk; // разрешаем использовать счётчик DWT_CONTROL |= DWT_CTRL_CYCCNTENA_Msk; // запускаем счётчик } void delay_us(uint32_t us) // DelayMicro { uint32_t us_count_tic = us * (SystemCoreClock / 1000000); DWT->CYCCNT = 0U; // обнуляем счётчик while(DWT->CYCCNT < us_count_tic); } */