diff --git a/Marlin/Configuration_adv.h b/Marlin/Configuration_adv.h index 95e93eb288..fa1b470ab2 100644 --- a/Marlin/Configuration_adv.h +++ b/Marlin/Configuration_adv.h @@ -1478,6 +1478,15 @@ // Enable if SD detect is rendered useless (e.g., by using an SD extender) //#define NO_SD_DETECT + // Multiple volume support - EXPERIMENTAL. + //#define MULTI_VOLUME + #if ENABLED(MULTI_VOLUME) + #define VOLUME_SD_ONBOARD + #define VOLUME_USB_FLASH_DRIVE + #define DEFAULT_VOLUME SD_ONBOARD + #define DEFAULT_SHARED_VOLUME USB_FLASH_DRIVE + #endif + #endif // SDSUPPORT /** diff --git a/Marlin/src/HAL/DUE/usb/sd_mmc_spi_mem.cpp b/Marlin/src/HAL/DUE/usb/sd_mmc_spi_mem.cpp index d92d332c1e..3dcbbaecd2 100644 --- a/Marlin/src/HAL/DUE/usb/sd_mmc_spi_mem.cpp +++ b/Marlin/src/HAL/DUE/usb/sd_mmc_spi_mem.cpp @@ -32,7 +32,7 @@ Ctrl_status sd_mmc_spi_test_unit_ready() { Ctrl_status sd_mmc_spi_read_capacity(uint32_t *nb_sector) { if (!IS_SD_INSERTED() || IS_SD_PRINTING() || IS_SD_FILE_OPEN() || !card.isMounted()) return CTRL_NO_PRESENT; - *nb_sector = card.getSd2Card().cardSize() - 1; + *nb_sector = card.diskIODriver()->cardSize() - 1; return CTRL_GOOD; } @@ -74,24 +74,24 @@ Ctrl_status sd_mmc_spi_usb_read_10(uint32_t addr, uint16_t nb_sector) { #endif // Start reading - if (!card.getSd2Card().readStart(addr)) + if (!card.diskIODriver()->readStart(addr)) return CTRL_FAIL; // For each specified sector while (nb_sector--) { // Read a sector - card.getSd2Card().readData(sector_buf); + card.diskIODriver()->readData(sector_buf); // RAM -> USB if (!udi_msc_trans_block(true, sector_buf, SD_MMC_BLOCK_SIZE, nullptr)) { - card.getSd2Card().readStop(); + card.diskIODriver()->readStop(); return CTRL_FAIL; } } // Stop reading - card.getSd2Card().readStop(); + card.diskIODriver()->readStop(); // Done return CTRL_GOOD; @@ -113,7 +113,7 @@ Ctrl_status sd_mmc_spi_usb_write_10(uint32_t addr, uint16_t nb_sector) { } #endif - if (!card.getSd2Card().writeStart(addr, nb_sector)) + if (!card.diskIODriver()->writeStart(addr, nb_sector)) return CTRL_FAIL; // For each specified sector @@ -121,16 +121,16 @@ Ctrl_status sd_mmc_spi_usb_write_10(uint32_t addr, uint16_t nb_sector) { // USB -> RAM if (!udi_msc_trans_block(false, sector_buf, SD_MMC_BLOCK_SIZE, nullptr)) { - card.getSd2Card().writeStop(); + card.diskIODriver()->writeStop(); return CTRL_FAIL; } // Write a sector - card.getSd2Card().writeData(sector_buf); + card.diskIODriver()->writeData(sector_buf); } // Stop writing - card.getSd2Card().writeStop(); + card.diskIODriver()->writeStop(); // Done return CTRL_GOOD; diff --git a/Marlin/src/HAL/STM32/msc_sd.cpp b/Marlin/src/HAL/STM32/msc_sd.cpp index 63ce7808f1..20e1ab3cf9 100644 --- a/Marlin/src/HAL/STM32/msc_sd.cpp +++ b/Marlin/src/HAL/STM32/msc_sd.cpp @@ -30,54 +30,66 @@ class Sd2CardUSBMscHandler : public USBMscHandler { public: + DiskIODriver* diskIODriver() { + #if ENABLED(MULTI_VOLUME) + #if SHARED_VOLUME_IS(SD_ONBOARD) + return &card.media_sd_spi; + #elif SHARED_VOLUME_IS(USB_FLASH_DRIVE) + return &card.media_usbFlashDrive; + #endif + #else + return diskIODriver(); + #endif + } + bool GetCapacity(uint32_t *pBlockNum, uint16_t *pBlockSize) { - *pBlockNum = card.getSd2Card().cardSize(); + *pBlockNum = diskIODriver()->cardSize(); *pBlockSize = BLOCK_SIZE; return true; } bool Write(uint8_t *pBuf, uint32_t blkAddr, uint16_t blkLen) { - auto sd2card = card.getSd2Card(); + auto sd2card = diskIODriver(); // single block if (blkLen == 1) { watchdog_refresh(); - sd2card.writeBlock(blkAddr, pBuf); + sd2card->writeBlock(blkAddr, pBuf); return true; } // multi block optmization - sd2card.writeStart(blkAddr, blkLen); + sd2card->writeStart(blkAddr, blkLen); while (blkLen--) { watchdog_refresh(); - sd2card.writeData(pBuf); + sd2card->writeData(pBuf); pBuf += BLOCK_SIZE; } - sd2card.writeStop(); + sd2card->writeStop(); return true; } bool Read(uint8_t *pBuf, uint32_t blkAddr, uint16_t blkLen) { - auto sd2card = card.getSd2Card(); + auto sd2card = diskIODriver(); // single block if (blkLen == 1) { watchdog_refresh(); - sd2card.readBlock(blkAddr, pBuf); + sd2card->readBlock(blkAddr, pBuf); return true; } // multi block optmization - sd2card.readStart(blkAddr); + sd2card->readStart(blkAddr); while (blkLen--) { watchdog_refresh(); - sd2card.readData(pBuf); + sd2card->readData(pBuf); pBuf += BLOCK_SIZE; } - sd2card.readStop(); + sd2card->readStop(); return true; } bool IsReady() { - return card.isMounted(); + return diskIODriver()->isReady(); } }; @@ -105,8 +117,8 @@ USBMscHandler *pSingleMscHandler = &usbMscHandler; void MSC_SD_init() { USBDevice.end(); delay(200); - USBDevice.begin(); USBDevice.registerMscHandlers(1, &pSingleMscHandler, Marlin_STORAGE_Inquirydata); + USBDevice.begin(); } #endif // __STM32F1__ && HAS_SD_HOST_DRIVE diff --git a/Marlin/src/MarlinCore.cpp b/Marlin/src/MarlinCore.cpp index 738f9a8d78..842429a407 100644 --- a/Marlin/src/MarlinCore.cpp +++ b/Marlin/src/MarlinCore.cpp @@ -757,7 +757,7 @@ void idle(TERN_(ADVANCED_PAUSE_FEATURE, bool no_stepper_sleep/*=false*/)) { TERN_(SDSUPPORT, card.manage_media()); // Handle USB Flash Drive insert / remove - TERN_(USB_FLASH_DRIVE_SUPPORT, Sd2Card::idle()); + TERN_(USB_FLASH_DRIVE_SUPPORT, card.diskIODriver()->idle()); // Announce Host Keepalive state (if any) TERN_(HOST_KEEPALIVE_FEATURE, gcode.host_keepalive()); diff --git a/Marlin/src/inc/Conditionals_adv.h b/Marlin/src/inc/Conditionals_adv.h index 3bd77d7545..735e6464d9 100644 --- a/Marlin/src/inc/Conditionals_adv.h +++ b/Marlin/src/inc/Conditionals_adv.h @@ -245,7 +245,7 @@ #define _CUTTER_POWER_PERCENT 2 #define _CUTTER_POWER_RPM 3 #define _CUTTER_POWER(V) _CAT(_CUTTER_POWER_, V) - #define CUTTER_UNIT_IS(V) (_CUTTER_POWER(CUTTER_POWER_UNIT) == _CUTTER_POWER(V)) + #define CUTTER_UNIT_IS(V) (_CUTTER_POWER(CUTTER_POWER_UNIT) == _CUTTER_POWER(V)) #endif // Add features that need hardware PWM here diff --git a/Marlin/src/inc/Conditionals_post.h b/Marlin/src/inc/Conditionals_post.h index 337cf2a950..f00dd6ec97 100644 --- a/Marlin/src/inc/Conditionals_post.h +++ b/Marlin/src/inc/Conditionals_post.h @@ -356,6 +356,15 @@ #define SD_DETECT_STATE LOW #endif #endif + + #if DISABLED(USB_FLASH_DRIVE_SUPPORT) || BOTH(MULTI_VOLUME, VOLUME_SD_ONBOARD) + #if ENABLED(SDIO_SUPPORT) + #define NEED_SD2CARD_SDIO 1 + #else + #define NEED_SD2CARD_SPI 1 + #endif + #endif + #endif #if ANY(HAS_GRAPHICAL_TFT, LCD_USE_DMA_FSMC, HAS_FSMC_GRAPHICAL_TFT, HAS_SPI_GRAPHICAL_TFT) || !PIN_EXISTS(SD_DETECT) diff --git a/Marlin/src/lcd/extui/lib/mks_ui/draw_keyboard.cpp b/Marlin/src/lcd/extui/lib/mks_ui/draw_keyboard.cpp index a05c558beb..3572991813 100644 --- a/Marlin/src/lcd/extui/lib/mks_ui/draw_keyboard.cpp +++ b/Marlin/src/lcd/extui/lib/mks_ui/draw_keyboard.cpp @@ -148,7 +148,7 @@ static void lv_kb_event_cb(lv_obj_t *kb, lv_event_t event) { public_buf_l[6] = 0x00; raw_send_to_wifi((uint8_t*)public_buf_l, 6); - last_disp_state = KEY_BOARD_UI; + last_disp_state = KEYBOARD_UI; lv_clear_keyboard(); wifi_tips_type = TIPS_TYPE_JOINING; lv_draw_wifi_tips(); @@ -216,7 +216,7 @@ static void lv_kb_event_cb(lv_obj_t *kb, lv_event_t event) { } void lv_draw_keyboard() { - scr = lv_screen_create(KEY_BOARD_UI, ""); + scr = lv_screen_create(KEYBOARD_UI, ""); // Create styles for the keyboard static lv_style_t rel_style, pr_style; diff --git a/Marlin/src/lcd/extui/lib/mks_ui/draw_media_select.cpp b/Marlin/src/lcd/extui/lib/mks_ui/draw_media_select.cpp new file mode 100644 index 0000000000..6dc816cc23 --- /dev/null +++ b/Marlin/src/lcd/extui/lib/mks_ui/draw_media_select.cpp @@ -0,0 +1,73 @@ +/** + * Marlin 3D Printer Firmware + * Copyright (c) 2021 MarlinFirmware [https://github.com/MarlinFirmware/Marlin] + * + * Based on Sprinter and grbl. + * Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ +#include "../../../../inc/MarlinConfigPre.h" + +#if BOTH(HAS_TFT_LVGL_UI, MULTI_VOLUME) + +#include "draw_ui.h" +#include + +#include "../../../../inc/MarlinConfig.h" +#include "../../../../sd/cardreader.h" + +extern lv_group_t *g; +static lv_obj_t *scr; + +enum { + ID_T_USB_DISK = 1, + ID_T_SD_DISK, + ID_T_RETURN +}; + +#if ENABLED(MKS_TEST) + extern uint8_t curent_disp_ui; +#endif + +static void event_handler(lv_obj_t *obj, lv_event_t event) { + if (event != LV_EVENT_RELEASED) return; + lv_clear_media_select(); + switch (obj->mks_obj_id) { + case ID_T_USB_DISK: card.changeMedia(&card.media_usbFlashDrive); break; + case ID_T_SD_DISK: card.changeMedia(&card.media_sd_spi); break; + case ID_T_RETURN: + TERN_(MKS_TEST, curent_disp_ui = 1); + lv_draw_ready_print(); + return; + } + lv_draw_print_file(); +} + +void lv_draw_media_select() { + scr = lv_screen_create(MEDIA_SELECT_UI); + lv_big_button_create(scr, "F:/bmp_sd.bin", media_select_menu.sd_disk, INTERVAL_V, titleHeight, event_handler, ID_T_SD_DISK); + lv_big_button_create(scr, "F:/bmp_usb_disk.bin", media_select_menu.usb_disk, BTN_X_PIXEL + INTERVAL_V * 2, titleHeight, event_handler, ID_T_USB_DISK); + lv_big_button_create(scr, "F:/bmp_return.bin", common_menu.text_back, BTN_X_PIXEL * 3 + INTERVAL_V * 4, BTN_Y_PIXEL + INTERVAL_H + titleHeight, event_handler, ID_T_RETURN); +} + +void lv_clear_media_select() { + #if HAS_ROTARY_ENCODER + if (gCfgItems.encoder_enable) lv_group_remove_all_objs(g); + #endif + lv_obj_del(scr); +} + +#endif // HAS_TFT_LVGL_UI diff --git a/Marlin/src/lcd/extui/lib/mks_ui/draw_media_select.h b/Marlin/src/lcd/extui/lib/mks_ui/draw_media_select.h new file mode 100644 index 0000000000..a698714a9d --- /dev/null +++ b/Marlin/src/lcd/extui/lib/mks_ui/draw_media_select.h @@ -0,0 +1,33 @@ +/** + * Marlin 3D Printer Firmware + * Copyright (c) 2021 MarlinFirmware [https://github.com/MarlinFirmware/Marlin] + * + * Based on Sprinter and grbl. + * Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ +#pragma once + +#ifdef __cplusplus + extern "C" { /* C-declarations for C++ */ +#endif + +extern void lv_draw_media_select(); +extern void lv_clear_media_select(); + +#ifdef __cplusplus + } /* C-declarations for C++ */ +#endif diff --git a/Marlin/src/lcd/extui/lib/mks_ui/draw_print_file.cpp b/Marlin/src/lcd/extui/lib/mks_ui/draw_print_file.cpp index d32851f761..17f5d95d2a 100644 --- a/Marlin/src/lcd/extui/lib/mks_ui/draw_print_file.cpp +++ b/Marlin/src/lcd/extui/lib/mks_ui/draw_print_file.cpp @@ -177,7 +177,7 @@ static void event_handler(lv_obj_t *obj, lv_event_t event) { } else { lv_clear_print_file(); - lv_draw_ready_print(); + TERN(MULTI_VOLUME, lv_draw_media_select(), lv_draw_ready_print()); } } else { @@ -248,6 +248,7 @@ static char test_public_buf_l[40]; void disp_gcode_icon(uint8_t file_num) { uint8_t i; + // TODO: set current media title?! scr = lv_screen_create(PRINT_FILE_UI, ""); // Create image buttons diff --git a/Marlin/src/lcd/extui/lib/mks_ui/draw_ready_print.cpp b/Marlin/src/lcd/extui/lib/mks_ui/draw_ready_print.cpp index d02e774b94..09784b5184 100644 --- a/Marlin/src/lcd/extui/lib/mks_ui/draw_ready_print.cpp +++ b/Marlin/src/lcd/extui/lib/mks_ui/draw_ready_print.cpp @@ -73,7 +73,7 @@ static void event_handler(lv_obj_t *obj, lv_event_t event) { case ID_INFO_EXT: uiCfg.curTempType = 0; lv_draw_preHeat(); break; case ID_INFO_BED: uiCfg.curTempType = 1; lv_draw_preHeat(); break; case ID_INFO_FAN: lv_draw_fan(); break; - case ID_PRINT: lv_draw_print_file(); break; + case ID_PRINT: TERN(MULTI_VOLUME, lv_draw_media_select(), lv_draw_print_file()); break; } } diff --git a/Marlin/src/lcd/extui/lib/mks_ui/draw_ui.cpp b/Marlin/src/lcd/extui/lib/mks_ui/draw_ui.cpp index 51e187435c..0a99df08e5 100644 --- a/Marlin/src/lcd/extui/lib/mks_ui/draw_ui.cpp +++ b/Marlin/src/lcd/extui/lib/mks_ui/draw_ui.cpp @@ -447,111 +447,63 @@ char *getDispText(int index) { ZERO(public_buf_l); switch (disp_state_stack._disp_state[index]) { - case PRINT_READY_UI: - strcpy(public_buf_l, main_menu.title); - break; - case PRINT_FILE_UI: - strcpy(public_buf_l, file_menu.title); - break; + case PRINT_READY_UI: strcpy(public_buf_l, main_menu.title); break; + case PRINT_FILE_UI: strcpy(public_buf_l, file_menu.title); break; case PRINTING_UI: - if (disp_state_stack._disp_state[disp_state_stack._disp_index] == PRINTING_UI - #ifndef TFT35 - || disp_state_stack._disp_state[disp_state_stack._disp_index] == OPERATE_UI - || disp_state_stack._disp_state[disp_state_stack._disp_index] == PAUSE_UI - #endif - ) strcpy(public_buf_l, common_menu.print_special_title); - else strcpy(public_buf_l, printing_menu.title); - break; - case MOVE_MOTOR_UI: - strcpy(public_buf_l, move_menu.title); + switch (disp_state_stack._disp_state[disp_state_stack._disp_index]) { + IF_DISABLED(TFT35, case OPERATE_UI: case PAUSE_UI:) + case PRINTING_UI: strcpy(public_buf_l, common_menu.print_special_title); break; + default: strcpy(public_buf_l, printing_menu.title); break; + } break; + case MOVE_MOTOR_UI: strcpy(public_buf_l, move_menu.title); break; case OPERATE_UI: - if (disp_state_stack._disp_state[disp_state_stack._disp_index] == PRINTING_UI - #ifndef TFT35 - || disp_state_stack._disp_state[disp_state_stack._disp_index] == OPERATE_UI - || disp_state_stack._disp_state[disp_state_stack._disp_index] == PAUSE_UI - #endif - ) strcpy(public_buf_l, common_menu.operate_special_title); - else strcpy(public_buf_l, operation_menu.title); + switch (disp_state_stack._disp_state[disp_state_stack._disp_index]) { + IF_DISABLED(TFT35, case OPERATE_UI: case PAUSE_UI:) + case PRINTING_UI: strcpy(public_buf_l, common_menu.operate_special_title); break; + default: strcpy(public_buf_l, operation_menu.title); break; + } break; case PAUSE_UI: - if (disp_state_stack._disp_state[disp_state_stack._disp_index] == PRINTING_UI - || disp_state_stack._disp_state[disp_state_stack._disp_index] == OPERATE_UI - || disp_state_stack._disp_state[disp_state_stack._disp_index] == PAUSE_UI - ) strcpy(public_buf_l, common_menu.pause_special_title); - else strcpy(public_buf_l, pause_menu.title); - break; - - case EXTRUSION_UI: - strcpy(public_buf_l, extrude_menu.title); - break; - case CHANGE_SPEED_UI: - strcpy(public_buf_l, speed_menu.title); - break; - case FAN_UI: - strcpy(public_buf_l, fan_menu.title); + switch (disp_state_stack._disp_state[disp_state_stack._disp_index]) { + case OPERATE_UI: + case PAUSE_UI: + case PRINTING_UI: strcpy(public_buf_l, common_menu.pause_special_title); break; + default: strcpy(public_buf_l, pause_menu.title); break; + } break; + case EXTRUSION_UI: strcpy(public_buf_l, extrude_menu.title); break; + case CHANGE_SPEED_UI: strcpy(public_buf_l, speed_menu.title); break; + case FAN_UI: strcpy(public_buf_l, fan_menu.title); break; case PRE_HEAT_UI: - if ((disp_state_stack._disp_state[disp_state_stack._disp_index - 1] == OPERATE_UI)) - strcpy(public_buf_l, preheat_menu.adjust_title); - else strcpy(public_buf_l, preheat_menu.title); - break; - case SET_UI: - strcpy(public_buf_l, set_menu.title); - break; - case ZERO_UI: - strcpy(public_buf_l, home_menu.title); - break; - case SPRAYER_UI: break; - case MACHINE_UI: break; - case LANGUAGE_UI: - strcpy(public_buf_l, language_menu.title); - break; - case ABOUT_UI: - strcpy(public_buf_l, about_menu.title); - break; - case LOG_UI: break; - case DISK_UI: - strcpy(public_buf_l, filesys_menu.title); - break; - case DIALOG_UI: - strcpy(public_buf_l, common_menu.dialog_confirm_title); - break; - case WIFI_UI: - strcpy(public_buf_l, wifi_menu.title); + switch (disp_state_stack._disp_state[disp_state_stack._disp_index]) { + case OPERATE_UI: strcpy(public_buf_l, preheat_menu.adjust_title); + default: strcpy(public_buf_l, preheat_menu.title); break; + } break; + case SET_UI: strcpy(public_buf_l, set_menu.title); break; + case ZERO_UI: strcpy(public_buf_l, home_menu.title); break; + case SPRAYER_UI: break; + case MACHINE_UI: break; + case LANGUAGE_UI: strcpy(public_buf_l, language_menu.title); break; + case ABOUT_UI: strcpy(public_buf_l, about_menu.title); break; + case LOG_UI: break; + case DISK_UI: strcpy(public_buf_l, filesys_menu.title); break; + case DIALOG_UI: strcpy(public_buf_l, common_menu.dialog_confirm_title); break; + case WIFI_UI: strcpy(public_buf_l, wifi_menu.title); break; case MORE_UI: - case PRINT_MORE_UI: - strcpy(public_buf_l, more_menu.title); - break; - case FILAMENTCHANGE_UI: - strcpy(public_buf_l, filament_menu.title); - break; + case PRINT_MORE_UI: strcpy(public_buf_l, more_menu.title); break; + case FILAMENTCHANGE_UI: strcpy(public_buf_l, filament_menu.title); break; case LEVELING_UI: - case MESHLEVELING_UI: - strcpy(public_buf_l, leveling_menu.title); - break; - case BIND_UI: - strcpy(public_buf_l, cloud_menu.title); - break; - case TOOL_UI: - strcpy(public_buf_l, tool_menu.title); - break; - case WIFI_LIST_UI: - #if ENABLED(MKS_WIFI_MODULE) - strcpy(public_buf_l, list_menu.title); - break; - #endif - case MACHINE_PARA_UI: - strcpy(public_buf_l, MachinePara_menu.title); - break; - case BABY_STEP_UI: - strcpy(public_buf_l, operation_menu.babystep); - break; - case EEPROM_SETTINGS_UI: - strcpy(public_buf_l, eeprom_menu.title); - break; + case MESHLEVELING_UI: strcpy(public_buf_l, leveling_menu.title); break; + case BIND_UI: strcpy(public_buf_l, cloud_menu.title); break; + case TOOL_UI: strcpy(public_buf_l, tool_menu.title); break; + case WIFI_LIST_UI: TERN_(MKS_WIFI_MODULE, strcpy(public_buf_l, list_menu.title)); break; + case MACHINE_PARA_UI: strcpy(public_buf_l, MachinePara_menu.title); break; + case BABY_STEP_UI: strcpy(public_buf_l, operation_menu.babystep); break; + case EEPROM_SETTINGS_UI: strcpy(public_buf_l, eeprom_menu.title); break; + case MEDIA_SELECT_UI: strcpy(public_buf_l, media_select_menu.title); break; default: break; } @@ -828,11 +780,9 @@ void GUI_RefreshPage() { } break; - case OPERATE_UI: - break; + case OPERATE_UI: break; - case PAUSE_UI: - break; + case PAUSE_UI: break; case FAN_UI: if (temps_update_flag) { @@ -841,8 +791,7 @@ void GUI_RefreshPage() { } break; - case MOVE_MOTOR_UI: - break; + case MOVE_MOTOR_UI: break; #if ENABLED(MKS_WIFI_MODULE) case WIFI_UI: @@ -852,10 +801,9 @@ void GUI_RefreshPage() { } break; - case BIND_UI: - refresh_bind_ui(); - break; + case BIND_UI: refresh_bind_ui(); break; #endif + case FILAMENTCHANGE_UI: if (temps_update_flag) { temps_update_flag = false; @@ -866,10 +814,8 @@ void GUI_RefreshPage() { filament_dialog_handle(); TERN_(MKS_WIFI_MODULE, wifi_scan_handle()); break; - case MESHLEVELING_UI: - break; - case HARDWARE_TEST_UI: - break; + case MESHLEVELING_UI: break; + case HARDWARE_TEST_UI: break; case WIFI_LIST_UI: #if ENABLED(MKS_WIFI_MODULE) if (printing_rate_update_flag) { @@ -878,8 +824,8 @@ void GUI_RefreshPage() { } #endif break; - case KEY_BOARD_UI: - break; + case KEYBOARD_UI: break; + #if ENABLED(MKS_WIFI_MODULE) case WIFI_TIPS_UI: switch (wifi_tips_type) { @@ -932,6 +878,7 @@ void GUI_RefreshPage() { disp_z_offset_value(); } break; + default: break; } @@ -982,7 +929,7 @@ void clear_cur_ui() { #if ENABLED(MKS_WIFI_MODULE) case WIFI_LIST_UI: lv_clear_wifi_list(); break; #endif - case KEY_BOARD_UI: lv_clear_keyboard(); break; + case KEYBOARD_UI: lv_clear_keyboard(); break; #if ENABLED(MKS_WIFI_MODULE) case WIFI_TIPS_UI: lv_clear_wifi_tips(); break; #endif @@ -1013,9 +960,9 @@ void clear_cur_ui() { case NUMBER_KEY_UI: lv_clear_number_key(); break; case BABY_STEP_UI: lv_clear_baby_stepping(); break; case PAUSE_POS_UI: lv_clear_pause_position(); break; - #if HAS_TRINAMIC_CONFIG - case TMC_CURRENT_UI: lv_clear_tmc_current_settings(); break; - #endif + #if HAS_TRINAMIC_CONFIG + case TMC_CURRENT_UI: lv_clear_tmc_current_settings(); break; + #endif case EEPROM_SETTINGS_UI: lv_clear_eeprom_settings(); break; #if HAS_STEALTHCHOP case TMC_MODE_UI: lv_clear_tmc_step_mode_settings(); break; @@ -1032,6 +979,9 @@ void clear_cur_ui() { #if ENABLED(TOUCH_SCREEN_CALIBRATION) case TOUCH_CALIBRATION_UI: lv_clear_touch_calibration_screen(); break; #endif + #if ENABLED(MULTI_VOLUME) + case MEDIA_SELECT_UI: lv_clear_media_select(); break; + #endif default: break; } } @@ -1087,7 +1037,7 @@ void draw_return_ui() { #if ENABLED(MKS_WIFI_MODULE) case WIFI_LIST_UI: lv_draw_wifi_list(); break; #endif - case KEY_BOARD_UI: lv_draw_keyboard(); break; + case KEYBOARD_UI: lv_draw_keyboard(); break; #if ENABLED(MKS_WIFI_MODULE) case WIFI_TIPS_UI: lv_draw_wifi_tips(); break; #endif diff --git a/Marlin/src/lcd/extui/lib/mks_ui/draw_ui.h b/Marlin/src/lcd/extui/lib/mks_ui/draw_ui.h index 6577d80cdf..2809e4e937 100644 --- a/Marlin/src/lcd/extui/lib/mks_ui/draw_ui.h +++ b/Marlin/src/lcd/extui/lib/mks_ui/draw_ui.h @@ -76,6 +76,7 @@ #include "draw_homing_sensitivity_settings.h" #include "draw_baby_stepping.h" #include "draw_keyboard.h" +#include "draw_media_select.h" #include "draw_encoder_settings.h" #include "../../../../inc/MarlinConfigPre.h" @@ -289,7 +290,7 @@ typedef enum { TOOL_UI, HARDWARE_TEST_UI, WIFI_LIST_UI, - KEY_BOARD_UI, + KEYBOARD_UI, WIFI_TIPS_UI, MACHINE_PARA_UI, MACHINE_SETTINGS_UI, @@ -327,6 +328,7 @@ typedef enum { ENCODER_SETTINGS_UI, TOUCH_CALIBRATION_UI, GCODE_UI, + MEDIA_SELECT_UI, } DISP_STATE; typedef struct { diff --git a/Marlin/src/lcd/extui/lib/mks_ui/pic_manager.cpp b/Marlin/src/lcd/extui/lib/mks_ui/pic_manager.cpp index 36f276c21b..9318b50d2b 100644 --- a/Marlin/src/lcd/extui/lib/mks_ui/pic_manager.cpp +++ b/Marlin/src/lcd/extui/lib/mks_ui/pic_manager.cpp @@ -197,6 +197,13 @@ static const char assets[][LONG_FILENAME_LENGTH] = { "bmp_cloud.bin", #endif + #if ENABLED(MULTI_VOLUME) + "bmp_usb_disk.bin", + // "bmp_usb_disk_sel.bin", + "bmp_sd.bin", + // "bmp_sd_sel.bin", + #endif + // Babystep screen "bmp_baby_move0_01.bin", "bmp_baby_move0_05.bin", diff --git a/Marlin/src/lcd/extui/lib/mks_ui/tft_Language_en.h b/Marlin/src/lcd/extui/lib/mks_ui/tft_Language_en.h index 104e1fdcaf..b6eef18368 100644 --- a/Marlin/src/lcd/extui/lib/mks_ui/tft_Language_en.h +++ b/Marlin/src/lcd/extui/lib/mks_ui/tft_Language_en.h @@ -540,6 +540,7 @@ #define USB_DRIVE_BACK_EN "< Back" #define FILE_PAGES_EN "%d/%d" #define FILE_NEXT_PAGE_EN "Next Page" +#define MEDIA_SELECT_TITLE_EN "Select Media" //BUILD PLATE #define PLATE_TITLE_EN "Build Plate" diff --git a/Marlin/src/lcd/extui/lib/mks_ui/tft_multi_language.cpp b/Marlin/src/lcd/extui/lib/mks_ui/tft_multi_language.cpp index 20b7d5f606..5e37acb2b4 100644 --- a/Marlin/src/lcd/extui/lib/mks_ui/tft_multi_language.cpp +++ b/Marlin/src/lcd/extui/lib/mks_ui/tft_multi_language.cpp @@ -56,6 +56,7 @@ tool_menu_def tool_menu; MachinePara_menu_def MachinePara_menu; pause_msg_def pause_msg_menu; eeprom_def eeprom_menu; +media_select_menu_def media_select_menu; machine_common_def machine_menu; void machine_setting_disp() { @@ -821,6 +822,10 @@ void disp_language_init() { filament_menu.stat_temp = TEXT_VALUE; + media_select_menu.title = MEDIA_SELECT_TITLE_EN; + media_select_menu.sd_disk = SD_CARD_TITLE_EN; + media_select_menu.usb_disk = USB_DRIVE_TITLE_EN; + machine_menu.key_0 = KEYBOARD_KEY0_EN; machine_menu.key_1 = KEYBOARD_KEY1_EN; machine_menu.key_2 = KEYBOARD_KEY2_EN; diff --git a/Marlin/src/lcd/extui/lib/mks_ui/tft_multi_language.h b/Marlin/src/lcd/extui/lib/mks_ui/tft_multi_language.h index 61e3524c58..79faad74e2 100644 --- a/Marlin/src/lcd/extui/lib/mks_ui/tft_multi_language.h +++ b/Marlin/src/lcd/extui/lib/mks_ui/tft_multi_language.h @@ -706,6 +706,14 @@ typedef struct tool_menu_disp { extern tool_menu_def tool_menu; +typedef struct media_select_menu_disp { + const char *title; + const char *sd_disk; + const char *usb_disk; +} media_select_menu_def; + +extern media_select_menu_def media_select_menu; + typedef struct MachinePara_menu_disp { const char *title; const char *MachineSetting; diff --git a/Marlin/src/lcd/extui/lib/mks_ui/wifi_module.cpp b/Marlin/src/lcd/extui/lib/mks_ui/wifi_module.cpp index 6c2afeafd3..1162f7a228 100644 --- a/Marlin/src/lcd/extui/lib/mks_ui/wifi_module.cpp +++ b/Marlin/src/lcd/extui/lib/mks_ui/wifi_module.cpp @@ -1142,7 +1142,7 @@ static void wifi_list_msg_handle(uint8_t * msg, uint16_t msgLen) { int8_t valid_name_num; if (msgLen <= 0) return; - if (disp_state == KEY_BOARD_UI) return; + if (disp_state == KEYBOARD_UI) return; wifi_list.getNameNum = msg[0]; diff --git a/Marlin/src/sd/Sd2Card.cpp b/Marlin/src/sd/Sd2Card.cpp index 28049c7e7e..3e714fe9fe 100644 --- a/Marlin/src/sd/Sd2Card.cpp +++ b/Marlin/src/sd/Sd2Card.cpp @@ -30,7 +30,7 @@ #include "../inc/MarlinConfig.h" -#if ENABLED(SDSUPPORT) && NONE(USB_FLASH_DRIVE_SUPPORT, SDIO_SUPPORT) +#if NEED_SD2CARD_SPI /* Enable FAST CRC computations - You can trade speed for FLASH space if * needed by disabling the following define */ @@ -88,7 +88,7 @@ #endif // Send command and return error code. Return zero for OK -uint8_t Sd2Card::cardCommand(const uint8_t cmd, const uint32_t arg) { +uint8_t DiskIODriver_SPI_SD::cardCommand(const uint8_t cmd, const uint32_t arg) { // Select card chipSelect(); @@ -133,7 +133,7 @@ uint8_t Sd2Card::cardCommand(const uint8_t cmd, const uint32_t arg) { * \return The number of 512 byte data blocks in the card * or zero if an error occurs. */ -uint32_t Sd2Card::cardSize() { +uint32_t DiskIODriver_SPI_SD::cardSize() { csd_t csd; if (!readCSD(&csd)) return 0; if (csd.v1.csd_ver == 0) { @@ -155,12 +155,12 @@ uint32_t Sd2Card::cardSize() { } } -void Sd2Card::chipDeselect() { +void DiskIODriver_SPI_SD::chipDeselect() { extDigitalWrite(chipSelectPin_, HIGH); spiSend(0xFF); // Ensure MISO goes high impedance } -void Sd2Card::chipSelect() { +void DiskIODriver_SPI_SD::chipSelect() { spiInit(spiRate_); extDigitalWrite(chipSelectPin_, LOW); } @@ -178,7 +178,7 @@ void Sd2Card::chipSelect() { * * \return true for success, false for failure. */ -bool Sd2Card::erase(uint32_t firstBlock, uint32_t lastBlock) { +bool DiskIODriver_SPI_SD::erase(uint32_t firstBlock, uint32_t lastBlock) { if (ENABLED(SDCARD_READONLY)) return false; csd_t csd; @@ -216,7 +216,7 @@ bool Sd2Card::erase(uint32_t firstBlock, uint32_t lastBlock) { * \return true if single block erase is supported. * false if single block erase is not supported. */ -bool Sd2Card::eraseSingleBlockEnable() { +bool DiskIODriver_SPI_SD::eraseSingleBlockEnable() { csd_t csd; return readCSD(&csd) ? csd.v1.erase_blk_en : false; } @@ -230,7 +230,7 @@ bool Sd2Card::eraseSingleBlockEnable() { * \return true for success, false for failure. * The reason for failure can be determined by calling errorCode() and errorData(). */ -bool Sd2Card::init(const uint8_t sckRateID, const pin_t chipSelectPin) { +bool DiskIODriver_SPI_SD::init(const uint8_t sckRateID, const pin_t chipSelectPin) { #if IS_TEENSY_35_36 || IS_TEENSY_40_41 chipSelectPin_ = BUILTIN_SDCARD; const uint8_t ret = SDHC_CardInit(); @@ -324,10 +324,12 @@ bool Sd2Card::init(const uint8_t sckRateID, const pin_t chipSelectPin) { } chipDeselect(); + ready = true; return setSckRate(sckRateID); FAIL: chipDeselect(); + ready = false; return false; } @@ -338,7 +340,7 @@ bool Sd2Card::init(const uint8_t sckRateID, const pin_t chipSelectPin) { * \param[out] dst Pointer to the location that will receive the data. * \return true for success, false for failure. */ -bool Sd2Card::readBlock(uint32_t blockNumber, uint8_t *dst) { +bool DiskIODriver_SPI_SD::readBlock(uint32_t blockNumber, uint8_t *dst) { #if IS_TEENSY_35_36 || IS_TEENSY_40_41 return 0 == SDHC_CardReadBlock(dst, blockNumber); #endif @@ -378,7 +380,7 @@ bool Sd2Card::readBlock(uint32_t blockNumber, uint8_t *dst) { * * \return true for success, false for failure. */ -bool Sd2Card::readData(uint8_t *dst) { +bool DiskIODriver_SPI_SD::readData(uint8_t *dst) { chipSelect(); return readData(dst, 512); } @@ -445,7 +447,7 @@ bool Sd2Card::readData(uint8_t *dst) { #endif #endif // SD_CHECK_AND_RETRY -bool Sd2Card::readData(uint8_t *dst, const uint16_t count) { +bool DiskIODriver_SPI_SD::readData(uint8_t *dst, const uint16_t count) { bool success = false; const millis_t read_timeout = millis() + SD_READ_TIMEOUT; @@ -477,7 +479,7 @@ bool Sd2Card::readData(uint8_t *dst, const uint16_t count) { } /** read CID or CSR register */ -bool Sd2Card::readRegister(const uint8_t cmd, void *buf) { +bool DiskIODriver_SPI_SD::readRegister(const uint8_t cmd, void *buf) { uint8_t *dst = reinterpret_cast(buf); if (cardCommand(cmd, 0)) { error(SD_CARD_ERROR_READ_REG); @@ -497,7 +499,7 @@ bool Sd2Card::readRegister(const uint8_t cmd, void *buf) { * * \return true for success, false for failure. */ -bool Sd2Card::readStart(uint32_t blockNumber) { +bool DiskIODriver_SPI_SD::readStart(uint32_t blockNumber) { if (type() != SD_CARD_TYPE_SDHC) blockNumber <<= 9; const bool success = !cardCommand(CMD18, blockNumber); @@ -511,7 +513,7 @@ bool Sd2Card::readStart(uint32_t blockNumber) { * * \return true for success, false for failure. */ -bool Sd2Card::readStop() { +bool DiskIODriver_SPI_SD::readStop() { chipSelect(); const bool success = !cardCommand(CMD12, 0); if (!success) error(SD_CARD_ERROR_CMD12); @@ -531,7 +533,7 @@ bool Sd2Card::readStop() { * \return The value one, true, is returned for success and the value zero, * false, is returned for an invalid value of \a sckRateID. */ -bool Sd2Card::setSckRate(const uint8_t sckRateID) { +bool DiskIODriver_SPI_SD::setSckRate(const uint8_t sckRateID) { const bool success = (sckRateID <= 6); if (success) spiRate_ = sckRateID; else error(SD_CARD_ERROR_SCK_RATE); return success; @@ -542,12 +544,14 @@ bool Sd2Card::setSckRate(const uint8_t sckRateID) { * \param[in] timeout_ms Timeout to abort. * \return true for success, false for timeout. */ -bool Sd2Card::waitNotBusy(const millis_t timeout_ms) { +bool DiskIODriver_SPI_SD::waitNotBusy(const millis_t timeout_ms) { const millis_t wait_timeout = millis() + timeout_ms; while (spiRec() != 0xFF) if (ELAPSED(millis(), wait_timeout)) return false; return true; } +void DiskIODriver_SPI_SD::error(const uint8_t code) { errorCode_ = code; } + /** * Write a 512 byte block to an SD card. * @@ -555,7 +559,7 @@ bool Sd2Card::waitNotBusy(const millis_t timeout_ms) { * \param[in] src Pointer to the location of the data to be written. * \return true for success, false for failure. */ -bool Sd2Card::writeBlock(uint32_t blockNumber, const uint8_t *src) { +bool DiskIODriver_SPI_SD::writeBlock(uint32_t blockNumber, const uint8_t *src) { if (ENABLED(SDCARD_READONLY)) return false; #if IS_TEENSY_35_36 || IS_TEENSY_40_41 @@ -586,7 +590,7 @@ bool Sd2Card::writeBlock(uint32_t blockNumber, const uint8_t *src) { * \param[in] src Pointer to the location of the data to be written. * \return true for success, false for failure. */ -bool Sd2Card::writeData(const uint8_t *src) { +bool DiskIODriver_SPI_SD::writeData(const uint8_t *src) { if (ENABLED(SDCARD_READONLY)) return false; bool success = true; @@ -601,7 +605,7 @@ bool Sd2Card::writeData(const uint8_t *src) { } // Send one block of data for write block or write multiple blocks -bool Sd2Card::writeData(const uint8_t token, const uint8_t *src) { +bool DiskIODriver_SPI_SD::writeData(const uint8_t token, const uint8_t *src) { if (ENABLED(SDCARD_READONLY)) return false; const uint16_t crc = TERN(SD_CHECK_AND_RETRY, CRC_CCITT(src, 512), 0xFFFF); @@ -629,7 +633,7 @@ bool Sd2Card::writeData(const uint8_t token, const uint8_t *src) { * * \return true for success, false for failure. */ -bool Sd2Card::writeStart(uint32_t blockNumber, const uint32_t eraseCount) { +bool DiskIODriver_SPI_SD::writeStart(uint32_t blockNumber, const uint32_t eraseCount) { if (ENABLED(SDCARD_READONLY)) return false; bool success = false; @@ -650,7 +654,7 @@ bool Sd2Card::writeStart(uint32_t blockNumber, const uint32_t eraseCount) { * * \return true for success, false for failure. */ -bool Sd2Card::writeStop() { +bool DiskIODriver_SPI_SD::writeStop() { if (ENABLED(SDCARD_READONLY)) return false; bool success = false; @@ -666,4 +670,4 @@ bool Sd2Card::writeStop() { return success; } -#endif // SDSUPPORT +#endif // NEED_SD2CARD_SPI diff --git a/Marlin/src/sd/Sd2Card.h b/Marlin/src/sd/Sd2Card.h index eb7f9bb2ca..e0dce02a02 100644 --- a/Marlin/src/sd/Sd2Card.h +++ b/Marlin/src/sd/Sd2Card.h @@ -35,47 +35,50 @@ #include "SdFatConfig.h" #include "SdInfo.h" +#include "disk_io_driver.h" #include -uint16_t const SD_INIT_TIMEOUT = 2000, // init timeout ms - SD_ERASE_TIMEOUT = 10000, // erase timeout ms - SD_READ_TIMEOUT = 300, // read timeout ms - SD_WRITE_TIMEOUT = 600; // write time out ms +uint16_t const SD_INIT_TIMEOUT = 2000, // (ms) Init timeout + SD_ERASE_TIMEOUT = 10000, // (ms) Erase timeout + SD_READ_TIMEOUT = 300, // (ms) Read timeout + SD_WRITE_TIMEOUT = 600; // (ms) Write timeout // SD card errors -uint8_t const SD_CARD_ERROR_CMD0 = 0x01, // timeout error for command CMD0 (initialize card in SPI mode) - SD_CARD_ERROR_CMD8 = 0x02, // CMD8 was not accepted - not a valid SD card - SD_CARD_ERROR_CMD12 = 0x03, // card returned an error response for CMD12 (write stop) - SD_CARD_ERROR_CMD17 = 0x04, // card returned an error response for CMD17 (read block) - SD_CARD_ERROR_CMD18 = 0x05, // card returned an error response for CMD18 (read multiple block) - SD_CARD_ERROR_CMD24 = 0x06, // card returned an error response for CMD24 (write block) - SD_CARD_ERROR_CMD25 = 0x07, // WRITE_MULTIPLE_BLOCKS command failed - SD_CARD_ERROR_CMD58 = 0x08, // card returned an error response for CMD58 (read OCR) - SD_CARD_ERROR_ACMD23 = 0x09, // SET_WR_BLK_ERASE_COUNT failed - SD_CARD_ERROR_ACMD41 = 0x0A, // ACMD41 initialization process timeout - SD_CARD_ERROR_BAD_CSD = 0x0B, // card returned a bad CSR version field - SD_CARD_ERROR_ERASE = 0x0C, // erase block group command failed - SD_CARD_ERROR_ERASE_SINGLE_BLOCK = 0x0D, // card not capable of single block erase - SD_CARD_ERROR_ERASE_TIMEOUT = 0x0E, // Erase sequence timed out - SD_CARD_ERROR_READ = 0x0F, // card returned an error token instead of read data - SD_CARD_ERROR_READ_REG = 0x10, // read CID or CSD failed - SD_CARD_ERROR_READ_TIMEOUT = 0x11, // timeout while waiting for start of read data - SD_CARD_ERROR_STOP_TRAN = 0x12, // card did not accept STOP_TRAN_TOKEN - SD_CARD_ERROR_WRITE = 0x13, // card returned an error token as a response to a write operation - SD_CARD_ERROR_WRITE_BLOCK_ZERO = 0x14, // REMOVE - not used ... attempt to write protected block zero - SD_CARD_ERROR_WRITE_MULTIPLE = 0x15, // card did not go ready for a multiple block write - SD_CARD_ERROR_WRITE_PROGRAMMING = 0x16, // card returned an error to a CMD13 status check after a write - SD_CARD_ERROR_WRITE_TIMEOUT = 0x17, // timeout occurred during write programming - SD_CARD_ERROR_SCK_RATE = 0x18, // incorrect rate selected - SD_CARD_ERROR_INIT_NOT_CALLED = 0x19, // init() not called - // 0x1A is unused now, it was: card returned an error for CMD59 (CRC_ON_OFF) - SD_CARD_ERROR_READ_CRC = 0x1B; // invalid read CRC +typedef enum : uint8_t { + SD_CARD_ERROR_CMD0 = 0x01, // Timeout error for command CMD0 (initialize card in SPI mode) + SD_CARD_ERROR_CMD8 = 0x02, // CMD8 was not accepted - not a valid SD card + SD_CARD_ERROR_CMD12 = 0x03, // Card returned an error response for CMD12 (write stop) + SD_CARD_ERROR_CMD17 = 0x04, // Card returned an error response for CMD17 (read block) + SD_CARD_ERROR_CMD18 = 0x05, // Card returned an error response for CMD18 (read multiple block) + SD_CARD_ERROR_CMD24 = 0x06, // Card returned an error response for CMD24 (write block) + SD_CARD_ERROR_CMD25 = 0x07, // WRITE_MULTIPLE_BLOCKS command failed + SD_CARD_ERROR_CMD58 = 0x08, // Card returned an error response for CMD58 (read OCR) + SD_CARD_ERROR_ACMD23 = 0x09, // SET_WR_BLK_ERASE_COUNT failed + SD_CARD_ERROR_ACMD41 = 0x0A, // ACMD41 initialization process timeout + SD_CARD_ERROR_BAD_CSD = 0x0B, // Card returned a bad CSR version field + SD_CARD_ERROR_ERASE = 0x0C, // Erase block group command failed + SD_CARD_ERROR_ERASE_SINGLE_BLOCK = 0x0D, // Card not capable of single block erase + SD_CARD_ERROR_ERASE_TIMEOUT = 0x0E, // Erase sequence timed out + SD_CARD_ERROR_READ = 0x0F, // Card returned an error token instead of read data + SD_CARD_ERROR_READ_REG = 0x10, // Read CID or CSD failed + SD_CARD_ERROR_READ_TIMEOUT = 0x11, // Timeout while waiting for start of read data + SD_CARD_ERROR_STOP_TRAN = 0x12, // Card did not accept STOP_TRAN_TOKEN + SD_CARD_ERROR_WRITE = 0x13, // Card returned an error token as a response to a write operation + SD_CARD_ERROR_WRITE_BLOCK_ZERO = 0x14, // REMOVE - not used ... attempt to write protected block zero + SD_CARD_ERROR_WRITE_MULTIPLE = 0x15, // Card did not go ready for a multiple block write + SD_CARD_ERROR_WRITE_PROGRAMMING = 0x16, // Card returned an error to a CMD13 status check after a write + SD_CARD_ERROR_WRITE_TIMEOUT = 0x17, // Timeout occurred during write programming + SD_CARD_ERROR_SCK_RATE = 0x18, // Incorrect rate selected + SD_CARD_ERROR_INIT_NOT_CALLED = 0x19, // Init() not called + // 0x1A is unused now, it was: card returned an error for CMD59 (CRC_ON_OFF) + SD_CARD_ERROR_READ_CRC = 0x1B // Invalid read CRC +} sd_error_code_t; // card types -uint8_t const SD_CARD_TYPE_SD1 = 1, // Standard capacity V1 SD card - SD_CARD_TYPE_SD2 = 2, // Standard capacity V2 SD card - SD_CARD_TYPE_SDHC = 3; // High Capacity SD card +uint8_t const SD_CARD_TYPE_SD1 = 1, // Standard capacity V1 SD card + SD_CARD_TYPE_SD2 = 2, // Standard capacity V2 SD card + SD_CARD_TYPE_SDHC = 3; // High Capacity SD card /** * Define SOFTWARE_SPI to use bit-bang SPI @@ -93,12 +96,11 @@ uint8_t const SD_CARD_TYPE_SD1 = 1, // Standard capacity V1 * \class Sd2Card * \brief Raw access to SD and SDHC flash memory cards. */ -class Sd2Card { +class DiskIODriver_SPI_SD : public DiskIODriver { public: - Sd2Card() : errorCode_(SD_CARD_ERROR_INIT_NOT_CALLED), type_(0) {} + DiskIODriver_SPI_SD() : errorCode_(SD_CARD_ERROR_INIT_NOT_CALLED), type_(0) {} - uint32_t cardSize(); bool erase(uint32_t firstBlock, uint32_t lastBlock); bool eraseSingleBlockEnable(); @@ -106,7 +108,7 @@ public: * Set SD error code. * \param[in] code value for error code. */ - inline void error(const uint8_t code) { errorCode_ = code; } + void error(const uint8_t code); /** * \return error code for last error. See Sd2Card.h for a list of error codes. @@ -122,9 +124,15 @@ public: * * \return true for success or false for failure. */ - bool init(const uint8_t sckRateID, const pin_t chipSelectPin); + bool init(const uint8_t sckRateID, const pin_t chipSelectPin) override; - bool readBlock(uint32_t block, uint8_t *dst); + bool setSckRate(const uint8_t sckRateID); + + /** + * Return the card type: SD V1, SD V2 or SDHC + * \return 0 - SD V1, 1 - SD V2, or 3 - SDHC. + */ + int type() const { return type_; } /** * Read a card's CID register. The CID contains card identification @@ -145,24 +153,27 @@ public: * * \return true for success or false for failure. */ - inline bool readCSD(csd_t *csd) { return readRegister(CMD9, csd); } + inline bool readCSD(csd_t *csd) override { return readRegister(CMD9, csd); } - bool readData(uint8_t *dst); - bool readStart(uint32_t blockNumber); - bool readStop(); - bool setSckRate(const uint8_t sckRateID); + bool readData(uint8_t *dst) override; + bool readStart(uint32_t blockNumber) override; + bool readStop() override; - /** - * Return the card type: SD V1, SD V2 or SDHC - * \return 0 - SD V1, 1 - SD V2, or 3 - SDHC. - */ - int type() const {return type_;} - bool writeBlock(uint32_t blockNumber, const uint8_t *src); - bool writeData(const uint8_t *src); - bool writeStart(uint32_t blockNumber, const uint32_t eraseCount); - bool writeStop(); + bool writeData(const uint8_t *src) override; + bool writeStart(const uint32_t blockNumber, const uint32_t eraseCount) override; + bool writeStop() override; + + bool readBlock(uint32_t block, uint8_t *dst) override; + bool writeBlock(uint32_t blockNumber, const uint8_t *src) override; + + uint32_t cardSize() override; + + bool isReady() override { return ready; }; + + void idle() override {} private: + bool ready = false; uint8_t chipSelectPin_, errorCode_, spiRate_, diff --git a/Marlin/src/sd/Sd2Card_sdio.h b/Marlin/src/sd/Sd2Card_sdio.h index 10fb757359..1580344805 100644 --- a/Marlin/src/sd/Sd2Card_sdio.h +++ b/Marlin/src/sd/Sd2Card_sdio.h @@ -23,17 +23,33 @@ #include "../inc/MarlinConfig.h" -#if ENABLED(SDIO_SUPPORT) +#include "SdInfo.h" +#include "disk_io_driver.h" bool SDIO_Init(); bool SDIO_ReadBlock(uint32_t block, uint8_t *dst); bool SDIO_WriteBlock(uint32_t block, const uint8_t *src); -class Sd2Card { +class DiskIODriver_SDIO : public DiskIODriver { public: - bool init(uint8_t sckRateID = 0, uint8_t chipSelectPin = 0) { return SDIO_Init(); } - bool readBlock(uint32_t block, uint8_t *dst) { return SDIO_ReadBlock(block, dst); } - bool writeBlock(uint32_t block, const uint8_t *src) { return SDIO_WriteBlock(block, src); } -}; + bool init(const uint8_t sckRateID=0, const pin_t chipSelectPin=0) override { return SDIO_Init(); } + + bool readCSD(csd_t *csd) override { return false; } + + bool readStart(const uint32_t block) override { return false; } + bool readData(uint8_t *dst) override { return false; } + bool readStop() override { return false; } + + bool writeStart(const uint32_t block, const uint32_t) override { return false; } + bool writeData(const uint8_t *src) override { return false; } + bool writeStop() override { return false; } -#endif // SDIO_SUPPORT + bool readBlock(uint32_t block, uint8_t *dst) override { return SDIO_ReadBlock(block, dst); } + bool writeBlock(uint32_t block, const uint8_t *src) override { return SDIO_WriteBlock(block, src); } + + uint32_t cardSize() override { return 0; } + + bool isReady() override { return true; } + + void idle() override {} +}; diff --git a/Marlin/src/sd/SdFatConfig.h b/Marlin/src/sd/SdFatConfig.h index 13ac3a7487..dfba641295 100644 --- a/Marlin/src/sd/SdFatConfig.h +++ b/Marlin/src/sd/SdFatConfig.h @@ -39,7 +39,7 @@ * * Each card requires about 550 bytes of SRAM so use of a Mega is recommended. */ -#define USE_MULTIPLE_CARDS 0 +#define USE_MULTIPLE_CARDS 0 //TODO? ENABLED(MULTI_VOLUME) /** * Call flush for endl if ENDL_CALLS_FLUSH is nonzero diff --git a/Marlin/src/sd/SdVolume.cpp b/Marlin/src/sd/SdVolume.cpp index 7fcebd640d..1b1fdc5a7c 100644 --- a/Marlin/src/sd/SdVolume.cpp +++ b/Marlin/src/sd/SdVolume.cpp @@ -41,10 +41,10 @@ // raw block cache uint32_t SdVolume::cacheBlockNumber_; // current block number cache_t SdVolume::cacheBuffer_; // 512 byte cache for Sd2Card - Sd2Card* SdVolume::sdCard_; // pointer to SD card object + DiskIODriver *SdVolume::sdCard_; // pointer to SD card object bool SdVolume::cacheDirty_; // cacheFlush() will write block if true uint32_t SdVolume::cacheMirrorBlock_; // mirror block for second FAT -#endif // USE_MULTIPLE_CARDS +#endif // find a contiguous group of clusters bool SdVolume::allocContiguous(uint32_t count, uint32_t *curCluster) { @@ -326,7 +326,7 @@ int32_t SdVolume::freeClusterCount() { * Reasons for failure include not finding a valid partition, not finding a valid * FAT file system in the specified partition or an I/O error. */ -bool SdVolume::init(Sd2Card* dev, uint8_t part) { +bool SdVolume::init(DiskIODriver* dev, uint8_t part) { uint32_t totalBlocks, volumeStartBlock = 0; fat32_boot_t *fbs; diff --git a/Marlin/src/sd/SdVolume.h b/Marlin/src/sd/SdVolume.h index c2eaf0bd13..b8e70ca9d7 100644 --- a/Marlin/src/sd/SdVolume.h +++ b/Marlin/src/sd/SdVolume.h @@ -36,9 +36,11 @@ #if ENABLED(USB_FLASH_DRIVE_SUPPORT) #include "usb_flashdrive/Sd2Card_FlashDrive.h" -#elif ENABLED(SDIO_SUPPORT) +#endif + +#if NEED_SD2CARD_SDIO #include "Sd2Card_sdio.h" -#else +#elif NEED_SD2CARD_SPI #include "Sd2Card.h" #endif @@ -47,6 +49,7 @@ //============================================================================== // SdVolume class + /** * \brief Cache for an SD data block */ @@ -84,14 +87,14 @@ class SdVolume { * Initialize a FAT volume. Try partition one first then try super * floppy format. * - * \param[in] dev The Sd2Card where the volume is located. + * \param[in] dev The DiskIODriver where the volume is located. * * \return true for success, false for failure. * Reasons for failure include not finding a valid partition, not finding * a valid FAT file system or an I/O error. */ - bool init(Sd2Card *dev) { return init(dev, 1) ? true : init(dev, 0); } - bool init(Sd2Card *dev, uint8_t part); + bool init(DiskIODriver *dev) { return init(dev, 1) || init(dev, 0); } + bool init(DiskIODriver *dev, uint8_t part); // inline functions that return volume info uint8_t blocksPerCluster() const { return blocksPerCluster_; } //> \return The volume's cluster size in blocks. @@ -112,10 +115,10 @@ class SdVolume { uint32_t rootDirStart() const { return rootDirStart_; } /** - * Sd2Card object for this volume - * \return pointer to Sd2Card object. + * DiskIODriver object for this volume + * \return pointer to DiskIODriver object. */ - Sd2Card* sdCard() { return sdCard_; } + DiskIODriver* sdCard() { return sdCard_; } /** * Debug access to FAT table @@ -138,13 +141,13 @@ class SdVolume { #if USE_MULTIPLE_CARDS cache_t cacheBuffer_; // 512 byte cache for device blocks uint32_t cacheBlockNumber_; // Logical number of block in the cache - Sd2Card *sdCard_; // Sd2Card object for cache + DiskIODriver *sdCard_; // DiskIODriver object for cache bool cacheDirty_; // cacheFlush() will write block if true uint32_t cacheMirrorBlock_; // block number for mirror FAT #else static cache_t cacheBuffer_; // 512 byte cache for device blocks static uint32_t cacheBlockNumber_; // Logical number of block in the cache - static Sd2Card *sdCard_; // Sd2Card object for cache + static DiskIODriver *sdCard_; // DiskIODriver object for cache static bool cacheDirty_; // cacheFlush() will write block if true static uint32_t cacheMirrorBlock_; // block number for mirror FAT #endif diff --git a/Marlin/src/sd/cardreader.cpp b/Marlin/src/sd/cardreader.cpp index 07a57cc658..a54884bec1 100644 --- a/Marlin/src/sd/cardreader.cpp +++ b/Marlin/src/sd/cardreader.cpp @@ -120,7 +120,16 @@ uint8_t CardReader::workDirDepth; #endif // SDCARD_SORT_ALPHA -Sd2Card CardReader::sd2card; +#if SHARED_VOLUME_IS(USB_FLASH_DRIVE) || ENABLED(USB_FLASH_DRIVE_SUPPORT) + DiskIODriver_USBFlash CardReader::media_usbFlashDrive; +#endif +#if NEED_SD2CARD_SDIO + DiskIODriver_SDIO CardReader::media_sdio; +#elif NEED_SD2CARD_SPI + DiskIODriver_SPI_SD CardReader::media_sd_spi; +#endif + +DiskIODriver* CardReader::driver = nullptr; SdVolume CardReader::volume; SdFile CardReader::file; @@ -133,6 +142,16 @@ SdFile CardReader::file; uint32_t CardReader::filesize, CardReader::sdpos; CardReader::CardReader() { + changeMedia(& + #if SHARED_VOLUME_IS(SD_ONBOARD) + media_sd_spi + #elif SHARED_VOLUME_IS(USB_FLASH_DRIVE) || ENABLED(USB_FLASH_DRIVE_SUPPORT) + media_usbFlashDrive + #else + TERN(SDIO_SUPPORT, media_sdio, media_sd_spi) + #endif + ); + #if ENABLED(SDCARD_SORT_ALPHA) sort_count = 0; #if ENABLED(SDSORT_GCODE) @@ -383,12 +402,12 @@ void CardReader::mount() { flag.mounted = false; if (root.isOpen()) root.close(); - if (!sd2card.init(SD_SPI_SPEED, SDSS) + if (!driver->init(SD_SPI_SPEED, SDSS) #if defined(LCD_SDSS) && (LCD_SDSS != SDSS) - && !sd2card.init(SD_SPI_SPEED, LCD_SDSS) + && !driver->init(SD_SPI_SPEED, LCD_SDSS) #endif ) SERIAL_ECHO_MSG(STR_SD_INIT_FAIL); - else if (!volume.init(&sd2card)) + else if (!volume.init(driver)) SERIAL_ERROR_MSG(STR_SD_VOL_INIT_FAIL); else if (!root.openRoot(&volume)) SERIAL_ERROR_MSG(STR_SD_OPENROOT_FAIL); diff --git a/Marlin/src/sd/cardreader.h b/Marlin/src/sd/cardreader.h index f1002e1dab..5fdd1222ae 100644 --- a/Marlin/src/sd/cardreader.h +++ b/Marlin/src/sd/cardreader.h @@ -42,6 +42,29 @@ extern const char M23_STR[], M24_STR[]; #define MAXPATHNAMELENGTH (1 + (MAXDIRNAMELENGTH + 1) * (MAX_DIR_DEPTH) + 1 + FILENAME_LENGTH) // "/" + N * ("ADIRNAME/") + "filename.ext" #include "SdFile.h" +#include "disk_io_driver.h" + +#if ENABLED(USB_FLASH_DRIVE_SUPPORT) + #include "usb_flashdrive/Sd2Card_FlashDrive.h" +#endif + +#if NEED_SD2CARD_SDIO + #include "Sd2Card_sdio.h" +#elif NEED_SD2CARD_SPI + #include "Sd2Card.h" +#endif + +#if ENABLED(MULTI_VOLUME) + #define SV_SD_ONBOARD 1 + #define SV_USB_FLASH_DRIVE 2 + #define _VOLUME_ID(N) _CAT(SV_, N) + #define SHARED_VOLUME_IS(N) (DEFAULT_SHARED_VOLUME == _VOLUME_ID(N)) + #if !SHARED_VOLUME_IS(SD_ONBOARD) && !SHARED_VOLUME_IS(USB_FLASH_DRIVE) + #error "DEFAULT_SHARED_VOLUME must be either SD_ONBOARD or USB_FLASH_DRIVE." + #endif +#else + #define SHARED_VOLUME_IS(...) 0 +#endif typedef struct { bool saving:1, @@ -80,6 +103,8 @@ public: CardReader(); + static void changeMedia(DiskIODriver *_driver) { driver = _driver; } + static SdFile getroot() { return root; } static void mount(); @@ -171,7 +196,8 @@ public: static inline int16_t read(void *buf, uint16_t nbyte) { return file.isOpen() ? file.read(buf, nbyte) : -1; } static inline int16_t write(void *buf, uint16_t nbyte) { return file.isOpen() ? file.write(buf, nbyte) : -1; } - static Sd2Card& getSd2Card() { return sd2card; } + // TODO: rename to diskIODriver() + static DiskIODriver* diskIODriver() { return driver; } #if ENABLED(AUTO_REPORT_SD_STATUS) // @@ -181,6 +207,15 @@ public: static AutoReporter auto_reporter; #endif + #if SHARED_VOLUME_IS(USB_FLASH_DRIVE) || ENABLED(USB_FLASH_DRIVE_SUPPORT) + static DiskIODriver_USBFlash media_usbFlashDrive; + #endif + #if NEED_SD2CARD_SDIO + static DiskIODriver_SDIO media_sdio; + #elif NEED_SD2CARD_SPI + static DiskIODriver_SPI_SD media_sd_spi; + #endif + private: // // Working directory and parents @@ -236,7 +271,7 @@ private: #if ENABLED(SDSORT_DYNAMIC_RAM) static uint8_t *isDir; #elif ENABLED(SDSORT_CACHE_NAMES) || DISABLED(SDSORT_USES_STACK) - static uint8_t isDir[(SDSORT_LIMIT+7)>>3]; + static uint8_t isDir[(SDSORT_LIMIT + 7) >> 3]; #endif #endif @@ -244,7 +279,7 @@ private: #endif // SDCARD_SORT_ALPHA - static Sd2Card sd2card; + static DiskIODriver *driver; static SdVolume volume; static SdFile file; @@ -275,7 +310,7 @@ private: }; #if ENABLED(USB_FLASH_DRIVE_SUPPORT) - #define IS_SD_INSERTED() Sd2Card::isInserted() + #define IS_SD_INSERTED() DiskIODriver_USBFlash::isInserted() #elif PIN_EXISTS(SD_DETECT) #define IS_SD_INSERTED() (READ(SD_DETECT_PIN) == SD_DETECT_STATE) #else diff --git a/Marlin/src/sd/disk_io_driver.h b/Marlin/src/sd/disk_io_driver.h new file mode 100644 index 0000000000..73c12efcfa --- /dev/null +++ b/Marlin/src/sd/disk_io_driver.h @@ -0,0 +1,67 @@ +/** + * Marlin 3D Printer Firmware + * Copyright (c) 2021 MarlinFirmware [https://github.com/MarlinFirmware/Marlin] + * + * Based on Sprinter and grbl. + * Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ +#pragma once + +#include + +/** + * DiskIO Interace + * + * Interface for low level disk io + */ +class DiskIODriver { +public: + /** + * Initialize an SD flash memory card with default clock rate and chip + * select pin. See sd2Card::init(uint8_t sckRateID, uint8_t chipSelectPin). + * + * \return true for success or false for failure. + */ + virtual bool init(const uint8_t sckRateID, const pin_t chipSelectPin) = 0; //TODO: only for SPI + + /** + * Read a card's CSD register. The CSD contains Card-Specific Data that + * provides information regarding access to the card's contents. + * + * \param[out] csd pointer to area for returned data. + * + * \return true for success or false for failure. + */ + virtual bool readCSD(csd_t* csd) = 0; + + virtual bool readStart(const uint32_t block) = 0; + virtual bool readData(uint8_t* dst) = 0; + virtual bool readStop() = 0; + + virtual bool writeStart(const uint32_t block, const uint32_t) = 0; + virtual bool writeData(const uint8_t* src) = 0; + virtual bool writeStop() = 0; + + virtual bool readBlock(uint32_t block, uint8_t* dst) = 0; + virtual bool writeBlock(uint32_t blockNumber, const uint8_t* src) = 0; + + virtual uint32_t cardSize() = 0; + + virtual bool isReady() = 0; + + virtual void idle() = 0; +}; diff --git a/Marlin/src/sd/usb_flashdrive/Sd2Card_FlashDrive.cpp b/Marlin/src/sd/usb_flashdrive/Sd2Card_FlashDrive.cpp index dc9efcb672..1975418415 100644 --- a/Marlin/src/sd/usb_flashdrive/Sd2Card_FlashDrive.cpp +++ b/Marlin/src/sd/usb_flashdrive/Sd2Card_FlashDrive.cpp @@ -121,7 +121,7 @@ static enum { uint32_t lun0_capacity; #endif -bool Sd2Card::usbStartup() { +bool DiskIODriver_USBFlash::usbStartup() { if (state <= DO_STARTUP) { SERIAL_ECHOPGM("Starting USB host..."); if (!UHS_START) { @@ -147,7 +147,7 @@ bool Sd2Card::usbStartup() { // the USB library to monitor for such events. This function also takes care // of initializing the USB library for the first time. -void Sd2Card::idle() { +void DiskIODriver_USBFlash::idle() { usb.Task(); const uint8_t task_state = usb.getUsbTaskState(); @@ -258,16 +258,16 @@ void Sd2Card::idle() { // Marlin calls this function to check whether an USB drive is inserted. // This is equivalent to polling the SD_DETECT when using SD cards. -bool Sd2Card::isInserted() { +bool DiskIODriver_USBFlash::isInserted() { return state == MEDIA_READY; } -bool Sd2Card::isReady() { - return state > DO_STARTUP; +bool DiskIODriver_USBFlash::isReady() { + return state > DO_STARTUP && usb.getUsbTaskState() == UHS_STATE(RUNNING); } // Marlin calls this to initialize an SD card once it is inserted. -bool Sd2Card::init(const uint8_t, const pin_t) { +bool DiskIODriver_USBFlash::init(const uint8_t, const pin_t) { if (!isInserted()) return false; #if USB_DEBUG >= 1 @@ -286,7 +286,7 @@ bool Sd2Card::init(const uint8_t, const pin_t) { } // Returns the capacity of the card in blocks. -uint32_t Sd2Card::cardSize() { +uint32_t DiskIODriver_USBFlash::cardSize() { if (!isInserted()) return false; #if USB_DEBUG < 3 const uint32_t @@ -295,7 +295,7 @@ uint32_t Sd2Card::cardSize() { return lun0_capacity; } -bool Sd2Card::readBlock(uint32_t block, uint8_t *dst) { +bool DiskIODriver_USBFlash::readBlock(uint32_t block, uint8_t *dst) { if (!isInserted()) return false; #if USB_DEBUG >= 3 if (block >= lun0_capacity) { @@ -309,7 +309,7 @@ bool Sd2Card::readBlock(uint32_t block, uint8_t *dst) { return bulk.Read(0, block, 512, 1, dst) == 0; } -bool Sd2Card::writeBlock(uint32_t block, const uint8_t *src) { +bool DiskIODriver_USBFlash::writeBlock(uint32_t block, const uint8_t *src) { if (!isInserted()) return false; #if USB_DEBUG >= 3 if (block >= lun0_capacity) { diff --git a/Marlin/src/sd/usb_flashdrive/Sd2Card_FlashDrive.h b/Marlin/src/sd/usb_flashdrive/Sd2Card_FlashDrive.h index 320678d091..3390bc51be 100644 --- a/Marlin/src/sd/usb_flashdrive/Sd2Card_FlashDrive.h +++ b/Marlin/src/sd/usb_flashdrive/Sd2Card_FlashDrive.h @@ -27,6 +27,7 @@ */ #include "../SdFatConfig.h" #include "../SdInfo.h" +#include "../disk_io_driver.h" #if DISABLED(USE_OTG_USB_HOST) /** @@ -46,7 +47,7 @@ #endif #endif -class Sd2Card { +class DiskIODriver_USBFlash : public DiskIODriver { private: uint32_t pos; @@ -54,25 +55,26 @@ class Sd2Card { public: static bool usbStartup(); + static bool isInserted(); - bool init(const uint8_t sckRateID=0, const pin_t chipSelectPin=TERN(USE_OTG_USB_HOST, 0, SD_CHIP_SELECT_PIN)); + bool init(const uint8_t sckRateID=0, const pin_t chipSelectPin=TERN(USE_OTG_USB_HOST, 0, SD_CHIP_SELECT_PIN)) override; - static void idle(); + inline bool readCSD(csd_t*) override { return true; } - inline bool readStart(const uint32_t block) { pos = block; return isReady(); } - inline bool readData(uint8_t *dst) { return readBlock(pos++, dst); } - inline bool readStop() const { return true; } + inline bool readStart(const uint32_t block) override { pos = block; return isReady(); } + inline bool readData(uint8_t *dst) override { return readBlock(pos++, dst); } + inline bool readStop() override { return true; } - inline bool writeStart(const uint32_t block, const uint32_t) { pos = block; return isReady(); } - inline bool writeData(uint8_t *src) { return writeBlock(pos++, src); } - inline bool writeStop() const { return true; } + inline bool writeStart(const uint32_t block, const uint32_t) override { pos = block; return isReady(); } + inline bool writeData(const uint8_t *src) override { return writeBlock(pos++, src); } + inline bool writeStop() override { return true; } - bool readBlock(uint32_t block, uint8_t *dst); - bool writeBlock(uint32_t blockNumber, const uint8_t *src); + bool readBlock(uint32_t block, uint8_t *dst) override; + bool writeBlock(uint32_t blockNumber, const uint8_t *src) override; - bool readCSD(csd_t*) { return true; } + uint32_t cardSize() override; - uint32_t cardSize(); - static bool isInserted(); - bool isReady(); + bool isReady() override; + + void idle() override; };