diff --git a/src/pio_usb.c b/src/pio_usb.c index 5e52f55..7554c0d 100644 --- a/src/pio_usb.c +++ b/src/pio_usb.c @@ -40,7 +40,7 @@ static void __no_inline_not_in_flash_func(send_pre)(const pio_port_t *pp) { // send PRE token in full-speed pio_sm_set_enabled(pp->pio_usb_tx, pp->sm_tx, false); for (uint i = 0; i < USB_TX_EOP_DISABLER_LEN; ++i) { - uint16_t instr = usb_tx_fs_pre_program.instructions[i + USB_TX_EOP_OFFSET]; + uint16_t instr = pp->fs_tx_pre_program->instructions[i + USB_TX_EOP_OFFSET]; pp->pio_usb_tx->instr_mem[pp->offset_tx + i + USB_TX_EOP_OFFSET] = instr; } @@ -59,7 +59,7 @@ static void __no_inline_not_in_flash_func(send_pre)(const pio_port_t *pp) { // change bus speed to low-speed pio_sm_set_enabled(pp->pio_usb_tx, pp->sm_tx, false); for (uint i = 0; i < USB_TX_EOP_DISABLER_LEN; ++i) { - uint16_t instr = usb_tx_fs_program.instructions[i + USB_TX_EOP_OFFSET]; + uint16_t instr = pp->fs_tx_program->instructions[i + USB_TX_EOP_OFFSET]; pp->pio_usb_tx->instr_mem[pp->offset_tx + i + USB_TX_EOP_OFFSET] = instr; } SM_SET_CLKDIV(pp->pio_usb_tx, pp->sm_tx, pp->clk_div_ls_tx); @@ -215,9 +215,9 @@ static __always_inline void add_pio_host_rx_program(PIO pio, static void __no_inline_not_in_flash_func(initialize_host_programs)( pio_port_t *pp, const pio_usb_configuration_t *c, root_port_t *port) { - pp->offset_tx = pio_add_program(pp->pio_usb_tx, &usb_tx_fs_program); + pp->offset_tx = pio_add_program(pp->pio_usb_tx, pp->fs_tx_program); usb_tx_fs_program_init(pp->pio_usb_tx, pp->sm_tx, pp->offset_tx, - port->pin_dp); + port->pin_dp, port->pin_dm); add_pio_host_rx_program(pp->pio_usb_rx, &usb_nrzi_decoder_program, &usb_nrzi_decoder_debug_program, &pp->offset_rx, @@ -234,7 +234,7 @@ static void __no_inline_not_in_flash_func(initialize_host_programs)( port->pin_dp, port->pin_dm, true, c->debug_pin_eop); - usb_tx_configure_pins(pp->pio_usb_tx, pp->sm_tx, port->pin_dp); + usb_tx_configure_pins(pp->pio_usb_tx, pp->sm_tx, port->pin_dp, port->pin_dm); pio_sm_set_jmp_pin(pp->pio_usb_rx, pp->sm_rx, port->pin_dp); pio_sm_set_jmp_pin(pp->pio_usb_rx, pp->sm_eop, port->pin_dm); @@ -262,7 +262,18 @@ static void apply_config(pio_port_t *pp, const pio_usb_configuration_t *c, pp->sm_rx = c->sm_rx; pp->sm_eop = c->sm_eop; port->pin_dp = c->pin_dp; - port->pin_dm = c->pin_dp + 1; + + if (c->pinout == PIO_USB_PINOUT_DPDM) { + port->pin_dm = c->pin_dp + 1; + pp->fs_tx_program = &usb_tx_dpdm_program; + pp->fs_tx_pre_program = &usb_tx_pre_dpdm_program; + pp->ls_tx_program = &usb_tx_dmdp_program; + } else { + port->pin_dm = c->pin_dp - 1; + pp->fs_tx_program = &usb_tx_dmdp_program; + pp->fs_tx_pre_program = &usb_tx_pre_dmdp_program; + pp->ls_tx_program = &usb_tx_dpdm_program; + } pp->debug_pin_rx = c->debug_pin_rx; pp->debug_pin_eop = c->debug_pin_eop; @@ -431,24 +442,26 @@ void __no_inline_not_in_flash_func(pio_usb_ll_transfer_complete)( ep->has_transfer = false; } -int pio_usb_host_add_port(uint8_t pin_dp) { +int pio_usb_host_add_port(uint8_t pin_dp, PIO_USB_PINOUT pinout) { for (int idx = 0; idx < PIO_USB_ROOT_PORT_CNT; idx++) { root_port_t *root = PIO_USB_ROOT_PORT(idx); if (!root->initialized) { root->pin_dp = pin_dp; - root->pin_dm = pin_dp + 1; - PIO_USB_ROOT_PORT(idx)->pin_dp = pin_dp; - PIO_USB_ROOT_PORT(idx)->pin_dm = pin_dp + 1; + if (pinout == PIO_USB_PINOUT_DPDM) { + root->pin_dm = pin_dp + 1; + } else { + root->pin_dm = pin_dp - 1; + } gpio_pull_down(pin_dp); - gpio_pull_down(pin_dp + 1); + gpio_pull_down(root->pin_dm); pio_gpio_init(pio_port[0].pio_usb_tx, pin_dp); - pio_gpio_init(pio_port[0].pio_usb_tx, pin_dp + 1); + pio_gpio_init(pio_port[0].pio_usb_tx, root->pin_dm); gpio_set_inover(pin_dp, GPIO_OVERRIDE_INVERT); - gpio_set_inover(pin_dp + 1, GPIO_OVERRIDE_INVERT); + gpio_set_inover(root->pin_dm, GPIO_OVERRIDE_INVERT); pio_sm_set_pindirs_with_mask(pio_port[0].pio_usb_tx, pio_port[0].sm_tx, 0, - (0b11 << pin_dp)); + (1 << pin_dp) | (1 << root->pin_dm)); port_pin_drive_setting(root); root->initialized = true; diff --git a/src/pio_usb.h b/src/pio_usb.h index b78c20a..30a87d3 100644 --- a/src/pio_usb.h +++ b/src/pio_usb.h @@ -10,7 +10,7 @@ // Host functions usb_device_t *pio_usb_host_init(const pio_usb_configuration_t *c); -int pio_usb_host_add_port(uint8_t pin_dp); +int pio_usb_host_add_port(uint8_t pin_dp, PIO_USB_PINOUT pinout); void pio_usb_host_task(void); void pio_usb_host_stop(void); void pio_usb_host_restart(void); diff --git a/src/pio_usb_configuration.h b/src/pio_usb_configuration.h index 500de6e..f8b8b6e 100644 --- a/src/pio_usb_configuration.h +++ b/src/pio_usb_configuration.h @@ -1,6 +1,11 @@ #pragma once +typedef enum { + PIO_USB_PINOUT_DPDM = 0, // DM = DP+1 + PIO_USB_PINOUT_DMDP, // DM = DP-1 +} PIO_USB_PINOUT; + typedef struct { uint8_t pin_dp; uint8_t pio_tx_num; @@ -13,6 +18,7 @@ typedef struct { int8_t debug_pin_rx; int8_t debug_pin_eop; bool skip_alarm_pool; + PIO_USB_PINOUT pinout; } pio_usb_configuration_t; #ifndef PIO_USB_DP_PIN_DEFAULT diff --git a/src/pio_usb_host.c b/src/pio_usb_host.c index 074a68e..1bca094 100644 --- a/src/pio_usb_host.c +++ b/src/pio_usb_host.c @@ -126,7 +126,7 @@ static __always_inline void override_pio_rx_program(PIO pio, static void __no_inline_not_in_flash_func(configure_fullspeed_host)( pio_port_t const *pp, root_port_t *port) { - override_pio_program(pp->pio_usb_tx, &usb_tx_fs_program, pp->offset_tx); + override_pio_program(pp->pio_usb_tx, pp->fs_tx_program, pp->offset_tx); SM_SET_CLKDIV(pp->pio_usb_tx, pp->sm_tx, pp->clk_div_fs_tx); pio_sm_set_jmp_pin(pp->pio_usb_rx, pp->sm_rx, port->pin_dp); @@ -136,12 +136,12 @@ static void __no_inline_not_in_flash_func(configure_fullspeed_host)( pio_sm_set_in_pins(pp->pio_usb_rx, pp->sm_eop, port->pin_dp); SM_SET_CLKDIV(pp->pio_usb_rx, pp->sm_eop, pp->clk_div_fs_rx); - usb_tx_configure_pins(pp->pio_usb_tx, pp->sm_tx, port->pin_dp); + usb_tx_configure_pins(pp->pio_usb_tx, pp->sm_tx, port->pin_dp, port->pin_dm); } static void __no_inline_not_in_flash_func(configure_lowspeed_host)( pio_port_t const *pp, root_port_t *port) { - override_pio_program(pp->pio_usb_tx, &usb_tx_ls_program, pp->offset_tx); + override_pio_program(pp->pio_usb_tx, pp->ls_tx_program, pp->offset_tx); SM_SET_CLKDIV(pp->pio_usb_tx, pp->sm_tx, pp->clk_div_ls_tx); pio_sm_set_jmp_pin(pp->pio_usb_rx, pp->sm_rx, port->pin_dm); @@ -151,7 +151,7 @@ static void __no_inline_not_in_flash_func(configure_lowspeed_host)( pio_sm_set_in_pins(pp->pio_usb_rx, pp->sm_eop, port->pin_dm); SM_SET_CLKDIV(pp->pio_usb_rx, pp->sm_eop, pp->clk_div_ls_rx); - usb_tx_configure_pins(pp->pio_usb_tx, pp->sm_tx, port->pin_dp); + usb_tx_configure_pins(pp->pio_usb_tx, pp->sm_tx, port->pin_dp, port->pin_dm); } static void __no_inline_not_in_flash_func(configure_root_port)( diff --git a/src/pio_usb_ll.h b/src/pio_usb_ll.h index b6a56ad..4414b2c 100644 --- a/src/pio_usb_ll.h +++ b/src/pio_usb_ll.h @@ -64,6 +64,10 @@ typedef struct { int8_t debug_pin_rx; int8_t debug_pin_eop; + const pio_program_t *fs_tx_program; + const pio_program_t *fs_tx_pre_program; + const pio_program_t *ls_tx_program; + pio_clk_div_t clk_div_fs_tx; pio_clk_div_t clk_div_fs_rx; pio_clk_div_t clk_div_ls_tx; @@ -99,8 +103,8 @@ extern pio_port_t pio_port[1]; // Bus functions //--------------------------------------------------------------------+ -#define IRQ_TX_EOP_MASK (1 << usb_tx_fs_IRQ_EOP) -#define IRQ_TX_COMP_MASK (1 << usb_tx_fs_IRQ_COMP) +#define IRQ_TX_EOP_MASK (1 << usb_tx_dpdm_IRQ_EOP) +#define IRQ_TX_COMP_MASK (1 << usb_tx_dpdm_IRQ_COMP) #define IRQ_TX_ALL_MASK (IRQ_TX_EOP_MASK | IRQ_TX_COMP_MASK) #define IRQ_RX_COMP_MASK (1 << IRQ_RX_EOP) #define IRQ_RX_ALL_MASK \ diff --git a/src/usb_tx.pio b/src/usb_tx.pio index 90672c3..cddce13 100644 --- a/src/usb_tx.pio +++ b/src/usb_tx.pio @@ -1,22 +1,26 @@ -; Copyright (c) 2021 sekigon-gonnoc +; Copyright (c) 2021-2023 sekigon-gonnoc .define public USB_TX_EOP_OFFSET 4 .define public USB_TX_EOP_DISABLER_LEN 4 -; USB FS NRZI transmitter -; Run 48 MHz, autopull -.program usb_tx_fs +; USB NRZI transmitter +; Run at 48 MHz for full-spped +; Run at 6 MHz for low-spped +; autopull enabled +.program usb_tx_dpdm .side_set 2 opt -.define J 0b01 -.define K 0b10 +; J for fs, K for ls +.define FJ_LK 0b01 +; K for fs, J for ls +.define FK_LJ 0b10 .define SE0 0b00 .define BR 5 ; bit repeat limit .define public IRQ_COMP 0 ; complete flag bit .define public IRQ_EOP 1 ; EOP start flag bit start: - set y, BR side J + set y, BR side FJ_LK set pindirs, 0b11 .wrap_target @@ -26,7 +30,7 @@ check_eop1: send_eop: irq IRQ_EOP side SE0 [3] ; To catch quik ACK, mark as complete here nop [3] - nop side J + nop side FJ_LK set pindirs, 0b00 [3] irq wait IRQ_COMP jmp start @@ -34,10 +38,10 @@ load_bit1: out x, 1 jmp !x low1 high1: - jmp y-- check_eop1 side J + jmp y-- check_eop1 side FJ_LK nop [2] ; bit stuffing low1: - set y BR side K + set y BR side FK_LJ check_eop2: jmp !osre load_bit2 @@ -46,15 +50,16 @@ load_bit2: out x, 1 jmp !x low2 high2: - jmp y-- check_eop2 side K + jmp y-- check_eop2 side FK_LJ nop [2] ; bit stuffing low2: - set y BR side J + set y BR side FJ_LK .wrap -; USB FS transmitter for PRE packet (No EOP) -; Run 48 MHz, autopull -.program usb_tx_fs_pre +; USB transmitter for PRE packet (No EOP) +; Run at 48 MHz for full-spped +; autopull enabled +.program usb_tx_pre_dpdm .side_set 2 opt .define J 0b01 @@ -102,9 +107,61 @@ low2: .wrap -; USB LS Transmitter -; Run 6MHz, autopull -.program usb_tx_ls +; USB NRZI transmitter +; Run at 48 MHz for full-spped +; Run at 6 MHz for low-spped +; autopull enabled +.program usb_tx_dmdp +.side_set 2 opt + +.define FK_LJ 0b10 +.define FJ_LK 0b01 +.define SE0 0b00 +.define BR 5 ; bit repeat limit +.define public IRQ_COMP 0 ; complete flag bit +.define public IRQ_EOP 1 ; EOP start flag bit + +start: + set y, BR side FK_LJ + set pindirs, 0b11 + +.wrap_target +check_eop1: + jmp !osre load_bit1 + nop [1] +send_eop: + irq IRQ_EOP side SE0 [3] + nop [3] + nop side FK_LJ + set pindirs, 0b00 [3] + irq wait IRQ_COMP + jmp start +load_bit1: + out x, 1 + jmp !x low1 +high1: + jmp y-- check_eop1 side FK_LJ + nop [2] ; bit stuffing +low1: + set y BR side FJ_LK + +check_eop2: + jmp !osre load_bit2 + jmp send_eop [1] +load_bit2: + out x, 1 + jmp !x low2 +high2: + jmp y-- check_eop2 side FJ_LK + nop [2] ; bit stuffing +low2: + set y BR side FK_LJ +.wrap + +; USB transmitter for PRE packet (No EOP) +; Run at 48 MHz for full-spped +; autopull enabled +.program usb_tx_pre_dmdp .side_set 2 opt .define J 0b10 @@ -123,10 +180,10 @@ check_eop1: jmp !osre load_bit1 nop [1] send_eop: - irq IRQ_EOP side SE0 [3] - nop [3] - nop side J - set pindirs, 0b00 [3] + irq IRQ_EOP side J [3] + set pindirs, 0b00 + nop ; to align program size + nop ; to align program size irq wait IRQ_COMP jmp start load_bit1: @@ -152,26 +209,31 @@ low2: .wrap - % c-sdk { #include "hardware/clocks.h" - static void __no_inline_not_in_flash_func(usb_tx_configure_pins)(PIO pio, uint sm, uint pin_dp) { - pio_sm_set_out_pins(pio, sm, pin_dp, 2); - pio_sm_set_set_pins(pio, sm, pin_dp, 2); - pio_sm_set_sideset_pins(pio, sm, pin_dp); + static void __no_inline_not_in_flash_func(usb_tx_configure_pins)(PIO pio, uint sm, uint pin_dp, uint pin_dm) { + if (pin_dp < pin_dm) { + pio_sm_set_out_pins(pio, sm, pin_dp, 2); + pio_sm_set_set_pins(pio, sm, pin_dp, 2); + pio_sm_set_sideset_pins(pio, sm, pin_dp); + } else { + pio_sm_set_out_pins(pio, sm, pin_dm, 2); + pio_sm_set_set_pins(pio, sm, pin_dm, 2); + pio_sm_set_sideset_pins(pio, sm, pin_dm); + } } static inline void usb_tx_fs_program_init(PIO pio, uint sm, uint offset, - uint pin_dp) { - pio_sm_set_pins_with_mask(pio, sm, (0b01 << pin_dp), (0b11 << pin_dp)); + uint pin_dp, uint pin_dm) { + pio_sm_set_pins_with_mask(pio, sm, (1 << pin_dp), ((1 << pin_dp) | (1 << pin_dm))); gpio_pull_down(pin_dp); - gpio_pull_down(pin_dp + 1); // dm + gpio_pull_down(pin_dm); pio_gpio_init(pio, pin_dp); - pio_gpio_init(pio, pin_dp + 1); // dm + pio_gpio_init(pio, pin_dm); - pio_sm_config c = usb_tx_fs_program_get_default_config(offset); + pio_sm_config c = usb_tx_dpdm_program_get_default_config(offset); // shifts to left, autopull, 8bit sm_config_set_out_shift(&c, true, true, 8); @@ -184,20 +246,20 @@ low2: sm_config_set_clkdiv(&c, div); pio_sm_init(pio, sm, offset, &c); - usb_tx_configure_pins(pio, sm, pin_dp); + usb_tx_configure_pins(pio, sm, pin_dp, pin_dm); pio_sm_set_enabled(pio, sm, true); } static inline void usb_tx_ls_program_init(PIO pio, uint sm, uint offset, - uint pin_dp) { - pio_sm_set_pins_with_mask(pio, sm, (0b10 << pin_dp), (0b11 << pin_dp)); + uint pin_dp, uint pin_dm) { + pio_sm_set_pins_with_mask(pio, sm, (1 << pin_dm), ((1 << pin_dp) | (1 << pin_dm))); gpio_pull_down(pin_dp); - gpio_pull_down(pin_dp + 1); // dm + gpio_pull_down(pin_dm); pio_gpio_init(pio, pin_dp); - pio_gpio_init(pio, pin_dp + 1); // dm + pio_gpio_init(pio, pin_dm); - pio_sm_config c = usb_tx_ls_program_get_default_config(offset); + pio_sm_config c = usb_tx_dmdp_program_get_default_config(offset); // shifts to left, autopull, 8bit sm_config_set_out_shift(&c, true, true, 8); @@ -210,8 +272,8 @@ low2: sm_config_set_clkdiv(&c, div); pio_sm_init(pio, sm, offset, &c); - usb_tx_configure_pins(pio, sm, pin_dp); + usb_tx_configure_pins(pio, sm, pin_dp, pin_dm); pio_sm_set_enabled(pio, sm, true); } -%} +%} \ No newline at end of file