+ uint8_t success = 0;
+
+ ao_radio_abort = 0;
+ ao_radio_get(size - 2);
+ ao_radio_set_mode(AO_RADIO_MODE_PACKET_RX);
+ ao_radio_wake = 0;
+ ao_radio_start_rx();
+
+ while (!ao_radio_abort) {
+ ao_radio_wait_isr(timeout);
+ if (ao_radio_wake) {
+ uint8_t marc_status1 = ao_radio_reg_read(CC1200_MARC_STATUS1);
+
+ /* Check the receiver status to see what happened
+ */
+ switch (marc_status1) {
+ case CC1200_MARC_STATUS1_RX_FINISHED:
+ case CC1200_MARC_STATUS1_ADDRESS:
+ case CC1200_MARC_STATUS1_CRC:
+ /* Normal return, go fetch the bytes from the FIFO
+ * and give them back to the caller
+ */
+ success = 1;
+ break;
+ case CC1200_MARC_STATUS1_RX_TIMEOUT:
+ case CC1200_MARC_STATUS1_RX_TERMINATION:
+ case CC1200_MARC_STATUS1_EWOR_SYNC_LOST:
+ case CC1200_MARC_STATUS1_MAXIMUM_LENGTH:
+ case CC1200_MARC_STATUS1_RX_FIFO_OVERFLOW:
+ case CC1200_MARC_STATUS1_RX_FIFO_UNDERFLOW:
+ /* Something weird happened; reset the radio and
+ * return failure
+ */
+ success = 0;
+ break;
+ default:
+ /* some other status; go wait for the radio to do something useful
+ */
+ continue;
+ }
+ break;
+ } else {
+ uint8_t modem_status1 = ao_radio_reg_read(CC1200_MODEM_STATUS1);
+
+ /* Check to see if the packet header has been seen, in which case we'll
+ * want to keep waiting for the rest of the packet to appear
+ */
+ if (modem_status1 & (1 << CC1200_MODEM_STATUS1_SYNC_FOUND))
+ {
+ ao_radio_abort = 0;
+
+ /* Set a timeout based on the packet length so that we make sure to
+ * wait long enough to receive the whole thing.
+ *
+ * timeout = bits * FEC expansion / rate
+ */
+ switch (ao_config.radio_rate) {
+ default:
+ case AO_RADIO_RATE_38400:
+ timeout = AO_MS_TO_TICKS(size * (8 * 2 * 10) / 384) + 1;
+ break;
+ case AO_RADIO_RATE_9600:
+ timeout = AO_MS_TO_TICKS(size * (8 * 2 * 10) / 96) + 1;
+ break;
+ case AO_RADIO_RATE_2400:
+ timeout = AO_MS_TO_TICKS(size * (8 * 2 * 10) / 24) + 1;
+ break;
+ }
+ }
+ }
+ }
+
+ if (success) {
+ int8_t rssi;
+ uint8_t status;
+
+ status = ao_radio_fifo_read(d, size);
+ (void) status;
+ rssi = ((int8_t *) d)[size - 2];
+ ao_radio_rssi = rssi;
+
+ /* Bound it to the representable range */
+ if (rssi > -11)
+ rssi = -11;
+
+ /* Write it back to the packet */
+ ((int8_t *) d)[size-2] = AO_RADIO_FROM_RSSI(rssi);
+ } else {
+ ao_radio_idle();
+ ao_radio_rssi = 0;
+ }
+
+ ao_radio_put();
+ return success;