// -------------------------------------------------- //
// This file is autogenerated by pioasm; do not edit! //
// -------------------------------------------------- //

#pragma once

#if !PICO_NO_HARDWARE
#include "hardware/pio.h"
#endif

#define IRQ_RX_BS_ERR 1
#define IRQ_RX_EOP 2
#define IRQ_RX_START 3
#define DECODER_TRIGGER 4

// ----------------- //
// usb_edge_detector //
// ----------------- //

#define usb_edge_detector_wrap_target 3
#define usb_edge_detector_wrap 9

static const uint16_t usb_edge_detector_program_instructions[] = {
    0xc022, //  0: irq    wait 2                     
    0x00c1, //  1: jmp    pin, 1                     
    0xc103, //  2: irq    nowait 3               [1] 
            //     .wrap_target
    0xc104, //  3: irq    nowait 4               [1] 
    0x00cc, //  4: jmp    pin, 12                    
    0x00cc, //  5: jmp    pin, 12                    
    0x00cc, //  6: jmp    pin, 12                    
    0x00cc, //  7: jmp    pin, 12                    
    0x00cc, //  8: jmp    pin, 12                    
    0x00cc, //  9: jmp    pin, 12                    
            //     .wrap
    0xa226, // 10: mov    x, isr                 [2] 
    0x0040, // 11: jmp    x--, 0                     
    0xa0c3, // 12: mov    isr, null                  
    0x4001, // 13: in     pins, 1                    
    0xc004, // 14: irq    nowait 4                   
    0x00ca, // 15: jmp    pin, 10                    
    0x0005, // 16: jmp    5                          
};

#if !PICO_NO_HARDWARE
static const struct pio_program usb_edge_detector_program = {
    .instructions = usb_edge_detector_program_instructions,
    .length = 17,
    .origin = -1,
};

static inline pio_sm_config usb_edge_detector_program_get_default_config(uint offset) {
    pio_sm_config c = pio_get_default_sm_config();
    sm_config_set_wrap(&c, offset + usb_edge_detector_wrap_target, offset + usb_edge_detector_wrap);
    return c;
}
#endif

// ----------------------- //
// usb_edge_detector_debug //
// ----------------------- //

#define usb_edge_detector_debug_wrap_target 3
#define usb_edge_detector_debug_wrap 9

static const uint16_t usb_edge_detector_debug_program_instructions[] = {
    0xc022, //  0: irq    wait 2          side 0     
    0x10c1, //  1: jmp    pin, 1          side 1     
    0xc103, //  2: irq    nowait 3        side 0 [1] 
            //     .wrap_target
    0xc104, //  3: irq    nowait 4        side 0 [1] 
    0x10cc, //  4: jmp    pin, 12         side 1     
    0x10cc, //  5: jmp    pin, 12         side 1     
    0x10cc, //  6: jmp    pin, 12         side 1     
    0x10cc, //  7: jmp    pin, 12         side 1     
    0x10cc, //  8: jmp    pin, 12         side 1     
    0x10cc, //  9: jmp    pin, 12         side 1     
            //     .wrap
    0xb226, // 10: mov    x, isr          side 1 [2] 
    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     
    0x00ca, // 15: jmp    pin, 10         side 0     
    0x1005, // 16: jmp    5               side 1     
};

#if !PICO_NO_HARDWARE
static const struct pio_program usb_edge_detector_debug_program = {
    .instructions = usb_edge_detector_debug_program_instructions,
    .length = 17,
    .origin = -1,
};

static inline pio_sm_config usb_edge_detector_debug_program_get_default_config(uint offset) {
    pio_sm_config c = pio_get_default_sm_config();
    sm_config_set_wrap(&c, offset + usb_edge_detector_debug_wrap_target, offset + usb_edge_detector_debug_wrap);
    sm_config_set_sideset(&c, 1, false, false);
    return c;
}
#endif

// ---------------- //
// usb_nrzi_decoder //
// ---------------- //

#define usb_nrzi_decoder_wrap_target 0
#define usb_nrzi_decoder_wrap 14

static const uint16_t usb_nrzi_decoder_program_instructions[] = {
            //     .wrap_target
    0xe046, //  0: set    y, 6                       
    0x20c4, //  1: wait   1 irq, 4                   
    0x00c9, //  2: jmp    pin, 9                     
    0x006e, //  3: jmp    !y, 14                     
    0x0027, //  4: jmp    !x, 7                      
    0x4061, //  5: in     null, 1                    
    0x000e, //  6: jmp    14                         
    0x40e1, //  7: in     osr, 1                     
    0x0081, //  8: jmp    y--, 1                     
    0x006e, //  9: jmp    !y, 14                     
    0x002d, // 10: jmp    !x, 13                     
    0x4021, // 11: in     x, 1                       
    0x0081, // 12: jmp    y--, 1                     
    0x4061, // 13: in     null, 1                    
    0xa029, // 14: mov    x, !x                      
            //     .wrap
};

#if !PICO_NO_HARDWARE
static const struct pio_program usb_nrzi_decoder_program = {
    .instructions = usb_nrzi_decoder_program_instructions,
    .length = 15,
    .origin = -1,
};

static inline pio_sm_config usb_nrzi_decoder_program_get_default_config(uint offset) {
    pio_sm_config c = pio_get_default_sm_config();
    sm_config_set_wrap(&c, offset + usb_nrzi_decoder_wrap_target, offset + usb_nrzi_decoder_wrap);
    return c;
}
#endif

// ---------------------- //
// usb_nrzi_decoder_debug //
// ---------------------- //

#define usb_nrzi_decoder_debug_wrap_target 0
#define usb_nrzi_decoder_debug_wrap 14

static const uint16_t usb_nrzi_decoder_debug_program_instructions[] = {
            //     .wrap_target
    0xe046, //  0: set    y, 6                       
    0x20c4, //  1: wait   1 irq, 4                   
    0x00c9, //  2: jmp    pin, 9                     
    0x106e, //  3: jmp    !y, 14          side 0     
    0x1027, //  4: jmp    !x, 7           side 0     
    0x4061, //  5: in     null, 1                    
    0x000e, //  6: jmp    14                         
    0x40e1, //  7: in     osr, 1                     
    0x0081, //  8: jmp    y--, 1                     
    0x186e, //  9: jmp    !y, 14          side 1     
    0x182d, // 10: jmp    !x, 13          side 1     
    0x4021, // 11: in     x, 1                       
    0x0081, // 12: jmp    y--, 1                     
    0x4061, // 13: in     null, 1                    
    0xa029, // 14: mov    x, !x                      
            //     .wrap
};

#if !PICO_NO_HARDWARE
static const struct pio_program usb_nrzi_decoder_debug_program = {
    .instructions = usb_nrzi_decoder_debug_program_instructions,
    .length = 15,
    .origin = -1,
};

static inline pio_sm_config usb_nrzi_decoder_debug_program_get_default_config(uint offset) {
    pio_sm_config c = pio_get_default_sm_config();
    sm_config_set_wrap(&c, offset + usb_nrzi_decoder_debug_wrap_target, offset + usb_nrzi_decoder_debug_wrap);
    sm_config_set_sideset(&c, 2, true, false);
    return c;
}

#include "hardware/clocks.h"
static __always_inline void pio_sm_set_jmp_pin(PIO pio, uint sm, uint jmp_pin) {
  pio->sm[sm].execctrl =
      (pio->sm[sm].execctrl & ~PIO_SM0_EXECCTRL_JMP_PIN_BITS) |
      (jmp_pin << PIO_SM0_EXECCTRL_JMP_PIN_LSB);
}
static inline void usb_rx_fs_program_init(PIO pio, uint sm, uint offset, uint pin_dp, uint pin_dm, int pin_debug) {
  if (pin_dp < pin_dm) {
    pio_sm_set_consecutive_pindirs(pio, sm, pin_dp, 2, false);
  } else {
    pio_sm_set_consecutive_pindirs(pio, sm, pin_dm, 2, false);
  }
  gpio_pull_down(pin_dp);
  gpio_pull_down(pin_dm);
  gpio_set_inover(pin_dp, GPIO_OVERRIDE_INVERT);
  gpio_set_inover(pin_dm, GPIO_OVERRIDE_INVERT);
  pio_sm_config c;
  if (pin_debug < 0) {
    c = usb_nrzi_decoder_program_get_default_config(offset);
  } else {
    c = usb_nrzi_decoder_debug_program_get_default_config(offset);
    pio_sm_set_pins_with_mask(pio, sm, 0, 1 << pin_debug);
    pio_sm_set_pindirs_with_mask(pio, sm, 1 << pin_debug, 1 << pin_debug);
    pio_gpio_init(pio, pin_debug);
    sm_config_set_sideset_pins(&c, pin_debug);
  }
  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
  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);
  pio_sm_exec(pio, sm, pio_encode_mov_not(pio_osr, pio_null));
  pio_sm_set_enabled(pio, sm, false);
}
static inline void eop_detect_fs_program_init(PIO pio, uint sm, uint offset,
                                           uint pin_dp, uint pin_dm, bool is_fs, int pin_debug) {
  pio_sm_config c;
  if (pin_debug < 0) {
    c = usb_edge_detector_program_get_default_config(offset);
  } else {
    c = usb_edge_detector_debug_program_get_default_config(offset);
    pio_sm_set_pins_with_mask(pio, sm, 0, 1 << pin_debug);
    pio_sm_set_pindirs_with_mask(pio, sm, 1 << pin_debug, 1 << pin_debug);
    pio_gpio_init(pio, pin_debug);
    sm_config_set_sideset_pins(&c, pin_debug);
  }
  sm_config_set_in_pins(&c, pin_dp);  // for WAIT, IN
  sm_config_set_jmp_pin(&c, pin_dm);  // for JMP
  sm_config_set_in_shift(&c, false, false, 8);
  float div;
  if (is_fs) {
    div = (float)clock_get_hz(clk_sys) / (96000000);
  } else {
    div = (float)clock_get_hz(clk_sys) / (12000000);
  }
  sm_config_set_clkdiv(&c, div);
  pio_sm_init(pio, sm, offset + 1, &c);
  pio_sm_set_enabled(pio, sm, true);
}

#endif

