diff --git a/.gitignore b/.gitignore index 08538d7..f33c2ad 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,5 @@ .vscode build makefsdata -unused \ No newline at end of file +unused +gen_build.bat \ No newline at end of file diff --git a/.gitmodules b/.gitmodules index c3e4b4f..e69de29 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,10 +0,0 @@ -[submodule "tinyusb"] - path = tinyusb - url = https://github.com/raspberrypi/tinyusb.git - branch = pico -[submodule "pico-sdk"] - path = pico-sdk - url = https://github.com/raspberrypi/pico-sdk.git -[submodule "lwip"] - path = lwip - url = https://git.savannah.nongnu.org/git/lwip.git diff --git a/CMakeLists.txt b/CMakeLists.txt index 4d0da75..382079c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,15 +1,12 @@ cmake_minimum_required(VERSION 3.13) -# We prefer to have all linked submodules at toplevel -set(PICO_TINYUSB_PATH ${CMAKE_CURRENT_SOURCE_DIR}/tinyusb) - -include(pico-sdk/pico_sdk_init.cmake) +include(pico_sdk_import.cmake) project(pico_gb_printer) #set(PICO_CXX_ENABLE_EXCEPTIONS 1) pico_sdk_init() # LWIP -set(LWIP_DIR ${CMAKE_CURRENT_SOURCE_DIR}/lwip) +set(LWIP_DIR ${PICO_SDK_PATH}/lib/lwip) set (LWIP_INCLUDE_DIRS "include" "${LWIP_DIR}/src/include" @@ -18,16 +15,20 @@ set (LWIP_INCLUDE_DIRS include(${LWIP_DIR}/src/Filelists.cmake) # Extra stuff from TinyUSB, that is not part of tinyusb_device library +set(PICO_TINYUSB_PATH ${PICO_SDK_PATH}/lib/tinyusb) set(TINYUSB_LIBNETWORKING_SOURCES ${PICO_TINYUSB_PATH}/lib/networking/dhserver.c + ${PICO_TINYUSB_PATH}/lib/networking/dnserver.c ${PICO_TINYUSB_PATH}/lib/networking/rndis_reports.c ) -add_executable(${PROJECT_NAME} src/pico_gb_printer.c src/gb_printer.c src/tusb_lwip_glue.c src/usb_descriptors.c ${TINYUSB_LIBNETWORKING_SOURCES}) +add_executable(${PROJECT_NAME} src/pico_gb_printer.c src/linkcable.c src/gb_printer.c src/tusb_lwip_glue.c src/usb_descriptors.c ${TINYUSB_LIBNETWORKING_SOURCES}) + +pico_generate_pio_header(${PROJECT_NAME} ${CMAKE_CURRENT_LIST_DIR}/src/linkcable.pio) pico_enable_stdio_usb(${PROJECT_NAME} 0) pico_enable_stdio_uart(${PROJECT_NAME} 0) target_include_directories(${PROJECT_NAME} PRIVATE ${LWIP_INCLUDE_DIRS} ${PICO_TINYUSB_PATH}/src ${PICO_TINYUSB_PATH}/lib/networking) -target_link_libraries(${PROJECT_NAME} pico_stdlib pico_multicore pico_unique_id hardware_spi tinyusb_device lwipallapps lwipcore hardware_flash) +target_link_libraries(${PROJECT_NAME} pico_stdlib hardware_pio pico_unique_id tinyusb_device lwipallapps lwipcore hardware_flash) pico_add_extra_outputs(${PROJECT_NAME}) target_compile_definitions(${PROJECT_NAME} PRIVATE PICO_ENTER_USB_BOOT_ON_EXIT=1) diff --git a/build/pico_gb_printer.uf2 b/build/pico_gb_printer.uf2 index 1f7a24c..a645c0f 100644 Binary files a/build/pico_gb_printer.uf2 and b/build/pico_gb_printer.uf2 differ diff --git a/include/globals.h b/include/globals.h index 23483e8..f7a1239 100644 --- a/include/globals.h +++ b/include/globals.h @@ -17,19 +17,6 @@ #define LED_TOGGLE #endif -// SPI -#define SPI_BAUDRATE 64 * 1024 * 8 - -#define SPI_PORT spi0 -#define PIN_SPI_SIN 0 -#define PIN_SPI_SCK 2 -#define PIN_SPI_SOUT 3 - -//#define SPI_PORT spi1 -//#define PIN_SPI_SCK 10 -//#define PIN_SPI_SOUT 11 -//#define PIN_SPI_SIN 12 - // "Tear" button pin, define to 0 to disable #define PIN_KEY 23 diff --git a/include/linkcable.h b/include/linkcable.h new file mode 100644 index 0000000..966edf6 --- /dev/null +++ b/include/linkcable.h @@ -0,0 +1,29 @@ +#ifndef _LINKCABLE_H_INCLUDE_ +#define _LINKCABLE_H_INCLUDE_ + +#include "hardware/pio.h" + +#define LINKCABLE_PIO pio0 +#define LINKCABLE_SM 0 + +#define LINKCABLE_BITS 8 + +#define PIN_SIN 0 +#define PIN_SCK 2 +#define PIN_SOUT 3 + +static inline uint8_t linkcable_receive(void) { + return pio_sm_get(LINKCABLE_PIO, LINKCABLE_SM); +} + +static inline void linkcable_send(uint8_t data) { + pio_sm_put(LINKCABLE_PIO, LINKCABLE_SM, data); +} + +static inline void linkcable_reset(void) { + pio_sm_restart(LINKCABLE_PIO, LINKCABLE_SM); +} + +void linkcable_init(irq_handler_t onReceive); + +#endif \ No newline at end of file diff --git a/include/lwipopts.h b/include/lwipopts.h index 87ebdce..7e56d4e 100644 --- a/include/lwipopts.h +++ b/include/lwipopts.h @@ -42,11 +42,14 @@ #define LWIP_ICMP 1 #define LWIP_UDP 1 #define LWIP_TCP 1 +#define LWIP_IPV4 1 +#define LWIP_IPV6 0 #define ETH_PAD_SIZE 0 #define LWIP_IP_ACCEPT_UDP_PORT(p) ((p) == PP_NTOHS(67)) #define TCP_MSS (1500 /*mtu*/ - 20 /*iphdr*/ - 20 /*tcphhr*/) #define TCP_SND_BUF (2 * TCP_MSS) +#define TCP_WND (TCP_MSS) #define ETHARP_SUPPORT_STATIC_ENTRIES 1 @@ -67,8 +70,13 @@ #define HTTPD_USE_CUSTOM_FSDATA 0 #define HTTPD_FSDATA_FILE "pico_printer_fs.c" -#define LWIP_SINGLE_NETIF 1 - #define HTTPD_ADDITIONAL_CONTENT_TYPES {"bin", HTTP_CONTENT_TYPE("application/pico-printer-binary-log")} +#define LWIP_SINGLE_NETIF 1 + +#define PBUF_POOL_SIZE 2 +#define LWIP_MULTICAST_PING 1 +#define LWIP_BROADCAST_PING 1 +#define LWIP_IPV6_MLD 0 +#define LWIP_IPV6_SEND_ROUTER_SOLICIT 0 #endif /* __LWIPOPTS_H__ */ diff --git a/include/tusb_config.h b/include/tusb_config.h index 262d4eb..69c549a 100644 --- a/include/tusb_config.h +++ b/include/tusb_config.h @@ -30,46 +30,46 @@ extern "C" { #endif -//-------------------------------------------------------------------- -// COMMON CONFIGURATION -//-------------------------------------------------------------------- +//--------------------------------------------------------------------+ +// Board Specific Configuration +//--------------------------------------------------------------------+ -// defined by board.mk -#ifndef CFG_TUSB_MCU - #error CFG_TUSB_MCU must be defined +#ifndef CFG_TUSB_RHPORT0_MODE +#define CFG_TUSB_RHPORT0_MODE (OPT_MODE_DEVICE | OPT_MODE_HIGH_SPEED) #endif // RHPort number used for device can be defined by board.mk, default to port 0 -#ifndef BOARD_DEVICE_RHPORT_NUM - #define BOARD_DEVICE_RHPORT_NUM 0 +#ifndef BOARD_TUD_RHPORT +#define BOARD_TUD_RHPORT 0 #endif // RHPort max operational speed can defined by board.mk -// Default to Highspeed for MCU with internal HighSpeed PHY (can be port specific), otherwise FullSpeed -#ifndef BOARD_DEVICE_RHPORT_SPEED - #if (CFG_TUSB_MCU == OPT_MCU_LPC18XX || CFG_TUSB_MCU == OPT_MCU_LPC43XX || CFG_TUSB_MCU == OPT_MCU_MIMXRT10XX || \ - CFG_TUSB_MCU == OPT_MCU_NUC505 || CFG_TUSB_MCU == OPT_MCU_CXD56) - #define BOARD_DEVICE_RHPORT_SPEED OPT_MODE_HIGH_SPEED - #else - #define BOARD_DEVICE_RHPORT_SPEED OPT_MODE_FULL_SPEED - #endif +#ifndef BOARD_TUD_MAX_SPEED +#define BOARD_TUD_MAX_SPEED OPT_MODE_DEFAULT_SPEED #endif -// Device mode with rhport and speed defined by board.mk -#if BOARD_DEVICE_RHPORT_NUM == 0 - #define CFG_TUSB_RHPORT0_MODE (OPT_MODE_DEVICE | BOARD_DEVICE_RHPORT_SPEED) -#elif BOARD_DEVICE_RHPORT_NUM == 1 - #define CFG_TUSB_RHPORT1_MODE (OPT_MODE_DEVICE | BOARD_DEVICE_RHPORT_SPEED) -#else - #error "Incorrect RHPort configuration" +//-------------------------------------------------------------------- +// Common Configuration +//-------------------------------------------------------------------- + +// defined by compiler flags for flexibility +#ifndef CFG_TUSB_MCU +#error CFG_TUSB_MCU must be defined #endif #ifndef CFG_TUSB_OS -#define CFG_TUSB_OS OPT_OS_NONE +#define CFG_TUSB_OS OPT_OS_NONE +#endif + +#ifndef CFG_TUSB_DEBUG +#define CFG_TUSB_DEBUG 0 #endif -// CFG_TUSB_DEBUG is defined by compiler in DEBUG build -// #define CFG_TUSB_DEBUG 0 +// Enable Device stack +#define CFG_TUD_ENABLED 1 + +// Default is max speed that hardware controller could support with on-chip PHY +#define CFG_TUD_MAX_SPEED BOARD_TUD_MAX_SPEED /* USB DMA on some MCUs can only access a specific SRAM region with restriction on alignment. * Tinyusb use follows macros to declare transferring memory so that they can be put @@ -83,7 +83,7 @@ #endif #ifndef CFG_TUSB_MEM_ALIGN -#define CFG_TUSB_MEM_ALIGN __attribute__ ((aligned(4))) +#define CFG_TUSB_MEM_ALIGN __attribute__ ((aligned(4))) #endif //-------------------------------------------------------------------- @@ -95,12 +95,11 @@ #endif //------------- CLASS -------------// -#define CFG_TUD_CDC 0 -#define CFG_TUD_MSC 0 -#define CFG_TUD_HID 0 -#define CFG_TUD_MIDI 0 -#define CFG_TUD_VENDOR 0 -#define CFG_TUD_NET 1 + +// Network class has 2 drivers: ECM/RNDIS and NCM. +// Only one of the drivers can be enabled +#define CFG_TUD_ECM_RNDIS 0 +#define CFG_TUD_NCM (1-CFG_TUD_ECM_RNDIS) #ifdef __cplusplus } diff --git a/include/tusb_lwip_glue.h b/include/tusb_lwip_glue.h index 0c4e9c3..ae87cad 100644 --- a/include/tusb_lwip_glue.h +++ b/include/tusb_lwip_glue.h @@ -12,10 +12,11 @@ #include "lwip/timeouts.h" #include "lwip/apps/httpd.h" -void init_lwip(); -void wait_for_netif_is_up(); -void dhcpd_init(); -void service_traffic(); +void init_lwip(void); +void wait_for_netif_is_up(void); +void dhcpd_init(void); +void dns_init(void); +void service_traffic(void); #ifdef __cplusplus } diff --git a/lwip b/lwip deleted file mode 160000 index 0056522..0000000 --- a/lwip +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 0056522cc974d2be2005c324f37187b5b3695765 diff --git a/pico-sdk b/pico-sdk deleted file mode 160000 index fc10a97..0000000 --- a/pico-sdk +++ /dev/null @@ -1 +0,0 @@ -Subproject commit fc10a97c386f65c1a44c68684fe52a56aaf50df0 diff --git a/pico_sdk_import.cmake b/pico_sdk_import.cmake new file mode 100644 index 0000000..65f8a6f --- /dev/null +++ b/pico_sdk_import.cmake @@ -0,0 +1,73 @@ +# This is a copy of /external/pico_sdk_import.cmake + +# This can be dropped into an external project to help locate this SDK +# It should be include()ed prior to project() + +if (DEFINED ENV{PICO_SDK_PATH} AND (NOT PICO_SDK_PATH)) + set(PICO_SDK_PATH $ENV{PICO_SDK_PATH}) + message("Using PICO_SDK_PATH from environment ('${PICO_SDK_PATH}')") +endif () + +if (DEFINED ENV{PICO_SDK_FETCH_FROM_GIT} AND (NOT PICO_SDK_FETCH_FROM_GIT)) + set(PICO_SDK_FETCH_FROM_GIT $ENV{PICO_SDK_FETCH_FROM_GIT}) + message("Using PICO_SDK_FETCH_FROM_GIT from environment ('${PICO_SDK_FETCH_FROM_GIT}')") +endif () + +if (DEFINED ENV{PICO_SDK_FETCH_FROM_GIT_PATH} AND (NOT PICO_SDK_FETCH_FROM_GIT_PATH)) + set(PICO_SDK_FETCH_FROM_GIT_PATH $ENV{PICO_SDK_FETCH_FROM_GIT_PATH}) + message("Using PICO_SDK_FETCH_FROM_GIT_PATH from environment ('${PICO_SDK_FETCH_FROM_GIT_PATH}')") +endif () + +set(PICO_SDK_PATH "${PICO_SDK_PATH}" CACHE PATH "Path to the Raspberry Pi Pico SDK") +set(PICO_SDK_FETCH_FROM_GIT "${PICO_SDK_FETCH_FROM_GIT}" CACHE BOOL "Set to ON to fetch copy of SDK from git if not otherwise locatable") +set(PICO_SDK_FETCH_FROM_GIT_PATH "${PICO_SDK_FETCH_FROM_GIT_PATH}" CACHE FILEPATH "location to download SDK") + +if (NOT PICO_SDK_PATH) + if (PICO_SDK_FETCH_FROM_GIT) + include(FetchContent) + set(FETCHCONTENT_BASE_DIR_SAVE ${FETCHCONTENT_BASE_DIR}) + if (PICO_SDK_FETCH_FROM_GIT_PATH) + get_filename_component(FETCHCONTENT_BASE_DIR "${PICO_SDK_FETCH_FROM_GIT_PATH}" REALPATH BASE_DIR "${CMAKE_SOURCE_DIR}") + endif () + # GIT_SUBMODULES_RECURSE was added in 3.17 + if (${CMAKE_VERSION} VERSION_GREATER_EQUAL "3.17.0") + FetchContent_Declare( + pico_sdk + GIT_REPOSITORY https://github.com/raspberrypi/pico-sdk + GIT_TAG master + GIT_SUBMODULES_RECURSE FALSE + ) + else () + FetchContent_Declare( + pico_sdk + GIT_REPOSITORY https://github.com/raspberrypi/pico-sdk + GIT_TAG master + ) + endif () + + if (NOT pico_sdk) + message("Downloading Raspberry Pi Pico SDK") + FetchContent_Populate(pico_sdk) + set(PICO_SDK_PATH ${pico_sdk_SOURCE_DIR}) + endif () + set(FETCHCONTENT_BASE_DIR ${FETCHCONTENT_BASE_DIR_SAVE}) + else () + message(FATAL_ERROR + "SDK location was not specified. Please set PICO_SDK_PATH or set PICO_SDK_FETCH_FROM_GIT to on to fetch from git." + ) + endif () +endif () + +get_filename_component(PICO_SDK_PATH "${PICO_SDK_PATH}" REALPATH BASE_DIR "${CMAKE_BINARY_DIR}") +if (NOT EXISTS ${PICO_SDK_PATH}) + message(FATAL_ERROR "Directory '${PICO_SDK_PATH}' not found") +endif () + +set(PICO_SDK_INIT_CMAKE_FILE ${PICO_SDK_PATH}/pico_sdk_init.cmake) +if (NOT EXISTS ${PICO_SDK_INIT_CMAKE_FILE}) + message(FATAL_ERROR "Directory '${PICO_SDK_PATH}' does not appear to contain the Raspberry Pi Pico SDK") +endif () + +set(PICO_SDK_PATH ${PICO_SDK_PATH} CACHE PATH "Path to the Raspberry Pi Pico SDK" FORCE) + +include(${PICO_SDK_INIT_CMAKE_FILE}) diff --git a/src/linkcable.c b/src/linkcable.c new file mode 100644 index 0000000..f76c7ec --- /dev/null +++ b/src/linkcable.c @@ -0,0 +1,27 @@ +#include + +#include "hardware/pio.h" +#include "hardware/irq.h" + +#include "linkcable.h" +#include "linkcable.pio.h" + +static irq_handler_t linkcable_irq_handler = NULL; + +static void linkcable_isr(void) { + if (linkcable_irq_handler) linkcable_irq_handler(); + if (pio_interrupt_get(LINKCABLE_PIO, 0)) pio_interrupt_clear(LINKCABLE_PIO, 0); +} + +void linkcable_init(irq_handler_t onDataReceive) { + linkcable_program_init(LINKCABLE_PIO, LINKCABLE_SM, pio_add_program(LINKCABLE_PIO, &linkcable_program), PIN_SIN); +// pio_sm_put_blocking(LINKCABLE_PIO, LINKCABLE_SM, LINKCABLE_BITS - 1); + pio_enable_sm_mask_in_sync(LINKCABLE_PIO, (1u << LINKCABLE_SM)); + + if (onDataReceive) { + linkcable_irq_handler = onDataReceive; + pio_set_irq0_source_enabled(LINKCABLE_PIO, pis_interrupt0, true); + irq_set_exclusive_handler(PIO0_IRQ_0, linkcable_isr); + irq_set_enabled(PIO0_IRQ_0, true); + } +} \ No newline at end of file diff --git a/src/linkcable.pio b/src/linkcable.pio new file mode 100644 index 0000000..23f86ec --- /dev/null +++ b/src/linkcable.pio @@ -0,0 +1,51 @@ +; Program name +.program linkcable + +.wrap_target + wait 0 pin 2 ; wait for falling edge + + pull noblock ; pull value for transmission from pico + out null, 24 ; shift left by 24 + + out pins, 1 ; out the MSB bit + + wait 1 pin 2 ; wait for rising edge + + in pins, 1 ; input MSB bit + + set x, 6 +bitloop: + wait 0 pin 2 ; wait for falling edge + + out pins, 1 ; output rest of the bits one by one + + wait 1 pin 2 ; wait for rising edge + + in pins, 1 ; input rest of the bits one by one + jmp x-- bitloop ; loop through the rest of the bits + + push noblock ; push the received value to pico + irq 0 +.wrap + +% c-sdk { +static inline void linkcable_program_init(PIO pio, uint sm, uint offset, uint pin) { + pio_sm_config c = linkcable_program_get_default_config(offset); + + sm_config_set_in_pins(&c, pin); + pio_sm_set_consecutive_pindirs(pio, sm, pin, 3, false); + sm_config_set_in_shift(&c, false, false, LINKCABLE_BITS); + + sm_config_set_out_pins(&c, pin + 3, 1); + pio_sm_set_consecutive_pindirs(pio, sm, pin + 3, 1, true); + sm_config_set_out_shift(&c, false, false, LINKCABLE_BITS); + +// sm_config_set_clkdiv(&c, 5); // Set clock division (Commented out, this one runs at full speed) + + for (uint i = 0; i != 4; i++) pio_gpio_init(pio, pin + i); + + pio_sm_init(pio, sm, offset, &c); + +// pio_sm_set_enabled(pio, sm, true); // Set the state machine running (commented out, I'll start this in the C) +} +%} \ No newline at end of file diff --git a/src/pico_gb_printer.c b/src/pico_gb_printer.c index f51b687..2369880 100644 --- a/src/pico_gb_printer.c +++ b/src/pico_gb_printer.c @@ -1,17 +1,17 @@ #include "pico/stdlib.h" #include "pico/bootrom.h" -#include "pico/multicore.h" #include "hardware/timer.h" #include "hardware/gpio.h" #include "hardware/irq.h" -#include "hardware/spi.h" #include "hardware/resets.h" +#include "hardware/pio.h" #include "globals.h" #include "lwip/apps/fs.h" #include "tusb_lwip_glue.h" #include "gb_printer.h" +#include "linkcable.h" bool debug_enable = ENABLE_DEBUG; bool speed_240_MHz = false; @@ -22,7 +22,7 @@ uint8_t receive_data[BUFFER_SIZE_KB * 1024]; // buffer length is 96K uint8_t json_buffer[1024] = {0}; // buffer for rendering of status json -void receive_data_reset() { +void receive_data_reset(void) { receive_data_pointer = 0; } @@ -31,7 +31,20 @@ void receive_data_write(uint8_t b) { receive_data[receive_data_pointer++] = b; } -void receive_data_commit() { +void receive_data_commit(void) { +} + +// link cable +uint64_t last_receive_ts; +void link_cable_ISR(void) { + linkcable_send(protocol_data_process(linkcable_receive())); + last_receive_ts = time_us_64(); +} + +void link_cable_process_warchdog(void) { + // reset if idle more than 300ms + uint64_t current_time = time_us_64(); + if ((current_time - last_receive_ts) > MS(300)) linkcable_reset(), last_receive_ts = current_time; } // key button @@ -43,58 +56,6 @@ static void key_callback(uint gpio, uint32_t events) { } #endif -// SPI polling loop and routines -static inline void spi_disable(spi_inst_t *spi) { - hw_clear_bits(&spi_get_hw(spi)->cr1, SPI_SSPCR1_SSE_BITS); -} -static inline void spi_enable(spi_inst_t *spi) { - hw_set_bits(&spi_get_hw(spi)->cr1, SPI_SSPCR1_SSE_BITS); -} -static inline bool spi_busy(spi_inst_t *spi) { - return (spi_get_hw(spi)->sr & SPI_SSPSR_BSY_BITS); -} -static inline bool spi_fifo_empty(spi_inst_t *spi) { - return (spi_get_hw(spi)->sr & SPI_SSPSR_TFE_BITS); -} - -void spi_slave_reinit(spi_inst_t *spi, uint32_t baudrate, uint8_t initial_value) { - reset_block(spi == spi0 ? RESETS_RESET_SPI0_BITS : RESETS_RESET_SPI1_BITS); - unreset_block_wait(spi == spi0 ? RESETS_RESET_SPI0_BITS : RESETS_RESET_SPI1_BITS); - - spi_set_baudrate(spi, baudrate); - spi_set_format(spi, 8, SPI_CPOL_1, SPI_CPHA_1, SPI_MSB_FIRST); - hw_set_bits(&spi_get_hw(spi)->dmacr, SPI_SSPDMACR_TXDMAE_BITS | SPI_SSPDMACR_RXDMAE_BITS); - spi_set_slave(spi, true); - - spi_get_hw(spi)->dr = initial_value; - - hw_set_bits(&spi_get_hw(spi)->cr1, SPI_SSPCR1_SSE_BITS); -} - -void core1_context() { - irq_set_mask_enabled(0xffffffff, false); - - // init SPI - gpio_set_function(PIN_SPI_SCK, GPIO_FUNC_SPI), gpio_pull_up(PIN_SPI_SCK); -// gpio_set_function(PIN_SPI_CS, GPIO_FUNC_SPI), gpio_pull_down(PIN_SPI_CS); - gpio_set_function(PIN_SPI_SIN, GPIO_FUNC_SPI); - gpio_set_function(PIN_SPI_SOUT, GPIO_FUNC_SPI); - - spi_slave_reinit(SPI_PORT, SPI_BAUDRATE, protocol_data_init()); - - uint64_t last_readable = time_us_64(); - while (true) { - uint64_t time_us_now = time_us_64(); - if (spi_is_readable(SPI_PORT)) { - spi_get_hw(SPI_PORT)->dr = protocol_data_process(spi_get_hw(SPI_PORT)->dr); - last_readable = time_us_now; - } else if ((time_us_now - last_readable) > MS(300)) { - spi_slave_reinit(SPI_PORT, SPI_BAUDRATE, protocol_data_init()); - last_readable = time_us_now; - } - } -} - // Webserver dynamic handling #define ROOT_PAGE "/index.shtml" #define IMAGE_FILE "/image.bin" @@ -195,7 +156,7 @@ void fs_close_custom(struct fs_file *file) { } // main loop -int main() { +int main(void) { speed_240_MHz = set_sys_clock_khz(240000, false); // For toggle_led @@ -212,15 +173,17 @@ int main() { gpio_set_irq_enabled_with_callback(PIN_KEY, GPIO_IRQ_EDGE_RISE, true, &key_callback); #endif - // Initialize tinyusb, lwip, dhcpd and httpd + // Initialize tinyusb, lwip, dhcpd, dnsd and httpd init_lwip(); + wait_for_netif_is_up(); dhcpd_init(); + dns_init(); httpd_init(); http_set_cgi_handlers(cgi_handlers, LWIP_ARRAYSIZE(cgi_handlers)); http_set_ssi_handler(ssi_handler, ssi_tags, LWIP_ARRAYSIZE(ssi_tags)); - multicore_launch_core1(core1_context); + linkcable_init(link_cable_ISR); LED_OFF; @@ -229,6 +192,8 @@ int main() { tud_task(); // process WEB service_traffic(); + // linkcable watchdog + link_cable_process_warchdog(); } return 0; diff --git a/src/tusb_lwip_glue.c b/src/tusb_lwip_glue.c index 75c1566..6ed56ea 100644 --- a/src/tusb_lwip_glue.c +++ b/src/tusb_lwip_glue.c @@ -54,12 +54,12 @@ static dhcp_entry_t entries[] = { }; static const dhcp_config_t dhcp_config = { - .router = IPADDR4_INIT_BYTES(0, 0, 0, 0), /* router address (if any) */ - .port = 67, /* listen port */ - .dns = IPADDR4_INIT_BYTES(0, 0, 0, 0), /* dns server (if any) */ - .domain = "picoprinter", /* dns suffix */ - .num_entry = TU_ARRAY_SIZE(entries), /* num entry */ - .entries = entries /* entries */ + .router = IPADDR4_INIT_BYTES(0, 0, 0, 0), /* router address (if any) */ + .port = 67, /* listen port */ + .dns = IPADDR4_INIT_BYTES(192, 168, 7, 1), /* dns server (if any) */ + .domain = "printer", /* dns suffix */ + .num_entry = TU_ARRAY_SIZE(entries), /* num entry */ + .entries = entries /* entries */ }; static err_t linkoutput_fn(struct netif *netif, struct pbuf *p) { @@ -70,7 +70,7 @@ static err_t linkoutput_fn(struct netif *netif, struct pbuf *p) { if (!tud_ready()) return ERR_USE; /* if the network driver can accept another packet, we make it happen */ - if (tud_network_can_xmit()) { + if (tud_network_can_xmit(p->tot_len)) { tud_network_xmit(p, 0 /* unused for this example */); return ERR_OK; } @@ -99,16 +99,10 @@ static err_t netif_init_cb(struct netif *netif) { void init_lwip(void) { struct netif *netif = &netif_data; - /* Fixup MAC address based on flash serial */ - //pico_unique_board_id_t id; - //pico_get_unique_board_id(&id); - //memcpy( (tud_network_mac_address)+1, id.id, 5); - // Fixing up does not work because tud_network_mac_address is const - - /* Initialize tinyUSB */ + /* initialize TinyUSB */ tusb_init(); - /* Initialize lwip */ + /* LWIP init */ lwip_init(); /* the lwip virtual MAC address must be different from the host's; to ensure this, we toggle the LSbit */ @@ -120,12 +114,13 @@ void init_lwip(void) { netif_set_default(netif); } -void tud_network_init_cb(void) { - /* if the network is re-initializing and we have a leftover packet, we must do a cleanup */ - if (received_frame) { - pbuf_free(received_frame); - received_frame = NULL; +/* handle any DNS requests from dns-server */ +bool dns_query_proc(const char *name, ip4_addr_t *addr) { + if (strcmp(name, "gb.printer") == 0) { + *addr = ipaddr; + return true; } + return false; } bool tud_network_recv_cb(const uint8_t *src, uint16_t size) { @@ -175,14 +170,26 @@ void service_traffic(void) { sys_check_timeouts(); } -void dhcpd_init() { +void tud_network_init_cb(void) +{ + /* if the network is re-initializing and we have a leftover packet, we must do a cleanup */ + if (received_frame) { + pbuf_free(received_frame); + received_frame = NULL; + } +} + +void dhcpd_init(void) { while (dhserv_init(&dhcp_config) != ERR_OK); } -void wait_for_netif_is_up() { - while (!netif_is_up(&netif_data)); +void dns_init(void) { + while (dnserv_init(IP_ADDR_ANY, 53, dns_query_proc) != ERR_OK); } +void wait_for_netif_is_up(void) { + while (!netif_is_up(&netif_data)); +} /* lwip platform specific routines for Pico */ auto_init_mutex(lwip_mutex); diff --git a/src/usb_descriptors.c b/src/usb_descriptors.c index 77a97cd..125accb 100644 --- a/src/usb_descriptors.c +++ b/src/usb_descriptors.c @@ -1,4 +1,4 @@ -/* +/* * The MIT License (MIT) * * Copyright (c) 2019 Ha Thach (tinyusb.org) @@ -33,7 +33,7 @@ * [MSB] NET | VENDOR | MIDI | HID | MSC | CDC [LSB] */ #define _PID_MAP(itf, n) ((CFG_TUD_##itf) << (n)) -#define USB_PID (0x4000 | _PID_MAP(CDC, 0) | _PID_MAP(MSC, 1) | _PID_MAP(HID, 2) | _PID_MAP(MIDI, 3) | _PID_MAP(VENDOR, 4) | _PID_MAP(NET, 5)) +#define USB_PID (0x4000 | _PID_MAP(CDC, 0) | _PID_MAP(MSC, 1) | _PID_MAP(HID, 2) | _PID_MAP(MIDI, 3) | _PID_MAP(VENDOR, 4) | _PID_MAP(ECM_RNDIS, 5) | _PID_MAP(NCM, 5)) // String Descriptor Index enum { @@ -52,11 +52,16 @@ enum { }; enum { +#if CFG_TUD_ECM_RNDIS CONFIG_ID_RNDIS = 0, CONFIG_ID_ECM = 1, +#else + CONFIG_ID_NCM = 0, +#endif CONFIG_ID_COUNT }; + //--------------------------------------------------------------------+ // Device Descriptors //--------------------------------------------------------------------+ @@ -69,7 +74,7 @@ tusb_desc_device_t const desc_device = { .bDeviceClass = TUSB_CLASS_MISC, .bDeviceSubClass = MISC_SUBCLASS_COMMON, .bDeviceProtocol = MISC_PROTOCOL_IAD, - + .bMaxPacketSize0 = CFG_TUD_ENDPOINT0_SIZE, .idVendor = 0xCafe, @@ -94,6 +99,7 @@ uint8_t const * tud_descriptor_device_cb(void) { //--------------------------------------------------------------------+ #define MAIN_CONFIG_TOTAL_LEN (TUD_CONFIG_DESC_LEN + TUD_RNDIS_DESC_LEN) #define ALT_CONFIG_TOTAL_LEN (TUD_CONFIG_DESC_LEN + TUD_CDC_ECM_DESC_LEN) +#define NCM_CONFIG_TOTAL_LEN (TUD_CONFIG_DESC_LEN + TUD_CDC_NCM_DESC_LEN) #if CFG_TUSB_MCU == OPT_MCU_LPC175X_6X || CFG_TUSB_MCU == OPT_MCU_LPC177X_8X || CFG_TUSB_MCU == OPT_MCU_LPC40XX // LPC 17xx and 40xx endpoint type (bulk/interrupt/iso) are fixed by its number @@ -102,7 +108,7 @@ uint8_t const * tud_descriptor_device_cb(void) { #define EPNUM_NET_OUT 0x02 #define EPNUM_NET_IN 0x82 -#elif CFG_TUSB_MCU == OPT_MCU_SAMG +#elif CFG_TUSB_MCU == OPT_MCU_SAMG || CFG_TUSB_MCU == OPT_MCU_SAMX7X // SAMG doesn't support a same endpoint number with different direction IN and OUT // e.g EP1 OUT & EP1 IN cannot exist together #define EPNUM_NET_NOTIF 0x81 @@ -115,9 +121,11 @@ uint8_t const * tud_descriptor_device_cb(void) { #define EPNUM_NET_IN 0x82 #endif +#if CFG_TUD_ECM_RNDIS + static uint8_t const rndis_configuration[] = { // Config number (index+1), interface count, string index, total length, attribute, power in mA - TUD_CONFIG_DESCRIPTOR(CONFIG_ID_RNDIS + 1, ITF_NUM_TOTAL, 0, MAIN_CONFIG_TOTAL_LEN, 0, 100), + TUD_CONFIG_DESCRIPTOR(CONFIG_ID_RNDIS+1, ITF_NUM_TOTAL, 0, MAIN_CONFIG_TOTAL_LEN, 0, 100), // Interface number, string index, EP notification address and size, EP data address (out, in) and size. TUD_RNDIS_DESCRIPTOR(ITF_NUM_CDC, STRID_INTERFACE, EPNUM_NET_NOTIF, 8, EPNUM_NET_OUT, EPNUM_NET_IN, CFG_TUD_NET_ENDPOINT_SIZE), @@ -125,20 +133,35 @@ static uint8_t const rndis_configuration[] = { static uint8_t const ecm_configuration[] = { // Config number (index+1), interface count, string index, total length, attribute, power in mA - TUD_CONFIG_DESCRIPTOR(CONFIG_ID_ECM + 1, ITF_NUM_TOTAL, 0, ALT_CONFIG_TOTAL_LEN, 0, 100), + TUD_CONFIG_DESCRIPTOR(CONFIG_ID_ECM+1, ITF_NUM_TOTAL, 0, ALT_CONFIG_TOTAL_LEN, 0, 100), // Interface number, description string index, MAC address string index, EP notification address and size, EP data address (out, in), and size, max segment size. TUD_CDC_ECM_DESCRIPTOR(ITF_NUM_CDC, STRID_INTERFACE, STRID_MAC, EPNUM_NET_NOTIF, 64, EPNUM_NET_OUT, EPNUM_NET_IN, CFG_TUD_NET_ENDPOINT_SIZE, CFG_TUD_NET_MTU), }; +#else + +static uint8_t const ncm_configuration[] = { + // Config number (index+1), interface count, string index, total length, attribute, power in mA + TUD_CONFIG_DESCRIPTOR(CONFIG_ID_NCM+1, ITF_NUM_TOTAL, 0, NCM_CONFIG_TOTAL_LEN, 0, 100), + + // Interface number, description string index, MAC address string index, EP notification address and size, EP data address (out, in), and size, max segment size. + TUD_CDC_NCM_DESCRIPTOR(ITF_NUM_CDC, STRID_INTERFACE, STRID_MAC, EPNUM_NET_NOTIF, 64, EPNUM_NET_OUT, EPNUM_NET_IN, CFG_TUD_NET_ENDPOINT_SIZE, CFG_TUD_NET_MTU), +}; + +#endif + // Configuration array: RNDIS and CDC-ECM // - Windows only works with RNDIS // - MacOS only works with CDC-ECM // - Linux will work on both -// Note index is Num-1x static uint8_t const * const configuration_arr[CONFIG_ID_COUNT] = { +#if CFG_TUD_ECM_RNDIS [CONFIG_ID_RNDIS] = rndis_configuration, [CONFIG_ID_ECM ] = ecm_configuration +#else + [CONFIG_ID_NCM ] = ncm_configuration +#endif }; // Invoked when received GET CONFIGURATION DESCRIPTOR diff --git a/tinyusb b/tinyusb deleted file mode 160000 index 11c23f8..0000000 --- a/tinyusb +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 11c23f88bf42f64ce14b8a7b0b2a4e207dc4dd12