Merge pull request #164 from tannewt/better_timeouts
Use microsecond for better timeout tracking
This commit is contained in:
commit
dd18302231
10 changed files with 152 additions and 100 deletions
|
|
@ -14,7 +14,6 @@
|
|||
#include "pio_usb_configuration.h"
|
||||
#include "pio_usb_ll.h"
|
||||
#include "usb_definitions.h"
|
||||
#include "usb_rx.pio.h"
|
||||
|
||||
pio_usb_configuration_t pio_usb_config = PIO_USB_DEFAULT_CONFIG;
|
||||
|
||||
|
|
|
|||
156
src/pio_usb.c
156
src/pio_usb.c
|
|
@ -23,8 +23,6 @@
|
|||
#include "pio_usb_configuration.h"
|
||||
#include "pio_usb_ll.h"
|
||||
#include "usb_crc.h"
|
||||
#include "usb_tx.pio.h"
|
||||
#include "usb_rx.pio.h"
|
||||
|
||||
#define UNUSED_PARAMETER(x) (void)x
|
||||
|
||||
|
|
@ -42,24 +40,33 @@ static uint8_t pre_encoded[5];
|
|||
// Bus functions
|
||||
//--------------------------------------------------------------------+
|
||||
|
||||
static void __no_inline_not_in_flash_func(send_pre)(const pio_port_t *pp) {
|
||||
static void __no_inline_not_in_flash_func(send_pre)(pio_port_t *pp) {
|
||||
// send PRE token in full-speed
|
||||
pp->low_speed = false;
|
||||
uint16_t instr = pp->fs_tx_pre_program->instructions[0];
|
||||
pp->pio_usb_tx->instr_mem[pp->offset_tx] = instr;
|
||||
|
||||
SM_SET_CLKDIV(pp->pio_usb_tx, pp->sm_tx, pp->clk_div_fs_tx);
|
||||
|
||||
pio_sm_exec(pp->pio_usb_tx, pp->sm_tx, pp->tx_start_instr);
|
||||
pp->pio_usb_tx->irq = IRQ_TX_ALL_MASK; // clear complete flag
|
||||
dma_channel_transfer_from_buffer_now(pp->tx_ch, pre_encoded,
|
||||
sizeof(pre_encoded));
|
||||
pp->pio_usb_tx->irq = IRQ_TX_ALL_MASK; // clear complete flag
|
||||
|
||||
while ((pp->pio_usb_tx->irq & IRQ_TX_EOP_MASK) == 0) {
|
||||
continue;
|
||||
}
|
||||
pio_sm_clear_fifos(pp->pio_usb_tx, pp->sm_tx);
|
||||
// Wait for complete transmission of the PRE packet. We don't want to
|
||||
// accidentally send trailing Ks in low speed mode due to an early start
|
||||
// instruction that re-enables the outputs.
|
||||
uint32_t stall_mask = 1 << (PIO_FDEBUG_TXSTALL_LSB + pp->sm_tx);
|
||||
pp->pio_usb_tx->fdebug = stall_mask; // clear sticky stall mask bit
|
||||
while (!(pp->pio_usb_tx->fdebug & stall_mask)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// change bus speed to low-speed
|
||||
pp->low_speed = true;
|
||||
pio_sm_set_enabled(pp->pio_usb_tx, pp->sm_tx, false);
|
||||
instr = pp->fs_tx_program->instructions[0];
|
||||
pp->pio_usb_tx->instr_mem[pp->offset_tx] = instr;
|
||||
|
|
@ -75,7 +82,7 @@ static void __no_inline_not_in_flash_func(send_pre)(const pio_port_t *pp) {
|
|||
pio_sm_set_enabled(pp->pio_usb_rx, pp->sm_eop, true);
|
||||
}
|
||||
|
||||
void __not_in_flash_func(pio_usb_bus_usb_transfer)(const pio_port_t *pp,
|
||||
void __not_in_flash_func(pio_usb_bus_usb_transfer)(pio_port_t *pp,
|
||||
uint8_t *data, uint16_t len) {
|
||||
if (pp->need_pre) {
|
||||
send_pre(pp);
|
||||
|
|
@ -89,14 +96,14 @@ void __not_in_flash_func(pio_usb_bus_usb_transfer)(const pio_port_t *pp,
|
|||
while ((pp->pio_usb_tx->irq & IRQ_TX_ALL_MASK) == 0) {
|
||||
continue;
|
||||
}
|
||||
pio_sm_clear_fifos(pp->pio_usb_tx, pp->sm_tx);
|
||||
pp->pio_usb_tx->irq = IRQ_TX_ALL_MASK; // clear complete flag
|
||||
while (*pc < PIO_USB_TX_ENCODED_DATA_COMP) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
void __no_inline_not_in_flash_func(pio_usb_bus_send_handshake)(
|
||||
const pio_port_t *pp, uint8_t pid) {
|
||||
pio_port_t *pp, uint8_t pid) {
|
||||
switch (pid) {
|
||||
case USB_PID_ACK:
|
||||
pio_usb_bus_usb_transfer(pp, ack_encoded, 5);
|
||||
|
|
@ -113,7 +120,7 @@ void __no_inline_not_in_flash_func(pio_usb_bus_send_handshake)(
|
|||
}
|
||||
}
|
||||
|
||||
void __no_inline_not_in_flash_func(pio_usb_bus_send_token)(const pio_port_t *pp,
|
||||
void __no_inline_not_in_flash_func(pio_usb_bus_send_token)(pio_port_t *pp,
|
||||
uint8_t token,
|
||||
uint8_t addr,
|
||||
uint8_t ep_num) {
|
||||
|
|
@ -139,87 +146,105 @@ void __no_inline_not_in_flash_func(pio_usb_bus_prepare_receive)(const pio_port_t
|
|||
pio_sm_set_enabled(pp->pio_usb_rx, pp->sm_rx, true);
|
||||
}
|
||||
|
||||
void __no_inline_not_in_flash_func(pio_usb_bus_start_receive)(const pio_port_t *pp) {
|
||||
pp->pio_usb_rx->irq = IRQ_RX_ALL_MASK;
|
||||
}
|
||||
static inline __force_inline bool pio_usb_bus_wait_for_rx_start(const pio_port_t* pp) {
|
||||
// USB 2.0 specs: 7.1.19.1: handshake timeout
|
||||
// Full-Speed (12 Mbps): 1 bit time = 1 / 12 MHz = 83.3 ns --> 16 bit times = 1.33 µs
|
||||
// Low-Speed (1.5 Mbps): 1 bit time = 1 / 1.5 MHz = 666.7 ns --> 16 bit times = 10.67 µs
|
||||
|
||||
// We're starting the timing somewhere in the current microsecond so always assume the first one
|
||||
// is less than a full microsecond. For example, a wait of 2 could actually be 1.1 microseconds.
|
||||
// We will use 3 us (24 bit time) for Full speed and 12us (18 bit time) for Low speed.
|
||||
uint32_t start = get_time_us_32();
|
||||
uint32_t timeout = pp->low_speed ? 12 : 3;
|
||||
while (get_time_us_32() - start <= timeout) {
|
||||
if ((pp->pio_usb_rx->irq & IRQ_RX_START_MASK) != 0) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
uint8_t __no_inline_not_in_flash_func(pio_usb_bus_wait_handshake)(pio_port_t* pp) {
|
||||
int16_t t = 240;
|
||||
int16_t idx = 0;
|
||||
if (!pio_usb_bus_wait_for_rx_start(pp)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
while (t--) {
|
||||
int16_t idx = 0;
|
||||
// Timeout in seven microseconds. That is enough time to receive one byte at low speed.
|
||||
// This is to detect packets without an EOP because the device was unplugged.
|
||||
uint32_t start = get_time_us_32();
|
||||
while (get_time_us_32() - start <= 7) {
|
||||
if (pio_sm_get_rx_fifo_level(pp->pio_usb_rx, pp->sm_rx)) {
|
||||
uint8_t data = pio_sm_get(pp->pio_usb_rx, pp->sm_rx) >> 24;
|
||||
pp->usb_rx_buffer[idx++] = data;
|
||||
|
||||
start = get_time_us_32(); // reset timeout when a byte is received
|
||||
if (idx == 2) {
|
||||
break;
|
||||
}
|
||||
} else if ((pp->pio_usb_rx->irq & IRQ_RX_COMP_MASK) != 0) {
|
||||
// Exit early if we've gotten an EOP. There *might* be a race between EOP
|
||||
// detection and NRZI decoding but it is unlikely.
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (t > 0) {
|
||||
while ((pp->pio_usb_rx->irq & IRQ_RX_COMP_MASK) == 0) {
|
||||
continue;
|
||||
}
|
||||
if (idx != 2) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// pio_sm_set_enabled(pp->pio_usb_rx, pp->sm_rx, true);
|
||||
|
||||
return pp->usb_rx_buffer[1];
|
||||
}
|
||||
|
||||
int __no_inline_not_in_flash_func(pio_usb_bus_receive_packet_and_handshake)(
|
||||
pio_port_t *pp, uint8_t handshake) {
|
||||
if (!pio_usb_bus_wait_for_rx_start(pp)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
uint16_t crc = 0xffff;
|
||||
uint16_t crc_prev = 0xffff;
|
||||
uint16_t crc_prev2 = 0xffff;
|
||||
uint16_t crc_receive = 0xffff;
|
||||
uint16_t crc_receive_inverse;
|
||||
uint16_t crc_receive_inverse = 0;
|
||||
bool crc_match = false;
|
||||
int16_t t = 240;
|
||||
uint16_t idx = 0;
|
||||
uint16_t nak_timeout = 10000;
|
||||
const uint16_t rx_buf_len = sizeof(pp->usb_rx_buffer) / sizeof(pp->usb_rx_buffer[0]);
|
||||
int16_t idx = 0;
|
||||
|
||||
while (t--) {
|
||||
// Timeout in seven microseconds. That is enough time to receive one byte at low speed.
|
||||
// This is to detect packets without an EOP because the device was unplugged.
|
||||
uint32_t start = get_time_us_32();
|
||||
while (get_time_us_32() - start <= 7) {
|
||||
if (pio_sm_get_rx_fifo_level(pp->pio_usb_rx, pp->sm_rx)) {
|
||||
uint8_t data = pio_sm_get(pp->pio_usb_rx, pp->sm_rx) >> 24;
|
||||
pp->usb_rx_buffer[idx++] = data;
|
||||
if (idx == 2) {
|
||||
break;
|
||||
if (idx < rx_buf_len) {
|
||||
pp->usb_rx_buffer[idx] = data;
|
||||
}
|
||||
}
|
||||
}
|
||||
start = get_time_us_32(); // reset timeout when a byte is received
|
||||
|
||||
// timing critical start
|
||||
if (t > 0) {
|
||||
if (handshake == USB_PID_ACK) {
|
||||
while ((pp->pio_usb_rx->irq & IRQ_RX_COMP_MASK) == 0 && idx < rx_buf_len - 1) {
|
||||
if (pio_sm_get_rx_fifo_level(pp->pio_usb_rx, pp->sm_rx)) {
|
||||
uint8_t data = pio_sm_get(pp->pio_usb_rx, pp->sm_rx) >> 24;
|
||||
crc_prev2 = crc_prev;
|
||||
crc_prev = crc;
|
||||
crc = update_usb_crc16(crc, data);
|
||||
pp->usb_rx_buffer[idx++] = data;
|
||||
crc_receive = (crc_receive >> 8) | (data << 8);
|
||||
crc_receive_inverse = crc_receive ^ 0xffff;
|
||||
crc_match = (crc_receive_inverse == crc_prev2);
|
||||
if (idx >= 2) {
|
||||
crc_prev2 = crc_prev;
|
||||
crc_prev = crc;
|
||||
crc = update_usb_crc16(crc, data);
|
||||
crc_receive = (crc_receive >> 8) | (data << 8);
|
||||
crc_receive_inverse = crc_receive ^ 0xffff;
|
||||
crc_match = (crc_receive_inverse == crc_prev2);
|
||||
}
|
||||
idx++;
|
||||
} else if ((pp->pio_usb_rx->irq & IRQ_RX_COMP_MASK) != 0) {
|
||||
// Exit early if we've gotten an EOP. There *might* be a race between EOP
|
||||
// detection and NRZI decoding but it is unlikely.
|
||||
if (handshake == USB_PID_ACK) {
|
||||
// Only ACK if crc matches
|
||||
if (idx >= 4 && crc_match) {
|
||||
pio_usb_bus_send_handshake(pp, USB_PID_ACK);
|
||||
return idx - 4;
|
||||
}
|
||||
} else {
|
||||
// always send other handshake NAK/STALL
|
||||
pio_usb_bus_send_handshake(pp, handshake);
|
||||
}
|
||||
|
||||
if (idx >= 4 && crc_match) {
|
||||
pio_usb_bus_send_handshake(pp, USB_PID_ACK);
|
||||
// timing critical end
|
||||
return idx - 4;
|
||||
}
|
||||
} else {
|
||||
// just discard received data since we NAK/STALL anyway
|
||||
while ((pp->pio_usb_rx->irq & IRQ_RX_COMP_MASK) == 0 && nak_timeout--) {
|
||||
continue;
|
||||
}
|
||||
pio_sm_clear_fifos(pp->pio_usb_rx, pp->sm_rx);
|
||||
|
||||
pio_usb_bus_send_handshake(pp, handshake);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -244,8 +269,15 @@ static void __no_inline_not_in_flash_func(initialize_host_programs)(
|
|||
pp->offset_tx = 0;
|
||||
usb_tx_fs_program_init(pp->pio_usb_tx, pp->sm_tx, pp->offset_tx, port->pin_dp,
|
||||
port->pin_dm);
|
||||
pp->tx_start_instr = pio_encode_jmp(pp->offset_tx + 4);
|
||||
pp->tx_reset_instr = pio_encode_jmp(pp->offset_tx + 2);
|
||||
uint32_t sideset_fj_lk;
|
||||
if (c->pinout == PIO_USB_PINOUT_DPDM) {
|
||||
sideset_fj_lk = pio_encode_sideset(2, usb_tx_dpdm_FJ_LK);
|
||||
} else {
|
||||
sideset_fj_lk = pio_encode_sideset(2, usb_tx_dmdp_FJ_LK);
|
||||
}
|
||||
|
||||
pp->tx_start_instr = pio_encode_jmp(pp->offset_tx + 4) | sideset_fj_lk;
|
||||
pp->tx_reset_instr = pio_encode_jmp(pp->offset_tx + 2) | sideset_fj_lk;
|
||||
|
||||
add_pio_host_rx_program(pp->pio_usb_rx, &usb_nrzi_decoder_program,
|
||||
&usb_nrzi_decoder_debug_program, &pp->offset_rx,
|
||||
|
|
@ -422,11 +454,11 @@ uint8_t __no_inline_not_in_flash_func(pio_usb_ll_encode_tx_data)(
|
|||
int current_state = 1;
|
||||
int bit_stuffing = 6;
|
||||
for (int idx = 0; idx < buffer_len; idx++) {
|
||||
uint8_t byte = buffer[idx];
|
||||
uint8_t data_byte = buffer[idx];
|
||||
for (int b = 0; b < 8; b++) {
|
||||
uint8_t byte_idx = bit_idx >> 2;
|
||||
encoded_data[byte_idx] <<= 2;
|
||||
if (byte & (1 << b)) {
|
||||
if (data_byte & (1 << b)) {
|
||||
if (current_state) {
|
||||
encoded_data[byte_idx] |= PIO_USB_TX_ENCODED_DATA_K;
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -200,10 +200,10 @@ static void __no_inline_not_in_flash_func(usb_device_packet_handler)(void) {
|
|||
endpoint_t *ep = PIO_USB_ENDPOINT(ep_num << 1);
|
||||
|
||||
gpio_clr_mask(1<<4);
|
||||
uint8_t hanshake = ep->stalled
|
||||
uint8_t handshake = ep->stalled
|
||||
? USB_PID_STALL
|
||||
: (ep->has_transfer ? USB_PID_ACK : USB_PID_NAK);
|
||||
int res = pio_usb_bus_receive_packet_and_handshake(pp, hanshake);
|
||||
int res = pio_usb_bus_receive_packet_and_handshake(pp, handshake);
|
||||
pio_sm_clear_fifos(pp->pio_usb_rx, pp->sm_rx);
|
||||
restart_usb_receiver(pp);
|
||||
pp->pio_usb_rx->irq = IRQ_RX_ALL_MASK;
|
||||
|
|
|
|||
|
|
@ -18,8 +18,6 @@
|
|||
#include "pio_usb.h"
|
||||
#include "pio_usb_ll.h"
|
||||
#include "usb_crc.h"
|
||||
#include "usb_rx.pio.h"
|
||||
#include "usb_tx.pio.h"
|
||||
|
||||
enum {
|
||||
TRANSACTION_MAX_RETRY = 3, // Number of times to retry a failed transaction
|
||||
|
|
@ -152,6 +150,7 @@ __no_inline_not_in_flash_func(configure_tx_program)(pio_port_t *pp,
|
|||
|
||||
static void __no_inline_not_in_flash_func(configure_fullspeed_host)(
|
||||
pio_port_t *pp, root_port_t *port) {
|
||||
pp->low_speed = false;
|
||||
configure_tx_program(pp, port);
|
||||
pio_sm_clear_fifos(pp->pio_usb_tx, pp->sm_tx);
|
||||
override_pio_program(pp->pio_usb_tx, pp->fs_tx_program, pp->offset_tx);
|
||||
|
|
@ -169,6 +168,7 @@ static void __no_inline_not_in_flash_func(configure_fullspeed_host)(
|
|||
|
||||
static void __no_inline_not_in_flash_func(configure_lowspeed_host)(
|
||||
pio_port_t *pp, root_port_t *port) {
|
||||
pp->low_speed = true;
|
||||
configure_tx_program(pp, port);
|
||||
pio_sm_clear_fifos(pp->pio_usb_tx, pp->sm_tx);
|
||||
override_pio_program(pp->pio_usb_tx, pp->ls_tx_program, pp->offset_tx);
|
||||
|
|
@ -193,8 +193,9 @@ static void __no_inline_not_in_flash_func(configure_root_port)(
|
|||
}
|
||||
}
|
||||
|
||||
static void __no_inline_not_in_flash_func(restore_fs_bus)(const pio_port_t *pp) {
|
||||
static void __no_inline_not_in_flash_func(restore_fs_bus)(pio_port_t *pp) {
|
||||
// change bus speed to full-speed
|
||||
pp->low_speed = false;
|
||||
pio_sm_set_enabled(pp->pio_usb_tx, pp->sm_tx, false);
|
||||
SM_SET_CLKDIV(pp->pio_usb_tx, pp->sm_tx, pp->clk_div_fs_tx);
|
||||
pio_sm_set_enabled(pp->pio_usb_tx, pp->sm_tx, true);
|
||||
|
|
@ -210,8 +211,8 @@ static void __no_inline_not_in_flash_func(restore_fs_bus)(const pio_port_t *pp)
|
|||
|
||||
// Time about 1us ourselves so it lives in RAM.
|
||||
static void __not_in_flash_func(busy_wait_1_us)(void) {
|
||||
uint32_t start = timer_hw->timerawl;
|
||||
while (timer_hw->timerawl == start) {
|
||||
uint32_t start = get_time_us_32();
|
||||
while (get_time_us_32() == start) {
|
||||
tight_loop_contents();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,6 +10,9 @@
|
|||
#include "usb_definitions.h"
|
||||
#include <stdint.h>
|
||||
|
||||
#include "usb_tx.pio.h"
|
||||
#include "usb_rx.pio.h"
|
||||
|
||||
enum {
|
||||
PIO_USB_INTS_CONNECT_POS = 0,
|
||||
PIO_USB_INTS_DISCONNECT_POS,
|
||||
|
|
@ -80,6 +83,7 @@ typedef struct {
|
|||
pio_clk_div_t clk_div_ls_rx;
|
||||
|
||||
bool need_pre;
|
||||
bool low_speed;
|
||||
|
||||
uint8_t usb_rx_buffer[128];
|
||||
} pio_port_t;
|
||||
|
|
@ -112,6 +116,7 @@ extern pio_port_t pio_port[1];
|
|||
#define IRQ_TX_EOP_MASK (1 << IRQ_TX_EOP)
|
||||
#define IRQ_TX_ALL_MASK (IRQ_TX_EOP_MASK)
|
||||
#define IRQ_RX_COMP_MASK (1 << IRQ_RX_EOP)
|
||||
#define IRQ_RX_START_MASK (1 << IRQ_RX_START)
|
||||
#define IRQ_RX_ALL_MASK \
|
||||
((1 << IRQ_RX_EOP) | (1 << IRQ_RX_BS_ERR) | (1 << IRQ_RX_START) | \
|
||||
(1 << DECODER_TRIGGER))
|
||||
|
|
@ -124,15 +129,14 @@ extern pio_port_t pio_port[1];
|
|||
void pio_usb_bus_init(pio_port_t *pp, const pio_usb_configuration_t *c,
|
||||
root_port_t *root);
|
||||
|
||||
void pio_usb_bus_start_receive(const pio_port_t *pp);
|
||||
void pio_usb_bus_prepare_receive(const pio_port_t *pp);
|
||||
int pio_usb_bus_receive_packet_and_handshake(pio_port_t *pp, uint8_t handshake);
|
||||
void pio_usb_bus_usb_transfer(const pio_port_t *pp, uint8_t *data,
|
||||
void pio_usb_bus_usb_transfer(pio_port_t *pp, uint8_t *data,
|
||||
uint16_t len);
|
||||
|
||||
uint8_t pio_usb_bus_wait_handshake(pio_port_t *pp);
|
||||
void pio_usb_bus_send_handshake(const pio_port_t *pp, uint8_t pid);
|
||||
void pio_usb_bus_send_token(const pio_port_t *pp, uint8_t token, uint8_t addr,
|
||||
void pio_usb_bus_send_handshake(pio_port_t *pp, uint8_t pid);
|
||||
void pio_usb_bus_send_token(pio_port_t *pp, uint8_t token, uint8_t addr,
|
||||
uint8_t ep_num);
|
||||
|
||||
static __always_inline port_pin_status_t
|
||||
|
|
@ -143,6 +147,13 @@ pio_usb_bus_get_line_state(root_port_t *root) {
|
|||
return (dm << 1) | dp;
|
||||
}
|
||||
|
||||
static __always_inline void pio_usb_bus_start_receive(const pio_port_t *pp) {
|
||||
pp->pio_usb_rx->irq = IRQ_RX_ALL_MASK;
|
||||
while ((pp->pio_usb_rx->irq & IRQ_RX_ALL_MASK) != 0) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
// Low Level functions
|
||||
//--------------------------------------------------------------------+
|
||||
|
|
|
|||
|
|
@ -12,4 +12,11 @@ extern const uint16_t crc16_tbl[256];
|
|||
static inline uint16_t __time_critical_func(update_usb_crc16)(uint16_t crc, uint8_t data) {
|
||||
crc = (crc >> 8) ^ crc16_tbl[(crc ^ data) & 0xff];
|
||||
return crc;
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef PICO_DEFAULT_TIMER_INSTANCE // not defined in sdk v1
|
||||
#define PICO_DEFAULT_TIMER_INSTANCE() timer_hw
|
||||
#endif
|
||||
|
||||
// time_us_32() not force inline and may be in flash, implement timestamp ourselves
|
||||
#define get_time_us_32() (PICO_DEFAULT_TIMER_INSTANCE()->timerawl)
|
||||
|
|
|
|||
|
|
@ -32,8 +32,8 @@ pin_still_low:
|
|||
; Resync on rising edge
|
||||
pin_low:
|
||||
jmp pin pin_went_high
|
||||
pin_went_low:
|
||||
jmp pin pin_went_high
|
||||
pin_went_low:
|
||||
jmp pin pin_went_high
|
||||
jmp pin pin_went_high
|
||||
jmp pin pin_went_high
|
||||
|
|
@ -41,13 +41,13 @@ pin_went_low:
|
|||
.wrap
|
||||
|
||||
pin_still_high:
|
||||
mov x, isr [2]
|
||||
mov x, isr [1]
|
||||
jmp x-- eop ; Jump to eop if jmp_pin and in_pin are high because both inputs are inverted
|
||||
; Jump to here on rising edge
|
||||
pin_went_high:
|
||||
mov isr, null
|
||||
mov isr, null [1]
|
||||
irq DECODER_TRIGGER ; Trigger NRZI decoder
|
||||
in pins, 1 ; Capture the pin to check eop.
|
||||
irq DECODER_TRIGGER ; Trigger NRZI decoder
|
||||
jmp pin pin_still_high
|
||||
jmp pin_went_low ; To adjust interval of decoder trigger, jump to pin_went_low (not pin_low)
|
||||
|
||||
|
|
@ -66,8 +66,8 @@ pin_still_low:
|
|||
; Resync on rising edge
|
||||
pin_low:
|
||||
jmp pin pin_went_high side db1
|
||||
pin_went_low:
|
||||
jmp pin pin_went_high side db1
|
||||
pin_went_low:
|
||||
jmp pin pin_went_high side db1
|
||||
jmp pin pin_went_high side db1
|
||||
jmp pin pin_went_high side db1
|
||||
|
|
@ -75,13 +75,13 @@ pin_went_low:
|
|||
.wrap
|
||||
|
||||
pin_still_high:
|
||||
mov x, isr [2] side db1
|
||||
mov x, isr [1] side db1
|
||||
jmp x-- eop side db1 ; Jump to eop if jmp_pin and in_pin are high because both inputs are inverted
|
||||
; Jump to here on rising edge
|
||||
pin_went_high:
|
||||
mov isr, null side db1
|
||||
mov isr, null [1] side db1
|
||||
irq DECODER_TRIGGER side db0 ; Trigger NRZI decoder
|
||||
in pins, 1 side db0 ; Capture the pin to check eop.
|
||||
irq DECODER_TRIGGER side db0 ; Trigger NRZI decoder
|
||||
jmp pin pin_still_high side db0
|
||||
jmp pin_went_low side db1 ; To adjust interval of decoder trigger, jump to pin_went_low (not pin_low)
|
||||
|
||||
|
|
|
|||
|
|
@ -33,13 +33,13 @@ static const uint16_t usb_edge_detector_program_instructions[] = {
|
|||
0x00cc, // 8: jmp pin, 12
|
||||
0x00cc, // 9: jmp pin, 12
|
||||
// .wrap
|
||||
0xa226, // 10: mov x, isr [2]
|
||||
0xa126, // 10: mov x, isr [1]
|
||||
0x0040, // 11: jmp x--, 0
|
||||
0xa0c3, // 12: mov isr, null
|
||||
0x4001, // 13: in pins, 1
|
||||
0xc004, // 14: irq nowait 4
|
||||
0xa1c3, // 12: mov isr, null [1]
|
||||
0xc004, // 13: irq nowait 4
|
||||
0x4001, // 14: in pins, 1
|
||||
0x00ca, // 15: jmp pin, 10
|
||||
0x0005, // 16: jmp 5
|
||||
0x0006, // 16: jmp 6
|
||||
};
|
||||
|
||||
#if !PICO_NO_HARDWARE
|
||||
|
|
@ -76,13 +76,13 @@ static const uint16_t usb_edge_detector_debug_program_instructions[] = {
|
|||
0x10cc, // 8: jmp pin, 12 side 1
|
||||
0x10cc, // 9: jmp pin, 12 side 1
|
||||
// .wrap
|
||||
0xb226, // 10: mov x, isr side 1 [2]
|
||||
0xb126, // 10: mov x, isr side 1 [1]
|
||||
0x1040, // 11: jmp x--, 0 side 1
|
||||
0xb0c3, // 12: mov isr, null side 1
|
||||
0x4001, // 13: in pins, 1 side 0
|
||||
0xc004, // 14: irq nowait 4 side 0
|
||||
0xb1c3, // 12: mov isr, null side 1 [1]
|
||||
0xc004, // 13: irq nowait 4 side 0
|
||||
0x4001, // 14: in pins, 1 side 0
|
||||
0x00ca, // 15: jmp pin, 10 side 0
|
||||
0x1005, // 16: jmp 5 side 1
|
||||
0x1006, // 16: jmp 6 side 1
|
||||
};
|
||||
|
||||
#if !PICO_NO_HARDWARE
|
||||
|
|
@ -196,7 +196,7 @@ static inline void usb_rx_fs_program_init(PIO pio, uint sm, uint offset, uint pi
|
|||
}
|
||||
sm_config_set_in_pins(&c, pin_dp); // for WAIT, IN
|
||||
sm_config_set_jmp_pin(&c, pin_dp); // for JMP
|
||||
// Shift to right, autopull enabled, 8bit
|
||||
// Shift to right, autopush enabled, 8bit
|
||||
sm_config_set_in_shift(&c, true, true, 8);
|
||||
sm_config_set_fifo_join(&c, PIO_FIFO_JOIN_RX);
|
||||
pio_sm_init(pio, sm, offset, &c);
|
||||
|
|
|
|||
|
|
@ -3,15 +3,15 @@
|
|||
.define public IRQ_TX_EOP 0 ; EOP start flag bit
|
||||
|
||||
; USB NRZI transmitter
|
||||
; Run at 48 MHz for full-spped (x4)
|
||||
; Run at 6 MHz for low-spped (x4)
|
||||
; Run at 48 MHz for full-speed (x4)
|
||||
; Run at 6 MHz for low-speed (x4)
|
||||
; autopull enabled
|
||||
; Should be placed at address 0
|
||||
.program usb_tx_dpdm
|
||||
.side_set 2
|
||||
|
||||
; J for fs, K for ls
|
||||
.define FJ_LK 0b01
|
||||
.define public FJ_LK 0b01
|
||||
; K for fs, J for ls
|
||||
.define FK_LJ 0b10
|
||||
.define SE0 0b00
|
||||
|
|
@ -49,14 +49,14 @@ set pindirs, 0b11 side FJ_LK
|
|||
.wrap
|
||||
|
||||
; USB NRZI transmitter
|
||||
; Run at 48 MHz for full-spped
|
||||
; Run at 6 MHz for low-spped
|
||||
; Run at 48 MHz for full-speed
|
||||
; Run at 6 MHz for low-speed
|
||||
; autopull enabled
|
||||
.program usb_tx_dmdp
|
||||
.side_set 2
|
||||
|
||||
.define FK_LJ 0b01
|
||||
.define FJ_LK 0b10
|
||||
.define public FJ_LK 0b10
|
||||
.define SE0 0b00
|
||||
|
||||
irq IRQ_TX_EOP side SE0 [7]
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@
|
|||
|
||||
#define usb_tx_dpdm_wrap_target 1
|
||||
#define usb_tx_dpdm_wrap 4
|
||||
#define usb_tx_dpdm_FJ_LK 1
|
||||
|
||||
static const uint16_t __not_in_flash("tx_program") usb_tx_dpdm_program_instructions[] = {
|
||||
0xc700, // 0: irq nowait 0 side 0 [7]
|
||||
|
|
@ -80,6 +81,7 @@ static inline pio_sm_config usb_tx_pre_dpdm_program_get_default_config(uint offs
|
|||
|
||||
#define usb_tx_dmdp_wrap_target 1
|
||||
#define usb_tx_dmdp_wrap 4
|
||||
#define usb_tx_dmdp_FJ_LK 2
|
||||
|
||||
static const uint16_t __not_in_flash("tx_program") usb_tx_dmdp_program_instructions[] = {
|
||||
0xc700, // 0: irq nowait 0 side 0 [7]
|
||||
|
|
|
|||
Loading…
Reference in a new issue