diff --git a/firmware/hackrf_usb/m0_state.h b/firmware/hackrf_usb/m0_state.h index 2ce24980..ef28afaf 100644 --- a/firmware/hackrf_usb/m0_state.h +++ b/firmware/hackrf_usb/m0_state.h @@ -37,7 +37,8 @@ struct m0_state { enum m0_mode { M0_MODE_IDLE = 0, M0_MODE_RX = 1, - M0_MODE_TX = 2, + M0_MODE_TX_START = 2, + M0_MODE_TX_RUN = 3, }; /* Address of m0_state is set in ldscripts. If you change the name of this diff --git a/firmware/hackrf_usb/sgpio_m0.s b/firmware/hackrf_usb/sgpio_m0.s index b2189c9c..6f4613bb 100644 --- a/firmware/hackrf_usb/sgpio_m0.s +++ b/firmware/hackrf_usb/sgpio_m0.s @@ -68,8 +68,8 @@ There are four key code paths, with the following worst-case timings: RX, normal: 147 cycles RX, overrun: 76 cycles -TX, normal: 133 cycles -TX, underrun: 140 cycles +TX, normal: 138 cycles +TX, underrun: 142 cycles Design ====== @@ -118,7 +118,8 @@ registers and fixed memory addresses. // Operating modes. .equ MODE_IDLE, 0 .equ MODE_RX, 1 -.equ MODE_TX, 2 +.equ MODE_TX_START, 2 +.equ MODE_TX_RUN, 3 // Our slice chain is set up as follows (ascending data age; arrows are reversed for flow): // L -> F -> K -> C -> J -> E -> I -> A @@ -179,7 +180,7 @@ main: idle: // Wait for RX or TX mode to be set. - mode .req r0 + mode .req r3 ldr mode, [state, #MODE] // mode = state.mode // 2 cmp mode, #MODE_IDLE // if mode == IDLE: // 1 beq idle // goto idle // 1 thru, 3 taken @@ -230,7 +231,7 @@ loop: add buf_ptr, buf_base // buf_ptr += buf_base // 1 // Load mode. - mode .req r0 + mode .req r3 ldr mode, [state, #MODE] // mode = state.mode // 2 // Branch according to mode setting. @@ -255,6 +256,15 @@ direction_tx: sub buf_margin, #32 // buf_margin -= 32 // 1 bmi tx_zeros // if buf_margin < 0: goto tx_zeros // 1 thru, 3 taken + // At this point we know there is TX data available. + // If still in TX start mode, switch to TX run. + cmp mode, #MODE_TX_START // if mode != TX_START: // 1 + bne tx_write // goto tx_write // 1 thru, 3 taken + mov mode, #MODE_TX_RUN // mode = TX_RUN // 1 + str mode, [state, #MODE] // state.mode = mode // 2 + +tx_write: + // Write data to SGPIO. ldm buf_ptr!, {r0-r3} // r0-r3 = buf_ptr[0:16]; buf_ptr += 16 // 5 str r0, [sgpio_data, #SLICE0] // SGPIO_REG_SS[SLICE0] = r0 // 8 @@ -282,6 +292,10 @@ tx_zeros: str zero, [sgpio_data, #SLICE6] // SGPIO_REG_SS[SLICE6] = zero // 8 str zero, [sgpio_data, #SLICE7] // SGPIO_REG_SS[SLICE7] = zero // 8 + // If in TX start mode, don't count this as a shortfall. + cmp mode, #MODE_TX_START // if mode == TX_START: // 1 + beq loop // goto loop // 1 thru, 3 taken + shortfall: // Get current shortfall length from high register. diff --git a/firmware/hackrf_usb/usb_api_transceiver.c b/firmware/hackrf_usb/usb_api_transceiver.c index f0f9b137..03d99747 100644 --- a/firmware/hackrf_usb/usb_api_transceiver.c +++ b/firmware/hackrf_usb/usb_api_transceiver.c @@ -296,7 +296,7 @@ void transceiver_startup(const transceiver_mode_t mode) { led_off(LED2); led_on(LED3); rf_path_set_direction(&rf_path, RF_PATH_DIRECTION_TX); - m0_state.mode = M0_MODE_TX; + m0_state.mode = M0_MODE_TX_START; m0_state.shortfall_limit = _tx_underrun_limit; break; default: diff --git a/host/hackrf-tools/src/hackrf_debug.c b/host/hackrf-tools/src/hackrf_debug.c index 38e832bd..3d107e06 100644 --- a/host/hackrf-tools/src/hackrf_debug.c +++ b/host/hackrf-tools/src/hackrf_debug.c @@ -378,7 +378,7 @@ int write_register(hackrf_device* device, uint8_t part, } static void print_state(hackrf_m0_state *state) { - const char *mode_names[] = {"IDLE", "RX", "TX"}; + const char *mode_names[] = {"IDLE", "RX", "TX_START", "TX_RUN"}; const uint32_t num_modes = sizeof(mode_names) / sizeof(mode_names[0]); printf("M0 state:\n"); printf("Mode: %u (%s)\n",