Add an idle mode for the M0.
In the idle mode, the M0 simply waits for a different mode to be set. No SGPIO access is done. One extra cycle is added to both TX code paths, to check whether the M0 should return to the idle loop based on the mode setting. The RX paths are unaffected as the branch to RX is handled first.
This commit is contained in:
@ -32,8 +32,9 @@ struct m0_state {
|
||||
};
|
||||
|
||||
enum m0_mode {
|
||||
M0_MODE_RX = 0,
|
||||
M0_MODE_TX = 1,
|
||||
M0_MODE_IDLE = 0,
|
||||
M0_MODE_RX = 1,
|
||||
M0_MODE_TX = 2,
|
||||
};
|
||||
|
||||
/* Address of m0_state is set in ldscripts. If you change the name of this
|
||||
|
@ -68,8 +68,8 @@ There are four key code paths, with the following worst-case timings:
|
||||
|
||||
RX, normal: 146 cycles
|
||||
RX, overrun: 52 cycles
|
||||
TX, normal: 131 cycles
|
||||
TX, underrun: 118 cycles
|
||||
TX, normal: 132 cycles
|
||||
TX, underrun: 119 cycles
|
||||
|
||||
Design
|
||||
======
|
||||
@ -113,8 +113,9 @@ registers and fixed memory addresses.
|
||||
.equ M4_COUNT, 0x08
|
||||
|
||||
// Operating modes.
|
||||
.equ MODE_RX, 0
|
||||
.equ MODE_TX, 1
|
||||
.equ MODE_IDLE, 0
|
||||
.equ MODE_RX, 1
|
||||
.equ MODE_TX, 2
|
||||
|
||||
// Our slice chain is set up as follows (ascending data age; arrows are reversed for flow):
|
||||
// L -> F -> K -> C -> J -> E -> I -> A
|
||||
@ -167,6 +168,13 @@ main:
|
||||
str zero, [state, #M0_COUNT] // state.m0_count = zero // 2
|
||||
str zero, [state, #M4_COUNT] // state.m4_count = zero // 2
|
||||
|
||||
idle:
|
||||
// Wait for RX or TX mode to be set.
|
||||
mode .req r0
|
||||
ldr mode, [state, #MODE] // mode = state.mode // 2
|
||||
cmp mode, #MODE_IDLE // if mode == IDLE: // 1
|
||||
beq idle // goto idle // 1 thru, 3 taken
|
||||
|
||||
loop:
|
||||
// The worst case timing is assumed to occur when reading the interrupt
|
||||
// status register *just* misses the flag being set - so we include the
|
||||
@ -208,9 +216,10 @@ loop:
|
||||
mode .req r0
|
||||
ldr mode, [state, #MODE] // mode = state.mode // 2
|
||||
|
||||
// TX?
|
||||
// Branch according to mode setting.
|
||||
cmp mode, #MODE_RX // if mode == RX: // 1
|
||||
beq direction_rx // goto direction_rx // 1 thru, 3 taken
|
||||
blt idle // elif mode < RX: goto idle // 1 thru, 3 taken
|
||||
|
||||
direction_tx:
|
||||
|
||||
|
@ -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[] = {"RX", "TX"};
|
||||
const char *mode_names[] = {"IDLE", "RX", "TX"};
|
||||
const uint32_t num_modes = sizeof(mode_names) / sizeof(mode_names[0]);
|
||||
printf("M0 state:\n");
|
||||
printf("Mode: %u (%s)\n",
|
||||
|
Reference in New Issue
Block a user