Skip to content

Commit e6027fb

Browse files
committed
Centralise logic for starting DMA and USB transfers.
1 parent 10a7582 commit e6027fb

1 file changed

Lines changed: 82 additions & 66 deletions

File tree

firmware/hackrf_usb/usb_api_transceiver.c

Lines changed: 82 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -552,39 +552,92 @@ void transceiver_bulk_transfer_complete(void* user_data, unsigned int bytes_tran
552552
usb_completed += bytes_transferred;
553553
}
554554

555+
typedef enum {
556+
DIRECTION_RX,
557+
DIRECTION_TX,
558+
} direction_t;
559+
560+
void start_dma_if_possible(direction_t direction, size_t size)
561+
{
562+
if (dma_pending) {
563+
return;
564+
}
565+
566+
uint32_t sampling_completed = m0_state.m0_count;
567+
uint32_t dma_completed = m0_state.m4_count;
568+
uint32_t samp_offset = dma_started & USB_SAMP_BUFFER_MASK;
569+
uint32_t bulk_offset = dma_started & USB_BULK_BUFFER_MASK;
570+
uint32_t data_available, space_in_use, space_available;
571+
uint8_t *dest, *src;
572+
573+
if (direction == DIRECTION_RX) {
574+
data_available = sampling_completed - dma_started;
575+
space_in_use = usb_completed - dma_completed;
576+
space_available = USB_BULK_BUFFER_SIZE - space_in_use;
577+
src = &usb_samp_buffer[samp_offset];
578+
dest = &usb_bulk_buffer[bulk_offset];
579+
} else {
580+
data_available = usb_completed - dma_started;
581+
space_in_use = dma_started - sampling_completed;
582+
space_available = USB_SAMP_BUFFER_SIZE - space_in_use;
583+
src = &usb_bulk_buffer[bulk_offset];
584+
dest = &usb_samp_buffer[samp_offset];
585+
}
586+
587+
if (data_available < size || size > space_available) {
588+
return;
589+
}
590+
591+
bool ahb_busy = !((sampling_completed ^ dma_started) & BUF_HALF_MASK);
592+
593+
if (ahb_busy) {
594+
return;
595+
}
596+
597+
transceiver_start_dma(src, dest, size);
598+
599+
dma_started += size;
600+
}
601+
602+
void start_usb_if_possible(direction_t direction)
603+
{
604+
uint32_t bulk_offset = usb_started & USB_BULK_BUFFER_MASK;
605+
uint32_t dma_completed = m0_state.m4_count;
606+
uint32_t bytes_available;
607+
usb_endpoint_t* usb_endpoint;
608+
609+
if (direction == DIRECTION_RX) {
610+
bytes_available = dma_completed - usb_started;
611+
usb_endpoint = &usb_endpoint_bulk_in;
612+
} else {
613+
uint32_t space_used = usb_started - dma_completed;
614+
bytes_available = USB_BULK_BUFFER_SIZE - space_used;
615+
usb_endpoint = &usb_endpoint_bulk_out;
616+
}
617+
618+
if (bytes_available < USB_TRANSFER_SIZE) {
619+
return;
620+
}
621+
622+
usb_transfer_schedule_block(
623+
usb_endpoint,
624+
&usb_bulk_buffer[bulk_offset],
625+
USB_TRANSFER_SIZE,
626+
transceiver_bulk_transfer_complete,
627+
NULL);
628+
629+
usb_started += USB_TRANSFER_SIZE;
630+
}
631+
555632
void rx_mode(uint32_t seq)
556633
{
557634
transceiver_startup(TRANSCEIVER_MODE_RX);
558635

559636
baseband_streaming_enable(&sgpio_config);
560637

561638
while (transceiver_request.seq == seq) {
562-
uint32_t data_gathered = m0_state.m0_count;
563-
uint32_t dma_completed = m0_state.m4_count;
564-
uint32_t data_available = data_gathered - dma_started;
565-
uint32_t space_in_use = usb_completed - dma_completed;
566-
uint32_t space_available = USB_BULK_BUFFER_SIZE - space_in_use;
567-
bool ahb_busy = !((data_gathered ^ dma_started) & BUF_HALF_MASK);
568-
if (!dma_pending && !ahb_busy && (data_available >= DMA_TRANSFER_SIZE) &&
569-
(space_available >= DMA_TRANSFER_SIZE)) {
570-
uint32_t samp_offset = dma_started & USB_SAMP_BUFFER_MASK;
571-
uint32_t bulk_offset = dma_started & USB_BULK_BUFFER_MASK;
572-
transceiver_start_dma(
573-
&usb_samp_buffer[samp_offset],
574-
&usb_bulk_buffer[bulk_offset],
575-
DMA_TRANSFER_SIZE);
576-
dma_started += DMA_TRANSFER_SIZE;
577-
}
578-
if ((dma_completed - usb_started) >= USB_TRANSFER_SIZE) {
579-
uint32_t bulk_offset = usb_started & USB_BULK_BUFFER_MASK;
580-
usb_transfer_schedule_block(
581-
&usb_endpoint_bulk_in,
582-
&usb_bulk_buffer[bulk_offset],
583-
USB_TRANSFER_SIZE,
584-
transceiver_bulk_transfer_complete,
585-
NULL);
586-
usb_started += USB_TRANSFER_SIZE;
587-
}
639+
start_dma_if_possible(DIRECTION_RX, DMA_TRANSFER_SIZE);
640+
start_usb_if_possible(DIRECTION_RX);
588641
}
589642

590643
transceiver_shutdown();
@@ -624,32 +677,8 @@ void tx_mode(uint32_t seq)
624677

625678
// Continue feeding samples to the sample buffer.
626679
while (transceiver_request.seq == seq) {
627-
uint32_t data_used = m0_state.m0_count;
628-
uint32_t dma_completed = m0_state.m4_count;
629-
uint32_t data_available = usb_completed - dma_started;
630-
uint32_t space_in_use = dma_started - data_used;
631-
uint32_t space_available = USB_SAMP_BUFFER_SIZE - space_in_use;
632-
bool ahb_busy = !((data_used ^ dma_started) & BUF_HALF_MASK);
633-
if (!dma_pending && !ahb_busy && (data_available >= DMA_TRANSFER_SIZE) &&
634-
(space_available >= DMA_TRANSFER_SIZE)) {
635-
uint32_t samp_offset = dma_started & USB_SAMP_BUFFER_MASK;
636-
uint32_t bulk_offset = dma_started & USB_BULK_BUFFER_MASK;
637-
transceiver_start_dma(
638-
&usb_bulk_buffer[bulk_offset],
639-
&usb_samp_buffer[samp_offset],
640-
DMA_TRANSFER_SIZE);
641-
dma_started += DMA_TRANSFER_SIZE;
642-
}
643-
if ((usb_started - dma_completed) <= USB_TRANSFER_SIZE) {
644-
uint32_t bulk_offset = usb_started & USB_BULK_BUFFER_MASK;
645-
usb_transfer_schedule_block(
646-
&usb_endpoint_bulk_out,
647-
&usb_bulk_buffer[bulk_offset],
648-
USB_TRANSFER_SIZE,
649-
transceiver_bulk_transfer_complete,
650-
NULL);
651-
usb_started += USB_TRANSFER_SIZE;
652-
}
680+
start_dma_if_possible(DIRECTION_TX, DMA_TRANSFER_SIZE);
681+
start_usb_if_possible(DIRECTION_TX);
653682
}
654683

655684
// Host has now requested to stop TX. If we're not auto-flushing, we
@@ -698,23 +727,10 @@ void tx_mode(uint32_t seq)
698727
// Any remainder of less than 4 bytes will be ignored; this is the chunk
699728
// size of our DMA transfers.
700729
while ((usb_completed - m0_state.m4_count) >= 4) {
701-
uint32_t data_used = m0_state.m0_count;
702730
uint32_t data_available = usb_completed - dma_started;
703-
uint32_t space_in_use = dma_started - data_used;
704-
uint32_t space_available = USB_SAMP_BUFFER_SIZE - space_in_use;
705-
uint32_t samp_offset = dma_started & USB_SAMP_BUFFER_MASK;
706-
uint32_t bulk_offset = dma_started & USB_BULK_BUFFER_MASK;
707-
bool ahb_busy = !((data_used ^ dma_started) & BUF_HALF_MASK);
708731
size_t size = data_available >= DMA_TRANSFER_SIZE ? DMA_TRANSFER_SIZE :
709732
data_available;
710-
if (dma_pending || ahb_busy || size > space_available) {
711-
continue;
712-
}
713-
transceiver_start_dma(
714-
&usb_bulk_buffer[bulk_offset],
715-
&usb_samp_buffer[samp_offset],
716-
size);
717-
dma_started += size;
733+
start_dma_if_possible(DIRECTION_TX, size);
718734
}
719735

720736
// Wait for the data in the sample buffer to be transmitted.

0 commit comments

Comments
 (0)