static void flasher_tx_handle(void) { static uint8_t first_tx = 1; /* * If more than a second has passed since previous communication * the bootloader will have left the flash mode by now so this is * probably a new boot and a new flashing attempt. */ if ((uint32_t) (timer_read() - prev_txrx_ts) > F_CPU) first_tx = 1; /* * Before any actual STK500v2 communication begins we need to * attempt to reset the board to start the bootloader, and send it * our radio address to return the ACK packets to. */ if (first_tx) { uint8_t ch, pkt[4]; /* * Our protocol requires any program running on the board * to reset it if it receives a 0xff byte. */ ch = 0xff; nrf24_tx(&ch, 1); nrf24_tx_result_wait(); /* Give the board time to reboot and enter the bootloader */ my_delay(100); /* Finally send our address + pkt size as a separate packet */ pkt[0] = eeprom_read(0); pkt[1] = eeprom_read(1); pkt[2] = eeprom_read(2); pkt[3] = MAX_PKT_SIZE; /* TODO: set the no-ACK bit, the remote board can't ACK yet */ nrf24_tx(pkt, 4); nrf24_tx_result_wait(); first_tx = 0; } prev_txrx_ts = timer_read(); }
void loop(void) { static uint8_t tx_cnt; /* Consecutive Tx packets counter */ /* * Note: all nrf24 calls are serialised in this function so as * to avoid any concurrency issues. */ if (nrf24_rx_fifo_data()) { uint8_t pkt_len, pkt_buf[32], i; #ifdef SEQN static uint8_t seqn = 0xff; #endif #ifdef FLASH_TOOL_MODE flasher_rx_handle(); #endif nrf24_rx_read(pkt_buf, &pkt_len); #ifdef SEQN if (pkt_buf[0] != seqn) { seqn = pkt_buf[0]; for (i = 1; i < pkt_len; i ++) serial_write1(pkt_buf[i]); } #else for (i = 0; i < pkt_len; i ++) serial_write1(pkt_buf[i]); #endif tx_cnt = 0; } if (tx_fifo.len) { /* .len access should be atomic */ uint8_t pkt_len, pkt_buf[MAX_PKT_SIZE], split; #ifdef SEQN static uint8_t seqn = 0x00; uint8_t count = 128; #define MAX_PLD_SIZE (MAX_PKT_SIZE - 1) pkt_buf[0] = seqn ++; #else uint8_t count = 2; #define MAX_PLD_SIZE MAX_PKT_SIZE #endif #ifdef FLASH_TOOL_MODE flasher_tx_handle(); #endif tx_cnt ++; cli(); pkt_len = min(tx_fifo.len, MAX_PLD_SIZE); sei(); /* HACK */ if (tx_cnt == 2 && MAX_PLD_SIZE > 2 && pkt_len == MAX_PLD_SIZE) pkt_len = MAX_PLD_SIZE - 2; else if (MAX_PLD_SIZE > 2 && tx_cnt == 3) pkt_len = 1; split = min(pkt_len, (uint16_t) (~tx_fifo.start & FIFO_MASK) + 1); #define START (MAX_PKT_SIZE - MAX_PLD_SIZE) memcpy(pkt_buf + START, tx_fifo.data + (tx_fifo.start & FIFO_MASK), split); memcpy(pkt_buf + START + split, tx_fifo.data, pkt_len - split); /* * Or we could just do pkt_buf = tx_fifo.data + ...; * pkt_len = split; */ cli(); tx_fifo.len -= pkt_len; tx_fifo.start += pkt_len; sei(); while (-- count) { /* Don't flood the remote end with the comms */ my_delay(4); nrf24_tx(pkt_buf, pkt_len + START); if (!nrf24_tx_result_wait()) break; } } }
bool RHReliableDatagram::sendtoWait(uint8_t *buf, uint8_t len, uint8_t address) { update_tx_addr(address); nrf24_tx(buf, len); return !nrf24_tx_result_wait(); }