Explorar el Código

Rebranding to BlueSCSI

List of commits and contributions prior to this commit from BlueSCSI that were merged into ZuluSCSI where we were only listed as co-authors instead of the original authors, skewing github stats as co-authors are not counted. In BlueSCSI any commits we pulled over preserved the author to the best of our ability. There may be more BlueSCSI contributions but there's only so much time to dig through commits.

BlueSCSI v2 Platform configuration - Androda
d4c9a944c40e0490f076c1f78d866e621078c4d6
Original Commit:
    https://github.com/BlueSCSI/BlueSCSI-v2/commit/cc2c12834cc15459ea38e43fe68b86aac65dcd4d

d4c9a944c40e0490f076c1f78d866e621078c4d6
Prototype 1 working - Androda
Original commit:
    https://github.com/BlueSCSI/BlueSCSI-v2/commit/8971584485c42

Debuglog Mask - Eric Helgeson
1d04ab981a7abbfd45e360aa716ee38dfd435736
Original commit:
    https://github.com/BlueSCSI/BlueSCSI-v2/commit/27906736962ffbb52da9b5aa8473fefa86a5b231

Zip drive support - jokker & Eric Helgeson
9dbeed43d2ad45c60cddc30082e715c87004b5c6
Original commit:
    https://github.com/BlueSCSI/BlueSCSI-v2/commit/4c8b6a96e81a8d555c9cdb14ab911d07ba187336
    https://github.com/BlueSCSI/BlueSCSI-v2/commit/b4975175a82518cc37cf8d8bded19fe27d52829f

Fix SCSI-1 check initiator - Androda
1e0aa9641a11806eda27bf4008755c84096e0ef3
Original commit:
    https://github.com/BlueSCSI/BlueSCSI-v2/commit/5c5833adb213979ccead5595a3af51cec6e74aa0

Initiator improvements - Eric Helgeson
57210a6d22a8fe0e9787a9ded2f6ad548704933e
Original commit:
    https://github.com/BlueSCSI/BlueSCSI-v2/commit/c80f3c0b72a6924eda2b5488bba7f8c81b395405
    https://github.com/BlueSCSI/BlueSCSI-v2/commit/d926dd71669056f950a5dd61c8360d1c21c9af15
    https://github.com/BlueSCSI/BlueSCSI-v2/commit/45f8e7392589bbc0a02cba769078b9ae970fe91c
    https://github.com/BlueSCSI/BlueSCSI-v2/commit/b4cf5b7bc996e2b90d2d62dc01e48154407454d5
    https://github.com/BlueSCSI/BlueSCSI-v2/commit/71ce1dab162290f858ff4fc491ab51da88d8ac36
    https://github.com/BlueSCSI/BlueSCSI-v2/commit/908af73f3794e3b88dc934239f5a2fb6d10f6a0a
    https://github.com/BlueSCSI/BlueSCSI-v2/commit/e1a173484e62f3b781aab9f00696a09567f3f517
    https://github.com/BlueSCSI/BlueSCSI-v2/commit/5860b48e776c5a2d5f695681d5c80a517951eb22
    https://github.com/BlueSCSI/BlueSCSI-v2/commit/7b97b49009c37c4db6aebc397ad0f664111d5305
    https://github.com/BlueSCSI/BlueSCSI-v2/commit/164ab5ede0605f823d1a94e46308969c6a317b1f

BlueSCSI Toolbox - Eric Helgeson
c5df0f9085ce6016227ca657a98b3f7500a60a39
Original commits:
    https://github.com/BlueSCSI/BlueSCSI-v2/commit/0052195afbb71e6bc222efdefce04341b30046c8
    https://github.com/BlueSCSI/BlueSCSI-v2/commit/13901a66faad1cb9d8f9c35bdc638462e3603103
    https://github.com/BlueSCSI/BlueSCSI-v2/commit/e8f7dc185dd3b4dc63a386c92bb420ea81c70954
    https://github.com/BlueSCSI/BlueSCSI-v2/commit/de182e26f9aa95b1b9ef58b7465358fb87a4c4cf
    https://github.com/BlueSCSI/BlueSCSI-v2/commit/4522d1f3c08e234dd7615aa4a812b61de68fb6b4
    https://github.com/BlueSCSI/BlueSCSI-v2/commit/a8d7d58cead1381310320581714ba949ca04d30b
    https://github.com/BlueSCSI/BlueSCSI-v2/commit/5e2300355134ba38b0ceb179b8f9604b9875b27a
    https://github.com/BlueSCSI/BlueSCSI-v2/commit/18736bcb0b75c7202f9bfaa15ea7b1c4d9987a45
    https://github.com/BlueSCSI/BlueSCSI-v2/commit/bd6e3b6181756f72c9eee2a680f49b37d452fe30
    https://github.com/BlueSCSI/BlueSCSI-v2/commit/1c094d58311ff646228e226306a61066cbb6ed66
    https://github.com/BlueSCSI/BlueSCSI-v2/commit/96a552bab66d56afea7b7147e084fdaad0fa3740
    https://github.com/BlueSCSI/BlueSCSI-v2/commit/58a3c7134225beb21efa3bb8a8aee3752f6f8a74
    https://github.com/BlueSCSI/BlueSCSI-v2/commit/eec90b9ef328fe47a4a7188f38dce90f95c5a6ef

Add X68000 quirk for odd 0x00 CBD opcode -  Andrea Ottaviani
3949d3e58aa6a7e054395de326019779203ebbdf
Original commit:
    https://github.com/BlueSCSI/BlueSCSI-v2/pull/102
    https://github.com/BlueSCSI/BlueSCSI-v2/commit/9d508478c08db32564657178eee3c565c09a762d
    https://github.com/BlueSCSI/BlueSCSI-v2/commit/0652d420ad8f846030b66a2ef22e7b381d0c3fe4
    https://github.com/BlueSCSI/BlueSCSI-v2/commit/0a40459fe2fa88e6fe5e2c366a00e1b27393967a
    https://github.com/BlueSCSI/BlueSCSI-v2/commit/1465e0ad65fceefdfee4a73a6ec4e9936b0802fb
    https://github.com/BlueSCSI/BlueSCSI-v2/commit/d8c5ab10ee655c5a8e8ebd4cf7dcaf907fd1d2eb
    https://github.com/BlueSCSI/BlueSCSI-v2/commit/791dacbd61f8be34ffc9afa3788dc42b3c08d324

Apple Floppy SCSI Strings - Eric Helgeson
340e9651683b98c21a34a83f1b872955fb212563
Original commit:
    https://github.com/BlueSCSI/BlueSCSI-v2/commit/58a736ec30ba1672a00755e9e764c7f54f4610c5

Initiator sense request from debug to standard log - Androda
9d115f0bd332ccba701159e6900dd39e88864f92
Original commit:
    https://github.com/BlueSCSI/BlueSCSI-v2/commit/980fb0b3f331d19eb6ffac422ba4411957ab1223

MegaSTE & X68000 Presets - Eric Helgeson
a1fa285afd9d5d523307035d237a8509f582bab3
Original commit:
    https://github.com/BlueSCSI/BlueSCSI-v2/commit/74236c8483c9cc0c1c482ac556c1024660d5d1bf
    https://github.com/BlueSCSI/BlueSCSI-v2/commit/be6d1adbbd64fb7de436efdb82d0d95c823124e8

DaynaPORT WiFi emulation - jcs & androda
8e46b47d10dd972bf0e85c1fa29ddecef1994682
6ed0e955d43fa6fe3ba0670c62bd651dd57198af
Original commit:
    https://github.com/BlueSCSI/BlueSCSI-v2/pull/59
    https://github.com/BlueSCSI/BlueSCSI-v2/commit/f895a6da89521d2cf3bc34a95a0b4dbba7612813
    https://github.com/BlueSCSI/BlueSCSI-v2/commit/d99b40ae60c68caab7f50548ad31783143d7eecc
    https://github.com/BlueSCSI/BlueSCSI-v2/commit/f810a217aae406bbb6ae94a8d19b315fb19bbc3a
    https://github.com/BlueSCSI/BlueSCSI-v2/commit/79ccf7ed9780cf2c3c3df70720438760e706531b
    https://github.com/BlueSCSI/BlueSCSI-v2/commit/30ce435f09f4149d11c33bac8158bdfa860aebaa
    https://github.com/BlueSCSI/BlueSCSI-v2/commit/7c0fde63c4e93f82e7398a3fa7309013cd290443
    https://github.com/BlueSCSI/BlueSCSI-v2/commit/8842560613a807ed620cb5fa2c9b078a5c0e93f2
    https://github.com/BlueSCSI/BlueSCSI-v2/commit/85f46990c1dfead37439e35ecba8842c8c53fba9
    https://github.com/BlueSCSI/BlueSCSI-v2/commit/487374ba3229d345f2541208f9904dddab0af3b7
    https://github.com/BlueSCSI/BlueSCSI-v2/commit/04b1e96065d74d46c13a6c488674392be79b4576
    https://github.com/BlueSCSI/BlueSCSI-v2/commit/02eaf2f4fb26c8a7a1bab7f2ab9ae4cbe1c831c1
    https://github.com/BlueSCSI/BlueSCSI-v2/commit/858a45e21197748097235e1c00c621ef2f377e6d
    https://github.com/BlueSCSI/BlueSCSI-v2/commit/e3aac81be0d143d21371a55c53c30a7e25695c75
    https://github.com/BlueSCSI/BlueSCSI-v2/commit/9fece065e47d81e7a975615c10e2b8cbf7cd38b6
    https://github.com/BlueSCSI/BlueSCSI-v2/commit/59f66653a4475b51df10a2de231518556072de69
    https://github.com/BlueSCSI/BlueSCSI-v2/commit/f5dce26d122c0490691d843a509d727e7b5b1ddc
    https://github.com/BlueSCSI/BlueSCSI-v2/commit/003b0dac804ff124cd9cad9bbfdc1c6b24ad9edf

Skip image if larger than max file size - Eric Helgeson
567d2ba98d54e71d12c9ac8096facfc701fcc205
Original commit:
    https://github.com/BlueSCSI/BlueSCSI-v2/commit/8e9a3c0bfc2c479901b1c7a5772c0e3c9f4d9ca8

Request stop from target without response - Eric Helgeson
97c14fb4685c5307b59345de4c89388ac758f09c
Original commit:
    https://github.com/BlueSCSI/BlueSCSI-v2/commit/6743cb6e3deef3794fcd2fcf01ff4e82f47be3b5

Skip imaging target if not enough free space - Eric Helgeson
e3c9f69e289d40742cb98793b7b1efbec09bf974
Original commit:
    https://github.com/BlueSCSI/BlueSCSI-v2/commit/586207e80c9c28b5c1b8d251ab30c1355242930c

Add Mac sanity checks - Eric Helgeson
8677a96aa0a37a520b0f9f8d175767ec006f1e03
Original commit:
    https://github.com/BlueSCSI/BlueSCSI-v2/commit/cc1ff5f4d03ce976d01ead09cee1106ce0acae08
    https://github.com/BlueSCSI/BlueSCSI-v2/commit/d00ebe016b8c7ef4777c31cef9cd002043de7d46

Add default directories - Eric Helgeson
16be0e0bd313ea960a3bf7bc859c5614804c5b41
Original Commit
    https://github.com/BlueSCSI/BlueSCSI-v2/commit/43221ad03258eeaa8e963b3cec272a493bde46b4

Changes to DynaPORT to allow the amiga A590/A2091 and GVP scsi
interfaces to use it - Rob Smith
ff41bbb1091f32951196a099649da7ec3e73e1cc
Original Commit
    https://github.com/BlueSCSI/BlueSCSI-v2/pull/189/commits/d8fc0b17ee1f8fb591587e39b872a606fd24eead
Eric Helgeson hace 6 meses
padre
commit
9825efaf9c
Se han modificado 100 ficheros con 1063 adiciones y 8738 borrados
  1. 0 53
      .github/workflows/analyze_crashlogs.yml
  2. 0 72
      .github/workflows/firmware_build.yml
  3. 1 0
      .gitignore
  4. 668 19
      LICENSE
  5. 0 3
      Performance.md
  6. 36 0
      README.adoc
  7. 0 226
      README.md
  8. 2 2
      boards/rpipico.json
  9. 2 2
      boards/rpipico2.json
  10. 2 2
      boards/rpipico2w.json
  11. 2 2
      boards/rpipicow.json
  12. 0 55
      boards/zuluscsi_blaster.json
  13. 0 57
      boards/zuluscsi_rp2040.json
  14. BIN
      docs/ZuluSCSI_RP2040_buttons.jpg
  15. BIN
      docs/ZuluSCSI_RP2040_compact_buttons.jpg
  16. BIN
      docs/ZuluSCSI_v1_1_buttons.jpg
  17. 0 8
      greenpak/README.md
  18. 0 647
      greenpak/SCSI_Accelerator_SLG46824.gp6
  19. 0 17
      greenpak/SCSI_Accelerator_SLG46824.hex
  20. BIN
      greenpak/SCSI_Accelerator_SLG46824.png
  21. 2 2
      lib/BlueI2S/BlueI2S.cpp
  22. 0 0
      lib/BlueI2S/BlueI2S.h
  23. 0 0
      lib/BlueI2S/blue_pio_i2s.pio
  24. 0 0
      lib/BlueI2S/blue_pio_i2s.pio.h
  25. 29 29
      lib/BlueSCSI_platform_RP2MCU/BlueSCSI_platform.cpp
  26. 17 17
      lib/BlueSCSI_platform_RP2MCU/BlueSCSI_platform.h
  27. 13 13
      lib/BlueSCSI_platform_RP2MCU/BlueSCSI_platform_config.h
  28. 0 0
      lib/BlueSCSI_platform_RP2MCU/BlueSCSI_platform_gpio_BS2.h
  29. 9 9
      lib/BlueSCSI_platform_RP2MCU/BlueSCSI_platform_msc.cpp
  30. 0 0
      lib/BlueSCSI_platform_RP2MCU/BlueSCSI_platform_msc.h
  31. 6 6
      lib/BlueSCSI_platform_RP2MCU/BlueSCSI_platform_network.cpp
  32. 3 3
      lib/BlueSCSI_platform_RP2MCU/BlueSCSI_platform_network.h
  33. 6 6
      lib/BlueSCSI_platform_RP2MCU/audio_i2s.cpp
  34. 0 0
      lib/BlueSCSI_platform_RP2MCU/audio_i2s.h
  35. 4 4
      lib/BlueSCSI_platform_RP2MCU/audio_spdif.cpp
  36. 0 0
      lib/BlueSCSI_platform_RP2MCU/audio_spdif.h
  37. 0 0
      lib/BlueSCSI_platform_RP2MCU/bsp.h
  38. 129 0
      lib/BlueSCSI_platform_RP2MCU/custom_timings.cpp
  39. 1 1
      lib/BlueSCSI_platform_RP2MCU/custom_timings.h
  40. 14 0
      lib/BlueSCSI_platform_RP2MCU/library.json
  41. 6 6
      lib/BlueSCSI_platform_RP2MCU/program_flash.cpp
  42. 6 6
      lib/BlueSCSI_platform_RP2MCU/rp2040-template.ld
  43. 0 0
      lib/BlueSCSI_platform_RP2MCU/rp2040_btldr.ld
  44. 3 3
      lib/BlueSCSI_platform_RP2MCU/rp23xx-template.ld
  45. 0 0
      lib/BlueSCSI_platform_RP2MCU/rp23xx_btldr.ld
  46. 0 0
      lib/BlueSCSI_platform_RP2MCU/run_pioasm.sh
  47. 1 1
      lib/BlueSCSI_platform_RP2MCU/scsi2sd_time.h
  48. 2 2
      lib/BlueSCSI_platform_RP2MCU/scsi2sd_timings.c
  49. 3 3
      lib/BlueSCSI_platform_RP2MCU/scsiHostPhy.cpp
  50. 0 0
      lib/BlueSCSI_platform_RP2MCU/scsiHostPhy.h
  51. 6 6
      lib/BlueSCSI_platform_RP2MCU/scsiPhy.cpp
  52. 0 0
      lib/BlueSCSI_platform_RP2MCU/scsiPhy.h
  53. 2 2
      lib/BlueSCSI_platform_RP2MCU/scsi_accel_host.cpp
  54. 0 0
      lib/BlueSCSI_platform_RP2MCU/scsi_accel_host.h
  55. 0 0
      lib/BlueSCSI_platform_RP2MCU/scsi_accel_host_RP2MCU.pio
  56. 0 0
      lib/BlueSCSI_platform_RP2MCU/scsi_accel_host_RP2MCU.pio.h
  57. 35 37
      lib/BlueSCSI_platform_RP2MCU/scsi_accel_target.cpp
  58. 0 0
      lib/BlueSCSI_platform_RP2MCU/scsi_accel_target.h
  59. 0 0
      lib/BlueSCSI_platform_RP2MCU/scsi_accel_target_RP2MCU.pio
  60. 0 0
      lib/BlueSCSI_platform_RP2MCU/scsi_accel_target_RP2MCU.pio.h
  61. 3 3
      lib/BlueSCSI_platform_RP2MCU/sd_card_sdio.cpp
  62. 2 2
      lib/BlueSCSI_platform_RP2MCU/sd_card_spi.cpp
  63. 7 7
      lib/BlueSCSI_platform_RP2MCU/sdio.cpp
  64. 1 1
      lib/BlueSCSI_platform_RP2MCU/sdio.h
  65. 0 0
      lib/BlueSCSI_platform_RP2MCU/sdio_RP2MCU.pio
  66. 0 0
      lib/BlueSCSI_platform_RP2MCU/sdio_RP2MCU.pio.h
  67. 4 4
      lib/BlueSCSI_platform_RP2MCU/sdio_rp2350_config.h
  68. 16 16
      lib/BlueSCSI_platform_RP2MCU/timings_RP2MCU.c
  69. 8 8
      lib/BlueSCSI_platform_RP2MCU/timings_RP2MCU.h
  70. 1 1
      lib/SCSI2SD/src/firmware/inquiry.c
  71. 1 1
      lib/SCSI2SD/src/firmware/mode.c
  72. 2 2
      lib/SCSI2SD/src/firmware/network.c
  73. 2 2
      lib/SCSI2SD/src/firmware/network.h
  74. 2 2
      lib/SCSI2SD/src/firmware/scsi.c
  75. 3 3
      lib/SCSI2SD/src/firmware/timings.h
  76. 1 1
      lib/SCSI2SD/src/firmware/toolbox.h
  77. 0 959
      lib/ZuluSCSI_platform_GD32F205/ZuluSCSI_platform.cpp
  78. 0 219
      lib/ZuluSCSI_platform_GD32F205/ZuluSCSI_platform.h
  79. 0 47
      lib/ZuluSCSI_platform_GD32F205/ZuluSCSI_platform_config.h
  80. 0 256
      lib/ZuluSCSI_platform_GD32F205/ZuluSCSI_platform_msc.cpp
  81. 0 62
      lib/ZuluSCSI_platform_GD32F205/ZuluSCSI_platform_msc.h
  82. 0 156
      lib/ZuluSCSI_platform_GD32F205/ZuluSCSI_v1_0_gpio.h
  83. 0 312
      lib/ZuluSCSI_platform_GD32F205/ZuluSCSI_v1_1_gpio.h
  84. 0 424
      lib/ZuluSCSI_platform_GD32F205/audio_i2s.cpp
  85. 0 61
      lib/ZuluSCSI_platform_GD32F205/audio_i2s.h
  86. 0 536
      lib/ZuluSCSI_platform_GD32F205/gd32_cdc_acm_core.c
  87. 0 66
      lib/ZuluSCSI_platform_GD32F205/gd32_cdc_acm_core.h
  88. 0 2520
      lib/ZuluSCSI_platform_GD32F205/gd32_sdio_sdcard.c
  89. 0 271
      lib/ZuluSCSI_platform_GD32F205/gd32_sdio_sdcard.h
  90. 0 209
      lib/ZuluSCSI_platform_GD32F205/greenpak.cpp
  91. 0 34
      lib/ZuluSCSI_platform_GD32F205/greenpak.h
  92. 0 46
      lib/ZuluSCSI_platform_GD32F205/greenpak_fw.h
  93. 0 106
      lib/ZuluSCSI_platform_GD32F205/platform_hw_config.cpp
  94. 0 77
      lib/ZuluSCSI_platform_GD32F205/platform_hw_config.h
  95. 0 37
      lib/ZuluSCSI_platform_GD32F205/scsi2sd_time.h
  96. 0 26
      lib/ZuluSCSI_platform_GD32F205/scsi2sd_timings.c
  97. 0 648
      lib/ZuluSCSI_platform_GD32F205/scsiPhy.cpp
  98. 0 90
      lib/ZuluSCSI_platform_GD32F205/scsiPhy.h
  99. 0 173
      lib/ZuluSCSI_platform_GD32F205/scsi_accel_asm.cpp
  100. 0 29
      lib/ZuluSCSI_platform_GD32F205/scsi_accel_asm.h

+ 0 - 53
.github/workflows/analyze_crashlogs.yml

@@ -1,53 +0,0 @@
-name: Analyze crash logs
-
-on:
-  issue_comment:
-    types: [created]
-  issues:
-    types: [opened, edited]
-
-jobs:
-  analyze_crashlog:
-    name: Analyze crash log
-    runs-on: ubuntu-20.04
-    if: |
-      (github.event_name == 'issue_comment' && (
-        contains(github.event.comment.body, 'CRASH!') ||
-        contains(github.event.comment.body, 'WATCHDOG TIMEOUT'))) ||
-      (github.event_name == 'issues' && (
-          contains(github.event.issue.body, 'CRASH!') ||
-          contains(github.event.issue.body, 'WATCHDOG TIMEOUT')))
-    permissions:
-      issues: write
-
-    steps:
-      - name: Check out code from GitHub
-        uses: actions/checkout@v4
-      - name: Install tools
-        run: |
-          sudo apt-get install binutils-arm-none-eabi
-
-      - name: Analyze crash log from issue body
-        if: github.event_name == 'issues'
-        env:
-          ISSUE_ID: ${{ github.event.issue.number }}
-          GH_TOKEN: ${{ github.token }}
-        run: |
-          gh api repos/${GITHUB_REPOSITORY}/issues/${ISSUE_ID}/comments --jq '.[-1].body' | grep Automatic && exit 0 # Comment only once
-          gh api repos/${GITHUB_REPOSITORY}/issues/${ISSUE_ID} --jq '.body' > comment.txt
-          echo -e 'Automatic analysis of the crash log:\n\n<pre>' > output.txt
-          utils/analyze_crashlog.sh comment.txt | tee -a output.txt
-          echo '</pre>' >> output.txt
-          grep '^0x' output.txt && gh issue comment ${ISSUE_ID} --body-file output.txt
-
-      - name: Analyze crash log from issue comment
-        if: github.event_name == 'issue_comment'
-        env:
-          ISSUE_ID: ${{ github.event.issue.number }}
-          GH_TOKEN: ${{ github.token }}
-        run: |
-          gh api repos/${GITHUB_REPOSITORY}/issues/${ISSUE_ID}/comments --jq '.[-1].body' > comment.txt
-          echo -e 'Automatic analysis of the crash log:\n\n<pre>' > output.txt
-          utils/analyze_crashlog.sh comment.txt | tee -a output.txt
-          echo '</pre>' >> output.txt
-          grep '^0x' output.txt && gh issue comment ${ISSUE_ID} --body-file output.txt

+ 0 - 72
.github/workflows/firmware_build.yml

@@ -1,72 +0,0 @@
-name: Build ZuluSCSI firmware
-
-on:
-  push:
-  workflow_dispatch:
-  pull_request:
-
-jobs:
-  build_firmware:
-#    name: RHC-internal-Z4
-#    runs-on: self-hosted
-    name: Build firmware on GitHub using latest Ubuntu
-    runs-on: ubuntu-latest
-
-    steps:
-      - name: Check out code from GitHub
-        uses: actions/checkout@v4
-        with:
-          path: ZuluSCSI
-          fetch-depth: "0"
-
-      - name: Install dependencies
-        run: |
-          sudo apt-get update
-          sudo apt-get install zip
-
-      - name: Install platformio
-        run: |
-          pip install -U platformio
-
-      - name: Build firmware
-        run: |
-          cd ZuluSCSI
-          pio run -v -j8
-
-      - name: Rename firmware files
-        run: |
-          cd ZuluSCSI
-          utils/rename_binaries.sh
-
-      - name: Create bin package zip file
-        run: |
-          cd ZuluSCSI
-          utils/create_bin_package_zip.sh
-
-      - name: Upload binaries into build artifacts
-        uses: actions/upload-artifact@v4
-        with:
-          path: ZuluSCSI/distrib/*
-          name: ZuluSCSI binaries
-
-      - name: Upload to latest release
-        env:
-          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
-        if: github.ref == 'refs/heads/main'
-        run: |
-          cd ZuluSCSI
-          git tag -d latest
-          git tag latest
-          git push origin --force latest
-          cd distrib
-          gh api repos/${GITHUB_REPOSITORY}/releases/tags/latest | jq -r '.assets[] | [.url] | @tsv' | xargs -n 1 gh api -X DELETE || true
-          gh release upload --repo ${GITHUB_REPOSITORY} --clobber latest *
-
-      - name: Upload to newly created release
-        env:
-          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
-        if: ${{ startsWith(github.ref, 'refs/tags/') }}
-        run: |
-          cd ZuluSCSI/distrib
-          RELEASE=$(basename ${{github.ref}})
-          gh release upload --repo ${GITHUB_REPOSITORY} $RELEASE *

+ 1 - 0
.gitignore

@@ -1,3 +1,4 @@
 .pio
 .vscode
 .DS_Store
+.idea

+ 668 - 19
LICENSE

@@ -1,25 +1,674 @@
-Software
------
+                    GNU GENERAL PUBLIC LICENSE
+                       Version 3, 29 June 2007
 
-ZuluSCSI™ - Copyright (c) 2022-2025 Rabbit Hole Computing™
+ Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
 
-ZuluSCSI™ is based on both SCSI2SD V6 and BlueSCSI codebases,
-and licensed under the GPL version 3 or any later version.
+                            Preamble
 
-https://www.gnu.org/licenses/gpl-3.0.html
-----
-SCSI2SD code is Copyright (C) 2016-2022 Michael McMaster.
-BlueSCSI code is Copyright (C) 2021 Eric Helgeson.
+  The GNU General Public License is a free, copyleft license for
+software and other kinds of works.
 
-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.
+  The licenses for most software and other practical works are designed
+to take away your freedom to share and change the works.  By contrast,
+the GNU General Public License is intended to guarantee your freedom to
+share and change all versions of a program--to make sure it remains free
+software for all its users.  We, the Free Software Foundation, use the
+GNU General Public License for most of our software; it applies also to
+any other work released this way by its authors.  You can apply it to
+your programs, too.
 
-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.
+  When we speak of free software, we are referring to freedom, not
+price.  Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+them if you wish), that you receive source code or can get it if you
+want it, that you can change the software or use pieces of it in new
+free programs, and that you know you can do these things.
 
-You should have received a copy of the GNU General Public License
-along with this program.  If not, see <https://www.gnu.org/licenses/>.
+  To protect your rights, we need to prevent others from denying you
+these rights or asking you to surrender the rights.  Therefore, you have
+certain responsibilities if you distribute copies of the software, or if
+you modify it: responsibilities to respect the freedom of others.
+
+  For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must pass on to the recipients the same
+freedoms that you received.  You must make sure that they, too, receive
+or can get the source code.  And you must show them these terms so they
+know their rights.
+
+  Developers that use the GNU GPL protect your rights with two steps:
+(1) assert copyright on the software, and (2) offer you this License
+giving you legal permission to copy, distribute and/or modify it.
+
+  For the developers' and authors' protection, the GPL clearly explains
+that there is no warranty for this free software.  For both users' and
+authors' sake, the GPL requires that modified versions be marked as
+changed, so that their problems will not be attributed erroneously to
+authors of previous versions.
+
+  Some devices are designed to deny users access to install or run
+modified versions of the software inside them, although the manufacturer
+can do so.  This is fundamentally incompatible with the aim of
+protecting users' freedom to change the software.  The systematic
+pattern of such abuse occurs in the area of products for individuals to
+use, which is precisely where it is most unacceptable.  Therefore, we
+have designed this version of the GPL to prohibit the practice for those
+products.  If such problems arise substantially in other domains, we
+stand ready to extend this provision to those domains in future versions
+of the GPL, as needed to protect the freedom of users.
+
+  Finally, every program is threatened constantly by software patents.
+States should not allow patents to restrict development and use of
+software on general-purpose computers, but in those that do, we wish to
+avoid the special danger that patents applied to a free program could
+make it effectively proprietary.  To prevent this, the GPL assures that
+patents cannot be used to render the program non-free.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.
+
+                       TERMS AND CONDITIONS
+
+  0. Definitions.
+
+  "This License" refers to version 3 of the GNU General Public License.
+
+  "Copyright" also means copyright-like laws that apply to other kinds of
+works, such as semiconductor masks.
+
+  "The Program" refers to any copyrightable work licensed under this
+License.  Each licensee is addressed as "you".  "Licensees" and
+"recipients" may be individuals or organizations.
+
+  To "modify" a work means to copy from or adapt all or part of the work
+in a fashion requiring copyright permission, other than the making of an
+exact copy.  The resulting work is called a "modified version" of the
+earlier work or a work "based on" the earlier work.
+
+  A "covered work" means either the unmodified Program or a work based
+on the Program.
+
+  To "propagate" a work means to do anything with it that, without
+permission, would make you directly or secondarily liable for
+infringement under applicable copyright law, except executing it on a
+computer or modifying a private copy.  Propagation includes copying,
+distribution (with or without modification), making available to the
+public, and in some countries other activities as well.
+
+  To "convey" a work means any kind of propagation that enables other
+parties to make or receive copies.  Mere interaction with a user through
+a computer network, with no transfer of a copy, is not conveying.
+
+  An interactive user interface displays "Appropriate Legal Notices"
+to the extent that it includes a convenient and prominently visible
+feature that (1) displays an appropriate copyright notice, and (2)
+tells the user that there is no warranty for the work (except to the
+extent that warranties are provided), that licensees may convey the
+work under this License, and how to view a copy of this License.  If
+the interface presents a list of user commands or options, such as a
+menu, a prominent item in the list meets this criterion.
+
+  1. Source Code.
+
+  The "source code" for a work means the preferred form of the work
+for making modifications to it.  "Object code" means any non-source
+form of a work.
+
+  A "Standard Interface" means an interface that either is an official
+standard defined by a recognized standards body, or, in the case of
+interfaces specified for a particular programming language, one that
+is widely used among developers working in that language.
+
+  The "System Libraries" of an executable work include anything, other
+than the work as a whole, that (a) is included in the normal form of
+packaging a Major Component, but which is not part of that Major
+Component, and (b) serves only to enable use of the work with that
+Major Component, or to implement a Standard Interface for which an
+implementation is available to the public in source code form.  A
+"Major Component", in this context, means a major essential component
+(kernel, window system, and so on) of the specific operating system
+(if any) on which the executable work runs, or a compiler used to
+produce the work, or an object code interpreter used to run it.
+
+  The "Corresponding Source" for a work in object code form means all
+the source code needed to generate, install, and (for an executable
+work) run the object code and to modify the work, including scripts to
+control those activities.  However, it does not include the work's
+System Libraries, or general-purpose tools or generally available free
+programs which are used unmodified in performing those activities but
+which are not part of the work.  For example, Corresponding Source
+includes interface definition files associated with source files for
+the work, and the source code for shared libraries and dynamically
+linked subprograms that the work is specifically designed to require,
+such as by intimate data communication or control flow between those
+subprograms and other parts of the work.
+
+  The Corresponding Source need not include anything that users
+can regenerate automatically from other parts of the Corresponding
+Source.
+
+  The Corresponding Source for a work in source code form is that
+same work.
+
+  2. Basic Permissions.
+
+  All rights granted under this License are granted for the term of
+copyright on the Program, and are irrevocable provided the stated
+conditions are met.  This License explicitly affirms your unlimited
+permission to run the unmodified Program.  The output from running a
+covered work is covered by this License only if the output, given its
+content, constitutes a covered work.  This License acknowledges your
+rights of fair use or other equivalent, as provided by copyright law.
+
+  You may make, run and propagate covered works that you do not
+convey, without conditions so long as your license otherwise remains
+in force.  You may convey covered works to others for the sole purpose
+of having them make modifications exclusively for you, or provide you
+with facilities for running those works, provided that you comply with
+the terms of this License in conveying all material for which you do
+not control copyright.  Those thus making or running the covered works
+for you must do so exclusively on your behalf, under your direction
+and control, on terms that prohibit them from making any copies of
+your copyrighted material outside their relationship with you.
+
+  Conveying under any other circumstances is permitted solely under
+the conditions stated below.  Sublicensing is not allowed; section 10
+makes it unnecessary.
+
+  3. Protecting Users' Legal Rights From Anti-Circumvention Law.
+
+  No covered work shall be deemed part of an effective technological
+measure under any applicable law fulfilling obligations under article
+11 of the WIPO copyright treaty adopted on 20 December 1996, or
+similar laws prohibiting or restricting circumvention of such
+measures.
+
+  When you convey a covered work, you waive any legal power to forbid
+circumvention of technological measures to the extent such circumvention
+is effected by exercising rights under this License with respect to
+the covered work, and you disclaim any intention to limit operation or
+modification of the work as a means of enforcing, against the work's
+users, your or third parties' legal rights to forbid circumvention of
+technological measures.
+
+  4. Conveying Verbatim Copies.
+
+  You may convey verbatim copies of the Program's source code as you
+receive it, in any medium, provided that you conspicuously and
+appropriately publish on each copy an appropriate copyright notice;
+keep intact all notices stating that this License and any
+non-permissive terms added in accord with section 7 apply to the code;
+keep intact all notices of the absence of any warranty; and give all
+recipients a copy of this License along with the Program.
+
+  You may charge any price or no price for each copy that you convey,
+and you may offer support or warranty protection for a fee.
+
+  5. Conveying Modified Source Versions.
+
+  You may convey a work based on the Program, or the modifications to
+produce it from the Program, in the form of source code under the
+terms of section 4, provided that you also meet all of these conditions:
+
+    a) The work must carry prominent notices stating that you modified
+    it, and giving a relevant date.
+
+    b) The work must carry prominent notices stating that it is
+    released under this License and any conditions added under section
+    7.  This requirement modifies the requirement in section 4 to
+    "keep intact all notices".
+
+    c) You must license the entire work, as a whole, under this
+    License to anyone who comes into possession of a copy.  This
+    License will therefore apply, along with any applicable section 7
+    additional terms, to the whole of the work, and all its parts,
+    regardless of how they are packaged.  This License gives no
+    permission to license the work in any other way, but it does not
+    invalidate such permission if you have separately received it.
+
+    d) If the work has interactive user interfaces, each must display
+    Appropriate Legal Notices; however, if the Program has interactive
+    interfaces that do not display Appropriate Legal Notices, your
+    work need not make them do so.
+
+  A compilation of a covered work with other separate and independent
+works, which are not by their nature extensions of the covered work,
+and which are not combined with it such as to form a larger program,
+in or on a volume of a storage or distribution medium, is called an
+"aggregate" if the compilation and its resulting copyright are not
+used to limit the access or legal rights of the compilation's users
+beyond what the individual works permit.  Inclusion of a covered work
+in an aggregate does not cause this License to apply to the other
+parts of the aggregate.
+
+  6. Conveying Non-Source Forms.
+
+  You may convey a covered work in object code form under the terms
+of sections 4 and 5, provided that you also convey the
+machine-readable Corresponding Source under the terms of this License,
+in one of these ways:
+
+    a) Convey the object code in, or embodied in, a physical product
+    (including a physical distribution medium), accompanied by the
+    Corresponding Source fixed on a durable physical medium
+    customarily used for software interchange.
+
+    b) Convey the object code in, or embodied in, a physical product
+    (including a physical distribution medium), accompanied by a
+    written offer, valid for at least three years and valid for as
+    long as you offer spare parts or customer support for that product
+    model, to give anyone who possesses the object code either (1) a
+    copy of the Corresponding Source for all the software in the
+    product that is covered by this License, on a durable physical
+    medium customarily used for software interchange, for a price no
+    more than your reasonable cost of physically performing this
+    conveying of source, or (2) access to copy the
+    Corresponding Source from a network server at no charge.
+
+    c) Convey individual copies of the object code with a copy of the
+    written offer to provide the Corresponding Source.  This
+    alternative is allowed only occasionally and noncommercially, and
+    only if you received the object code with such an offer, in accord
+    with subsection 6b.
+
+    d) Convey the object code by offering access from a designated
+    place (gratis or for a charge), and offer equivalent access to the
+    Corresponding Source in the same way through the same place at no
+    further charge.  You need not require recipients to copy the
+    Corresponding Source along with the object code.  If the place to
+    copy the object code is a network server, the Corresponding Source
+    may be on a different server (operated by you or a third party)
+    that supports equivalent copying facilities, provided you maintain
+    clear directions next to the object code saying where to find the
+    Corresponding Source.  Regardless of what server hosts the
+    Corresponding Source, you remain obligated to ensure that it is
+    available for as long as needed to satisfy these requirements.
+
+    e) Convey the object code using peer-to-peer transmission, provided
+    you inform other peers where the object code and Corresponding
+    Source of the work are being offered to the general public at no
+    charge under subsection 6d.
+
+  A separable portion of the object code, whose source code is excluded
+from the Corresponding Source as a System Library, need not be
+included in conveying the object code work.
+
+  A "User Product" is either (1) a "consumer product", which means any
+tangible personal property which is normally used for personal, family,
+or household purposes, or (2) anything designed or sold for incorporation
+into a dwelling.  In determining whether a product is a consumer product,
+doubtful cases shall be resolved in favor of coverage.  For a particular
+product received by a particular user, "normally used" refers to a
+typical or common use of that class of product, regardless of the status
+of the particular user or of the way in which the particular user
+actually uses, or expects or is expected to use, the product.  A product
+is a consumer product regardless of whether the product has substantial
+commercial, industrial or non-consumer uses, unless such uses represent
+the only significant mode of use of the product.
+
+  "Installation Information" for a User Product means any methods,
+procedures, authorization keys, or other information required to install
+and execute modified versions of a covered work in that User Product from
+a modified version of its Corresponding Source.  The information must
+suffice to ensure that the continued functioning of the modified object
+code is in no case prevented or interfered with solely because
+modification has been made.
+
+  If you convey an object code work under this section in, or with, or
+specifically for use in, a User Product, and the conveying occurs as
+part of a transaction in which the right of possession and use of the
+User Product is transferred to the recipient in perpetuity or for a
+fixed term (regardless of how the transaction is characterized), the
+Corresponding Source conveyed under this section must be accompanied
+by the Installation Information.  But this requirement does not apply
+if neither you nor any third party retains the ability to install
+modified object code on the User Product (for example, the work has
+been installed in ROM).
+
+  The requirement to provide Installation Information does not include a
+requirement to continue to provide support service, warranty, or updates
+for a work that has been modified or installed by the recipient, or for
+the User Product in which it has been modified or installed.  Access to a
+network may be denied when the modification itself materially and
+adversely affects the operation of the network or violates the rules and
+protocols for communication across the network.
+
+  Corresponding Source conveyed, and Installation Information provided,
+in accord with this section must be in a format that is publicly
+documented (and with an implementation available to the public in
+source code form), and must require no special password or key for
+unpacking, reading or copying.
+
+  7. Additional Terms.
+
+  "Additional permissions" are terms that supplement the terms of this
+License by making exceptions from one or more of its conditions.
+Additional permissions that are applicable to the entire Program shall
+be treated as though they were included in this License, to the extent
+that they are valid under applicable law.  If additional permissions
+apply only to part of the Program, that part may be used separately
+under those permissions, but the entire Program remains governed by
+this License without regard to the additional permissions.
+
+  When you convey a copy of a covered work, you may at your option
+remove any additional permissions from that copy, or from any part of
+it.  (Additional permissions may be written to require their own
+removal in certain cases when you modify the work.)  You may place
+additional permissions on material, added by you to a covered work,
+for which you have or can give appropriate copyright permission.
+
+  Notwithstanding any other provision of this License, for material you
+add to a covered work, you may (if authorized by the copyright holders of
+that material) supplement the terms of this License with terms:
+
+    a) Disclaiming warranty or limiting liability differently from the
+    terms of sections 15 and 16 of this License; or
+
+    b) Requiring preservation of specified reasonable legal notices or
+    author attributions in that material or in the Appropriate Legal
+    Notices displayed by works containing it; or
+
+    c) Prohibiting misrepresentation of the origin of that material, or
+    requiring that modified versions of such material be marked in
+    reasonable ways as different from the original version; or
+
+    d) Limiting the use for publicity purposes of names of licensors or
+    authors of the material; or
+
+    e) Declining to grant rights under trademark law for use of some
+    trade names, trademarks, or service marks; or
+
+    f) Requiring indemnification of licensors and authors of that
+    material by anyone who conveys the material (or modified versions of
+    it) with contractual assumptions of liability to the recipient, for
+    any liability that these contractual assumptions directly impose on
+    those licensors and authors.
+
+  All other non-permissive additional terms are considered "further
+restrictions" within the meaning of section 10.  If the Program as you
+received it, or any part of it, contains a notice stating that it is
+governed by this License along with a term that is a further
+restriction, you may remove that term.  If a license document contains
+a further restriction but permits relicensing or conveying under this
+License, you may add to a covered work material governed by the terms
+of that license document, provided that the further restriction does
+not survive such relicensing or conveying.
+
+  If you add terms to a covered work in accord with this section, you
+must place, in the relevant source files, a statement of the
+additional terms that apply to those files, or a notice indicating
+where to find the applicable terms.
+
+  Additional terms, permissive or non-permissive, may be stated in the
+form of a separately written license, or stated as exceptions;
+the above requirements apply either way.
+
+  8. Termination.
+
+  You may not propagate or modify a covered work except as expressly
+provided under this License.  Any attempt otherwise to propagate or
+modify it is void, and will automatically terminate your rights under
+this License (including any patent licenses granted under the third
+paragraph of section 11).
+
+  However, if you cease all violation of this License, then your
+license from a particular copyright holder is reinstated (a)
+provisionally, unless and until the copyright holder explicitly and
+finally terminates your license, and (b) permanently, if the copyright
+holder fails to notify you of the violation by some reasonable means
+prior to 60 days after the cessation.
+
+  Moreover, your license from a particular copyright holder is
+reinstated permanently if the copyright holder notifies you of the
+violation by some reasonable means, this is the first time you have
+received notice of violation of this License (for any work) from that
+copyright holder, and you cure the violation prior to 30 days after
+your receipt of the notice.
+
+  Termination of your rights under this section does not terminate the
+licenses of parties who have received copies or rights from you under
+this License.  If your rights have been terminated and not permanently
+reinstated, you do not qualify to receive new licenses for the same
+material under section 10.
+
+  9. Acceptance Not Required for Having Copies.
+
+  You are not required to accept this License in order to receive or
+run a copy of the Program.  Ancillary propagation of a covered work
+occurring solely as a consequence of using peer-to-peer transmission
+to receive a copy likewise does not require acceptance.  However,
+nothing other than this License grants you permission to propagate or
+modify any covered work.  These actions infringe copyright if you do
+not accept this License.  Therefore, by modifying or propagating a
+covered work, you indicate your acceptance of this License to do so.
+
+  10. Automatic Licensing of Downstream Recipients.
+
+  Each time you convey a covered work, the recipient automatically
+receives a license from the original licensors, to run, modify and
+propagate that work, subject to this License.  You are not responsible
+for enforcing compliance by third parties with this License.
+
+  An "entity transaction" is a transaction transferring control of an
+organization, or substantially all assets of one, or subdividing an
+organization, or merging organizations.  If propagation of a covered
+work results from an entity transaction, each party to that
+transaction who receives a copy of the work also receives whatever
+licenses to the work the party's predecessor in interest had or could
+give under the previous paragraph, plus a right to possession of the
+Corresponding Source of the work from the predecessor in interest, if
+the predecessor has it or can get it with reasonable efforts.
+
+  You may not impose any further restrictions on the exercise of the
+rights granted or affirmed under this License.  For example, you may
+not impose a license fee, royalty, or other charge for exercise of
+rights granted under this License, and you may not initiate litigation
+(including a cross-claim or counterclaim in a lawsuit) alleging that
+any patent claim is infringed by making, using, selling, offering for
+sale, or importing the Program or any portion of it.
+
+  11. Patents.
+
+  A "contributor" is a copyright holder who authorizes use under this
+License of the Program or a work on which the Program is based.  The
+work thus licensed is called the contributor's "contributor version".
+
+  A contributor's "essential patent claims" are all patent claims
+owned or controlled by the contributor, whether already acquired or
+hereafter acquired, that would be infringed by some manner, permitted
+by this License, of making, using, or selling its contributor version,
+but do not include claims that would be infringed only as a
+consequence of further modification of the contributor version.  For
+purposes of this definition, "control" includes the right to grant
+patent sublicenses in a manner consistent with the requirements of
+this License.
+
+  Each contributor grants you a non-exclusive, worldwide, royalty-free
+patent license under the contributor's essential patent claims, to
+make, use, sell, offer for sale, import and otherwise run, modify and
+propagate the contents of its contributor version.
+
+  In the following three paragraphs, a "patent license" is any express
+agreement or commitment, however denominated, not to enforce a patent
+(such as an express permission to practice a patent or covenant not to
+sue for patent infringement).  To "grant" such a patent license to a
+party means to make such an agreement or commitment not to enforce a
+patent against the party.
+
+  If you convey a covered work, knowingly relying on a patent license,
+and the Corresponding Source of the work is not available for anyone
+to copy, free of charge and under the terms of this License, through a
+publicly available network server or other readily accessible means,
+then you must either (1) cause the Corresponding Source to be so
+available, or (2) arrange to deprive yourself of the benefit of the
+patent license for this particular work, or (3) arrange, in a manner
+consistent with the requirements of this License, to extend the patent
+license to downstream recipients.  "Knowingly relying" means you have
+actual knowledge that, but for the patent license, your conveying the
+covered work in a country, or your recipient's use of the covered work
+in a country, would infringe one or more identifiable patents in that
+country that you have reason to believe are valid.
+
+  If, pursuant to or in connection with a single transaction or
+arrangement, you convey, or propagate by procuring conveyance of, a
+covered work, and grant a patent license to some of the parties
+receiving the covered work authorizing them to use, propagate, modify
+or convey a specific copy of the covered work, then the patent license
+you grant is automatically extended to all recipients of the covered
+work and works based on it.
+
+  A patent license is "discriminatory" if it does not include within
+the scope of its coverage, prohibits the exercise of, or is
+conditioned on the non-exercise of one or more of the rights that are
+specifically granted under this License.  You may not convey a covered
+work if you are a party to an arrangement with a third party that is
+in the business of distributing software, under which you make payment
+to the third party based on the extent of your activity of conveying
+the work, and under which the third party grants, to any of the
+parties who would receive the covered work from you, a discriminatory
+patent license (a) in connection with copies of the covered work
+conveyed by you (or copies made from those copies), or (b) primarily
+for and in connection with specific products or compilations that
+contain the covered work, unless you entered into that arrangement,
+or that patent license was granted, prior to 28 March 2007.
+
+  Nothing in this License shall be construed as excluding or limiting
+any implied license or other defenses to infringement that may
+otherwise be available to you under applicable patent law.
+
+  12. No Surrender of Others' Freedom.
+
+  If conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot convey a
+covered work so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you may
+not convey it at all.  For example, if you agree to terms that obligate you
+to collect a royalty for further conveying from those to whom you convey
+the Program, the only way you could satisfy both those terms and this
+License would be to refrain entirely from conveying the Program.
+
+  13. Use with the GNU Affero General Public License.
+
+  Notwithstanding any other provision of this License, you have
+permission to link or combine any covered work with a work licensed
+under version 3 of the GNU Affero General Public License into a single
+combined work, and to convey the resulting work.  The terms of this
+License will continue to apply to the part which is the covered work,
+but the special requirements of the GNU Affero General Public License,
+section 13, concerning interaction through a network will apply to the
+combination as such.
+
+  14. Revised Versions of this License.
+
+  The Free Software Foundation may publish revised and/or new versions of
+the GNU General Public License from time to time.  Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+  Each version is given a distinguishing version number.  If the
+Program specifies that a certain numbered version of the GNU General
+Public License "or any later version" applies to it, you have the
+option of following the terms and conditions either of that numbered
+version or of any later version published by the Free Software
+Foundation.  If the Program does not specify a version number of the
+GNU General Public License, you may choose any version ever published
+by the Free Software Foundation.
+
+  If the Program specifies that a proxy can decide which future
+versions of the GNU General Public License can be used, that proxy's
+public statement of acceptance of a version permanently authorizes you
+to choose that version for the Program.
+
+  Later license versions may give you additional or different
+permissions.  However, no additional obligations are imposed on any
+author or copyright holder as a result of your choosing to follow a
+later version.
+
+  15. Disclaimer of Warranty.
+
+  THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
+APPLICABLE LAW.  EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
+HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
+OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
+THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
+IS WITH YOU.  SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
+ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+  16. Limitation of Liability.
+
+  IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
+THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
+GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
+USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
+DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
+PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
+EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
+SUCH DAMAGES.
+
+  17. Interpretation of Sections 15 and 16.
+
+  If the disclaimer of warranty and limitation of liability provided
+above cannot be given local legal effect according to their terms,
+reviewing courts shall apply local law that most closely approximates
+an absolute waiver of all civil liability in connection with the
+Program, unless a warranty or assumption of liability accompanies a
+copy of the Program in return for a fee.
+
+                     END OF TERMS AND CONDITIONS
+
+            How to Apply These Terms to Your New Programs
+
+  If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+  To do so, attach the following notices to the program.  It is safest
+to attach them to the start of each source file to most effectively
+state the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+    <one line to give the program's name and a brief idea of what it does.>
+    Copyright (C) <year>  <name of author>
+
+    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 <https://www.gnu.org/licenses/>.
+
+Also add information on how to contact you by electronic and paper mail.
+
+  If the program does terminal interaction, make it output a short
+notice like this when it starts in an interactive mode:
+
+    <program>  Copyright (C) <year>  <name of author>
+    This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+    This is free software, and you are welcome to redistribute it
+    under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License.  Of course, your program's commands
+might be different; for a GUI interface, you would use an "about box".
+
+  You should also get your employer (if you work as a programmer) or school,
+if any, to sign a "copyright disclaimer" for the program, if necessary.
+For more information on this, and how to apply and follow the GNU GPL, see
+<https://www.gnu.org/licenses/>.
+
+  The GNU General Public License does not permit incorporating your program
+into proprietary programs.  If your program is a subroutine library, you
+may consider it more useful to permit linking proprietary applications with
+the library.  If this is what you want to do, use the GNU Lesser General
+Public License instead of this License.  But first, please read
+<https://www.gnu.org/licenses/why-not-lgpl.html>.

+ 0 - 3
Performance.md

@@ -1,3 +0,0 @@
-Performance
------------
-Performance characteristics of ZuluSCSI are now documented on the Wiki at https://github.com/ZuluSCSI/ZuluSCSI-firmware/wiki/Performance

+ 36 - 0
README.adoc

@@ -0,0 +1,36 @@
+# BlueSCSI
+:toc: macro
+
+BlueSCSI is hardware that reproduces SCSI devices (hard disks, optical, etc) with an Pico 2040 dev board.
+
+image::docs/buynow.png[link=https://scsi.blue, 150]
+image::docs/discordbanner.png[link=https://discord.gg/GKcvtgU7P9, 150]
+
+Join us in #bluescsi on https://discord.gg/GKcvtgU7P9[Discord] or open an issue on this repo.
+
+## Hardware
+
+Hardware schematics, designs, and production files can be found under the `hardware` folder.
+
+Hardware version numbers are based on when the design was updated plus a sub-revision letter, such as "2022_11b" and "2022_12a".
+
+You can find an errta of all the current and former versions in the wiki https://github.com/BlueSCSI/BlueSCSI-v2/wiki/Hardware
+
+## Notes
+
+### Making Gerbers for JLCPCB
+
+https://support.jlcpcb.com/article/44-how-to-export-kicad-pcb-to-gerber-files
+
+## Licenses
+
+### Firmware
+
+The BlueSCSI V2 firmware is a fork of ZuluSCSI, which also includes SCSI2SD V6 source code:
+
+* https://github.com/ZuluSCSI/ZuluSCSI-firmware[ZuluSCSI]
+* http://git.codesrc.com/index.cgi?p=SCSI2SD-V6.git;a=summary[SCSI2SD V6]
+* https://github.com/erichelgeson/BlueSCSI[BlueSCSI V1]
+* https://github.com/ztto/ArdSCSino-stm32[ArdSCSIno-stm32]
+
+BlueSCSI(TM) - Eric Helgeson - All rights reserved.

+ 0 - 226
README.md

@@ -1,226 +0,0 @@
-ZuluSCSI™ Firmware
-=================
-
-Hard Drive & ISO image files
----------------------
-ZuluSCSI uses raw hard drive image files, which are stored on a FAT32 or exFAT-formatted SD card. These are often referred to as "hda" files.
-
-Examples of valid filenames:
-* `HD5.hda` or `HD5.img`: hard drive with SCSI ID 5
-* `HD20_512.hda`: hard drive with SCSI ID 2, LUN 0, block size 512. Currently, ZuluSCSI does not support multiple LUNs, only LUN 0.
-* `CD3.iso`: CD drive with SCSI ID 3
-
-In addition to the simplified filenames style above, the ZuluSCSI firmware also looks for images using the BlueSCSI-style "HDxy_512.hda" filename formatting.
-
-The media type can be set in `zuluscsi.ini`, or directly by the file name prefix.
-Supported prefixes are `HD` (hard drive), `CD` (cd-rom), `FD` (floppy), `MO` (magneto-optical), `RE` (generic removeable media), `TP` (sequential tape drive).
-
-CD-ROM images in BIN/CUE format
--------------------------------
-The `.iso` format for CD images only supports data track.
-For audio and mixed mode CDs, two files are needed: `.bin` with data and `.cue` with the list of tracks.
-
-To use a BIN/CUE image with ZuluSCSI, name both files with the same part before the extension.
-For example `CD3.bin` and `CD3.cue`.
-The cue file contains the original file name, but it doesn't matter for ZuluSCSI.
-
-If the image consists of one `.cue` file and multiple `.bin` files, they need to be placed in a separate subfolder.
-For example, create `CD3` folder, then `MyGame` subfolder and put the `.cue` and `.bin` files there.
-The `.bin` file names must then match the names specified in the `.cue` file.
-
-Supported track types are `AUDIO`, `MODE1/2048` and `MODE1/2352`.
-
-Creating new image files
-------------------------
-Empty image files can be created using operating system tools:
-
-* Windows: `fsutil file createnew HD1.img 1073741824` (1 GB)
-* Linux: `truncate -s 1G HD1.img`
-* Mac OS X: `mkfile -n 1g HD1.img`
-
-If you need to use image files larger than 4GB, you _must_ use an exFAT-formatted SD card, as the FAT32 filesystem does not support files larger than 4,294,967,295 bytes (4GB-1 byte).
-
-ZuluSCSI firmware can also create image files itself.
-To do this, create a text file with filename such as `Create 1024M HD40.txt`.
-The special filename must start with "Create" and be followed by file size and the name of resulting image file.
-The file will be created next time the SD card is inserted.
-The status LED will flash rapidly while image file generation is in progress.
-
-Log files and error indications
--------------------------------
-Log messages are stored in `zululog.txt`, which is cleared on every boot.
-Normally only basic initialization information is stored, but switching the `DBG` DIP switch on will cause every SCSI command to be logged, once the board is power cycled.
-
-The indicator LED will normally report disk access.
-It also reports following status conditions:
-
-- 1 fast blink on boot: Image file loaded successfully
-- 3 fast blinks: No images found on SD card
-- 5 fast blinks: SD card not detected
-- Continuous morse pattern: firmware crashed, morse code indicates crash location
-
-In crashes the firmware will also attempt to save information into `zuluerr.txt`.
-
-Configuration file
-------------------
-Optional configuration can be stored in `zuluscsi.ini`.
-If image file is found but configuration is missing, a default configuration is used.
-
-Example config file is available here: [zuluscsi.ini](zuluscsi.ini).
-
-Performance
------------
-Performance information for the various ZuluSCSI hardware models is [documented separately, here](https://github.com/ZuluSCSI/ZuluSCSI-firmware/wiki/Performance)
-
-Hotplugging
------------
-The firmware supports hot-plug removal and reinsertion of SD card.
-The status led will blink continuously when card is not present, then blink once when card is reinserted successfully.
-
-It will depend on the host system whether it gets confused by hotplugging.
-Any IO requests issued when card is removed will be timeouted.
-
-Programming & bootloader
-------------------------
-For ZuluSCSI Blaster and RP2040-based boards, the USB programming uses `.uf2` format file that can be copied to the virtual USB drive that shows up in bootloader mode.
-
-- There is a custom bootloader that loads new firmware from SD card on boot.
-- Firmware update takes about 1 second, during which the LED will flash rapidly.
-- When successful, the bootloader removes the update file and continues to main firmware.
-- On ZuluSCSI Blaster and RP2040 boards, there is a "BOOTLDR" momentary-contact switch, which can be held down at initial power-on, to enable .uf2 firmware to be loaded.
-
-
-For ZuluSCSI V1.1 and V1.2:
-
-- Alternatively, ZuluSCSI V1.x can be programmed using USB connection in DFU mode by setting DIP switch 4.
-- For ZuluSCSI V1.2 boards, there is a "BOOTLDR" momentary-contact switch, which can be held down at initial power-on, to enable DFU mode, needed for firmware recovery mode.
-- The necessary programmer utility for Windows can be downloaded from [GD32 website](http://www.gd32mcu.com/en/download?kw=dfu&lan=en). On Linux and MacOS, the standard 'dfu-util' can be used. It can be installed via your package manager under Linux. On MacOS, it is available through MacPorts and Brew as a package.
-- For ZuluSCSI V1.x boards, firmware can be flashed with the following command:
-- `dfu-util --alt 0 --dfuse-address 0x08000000 --download ZuluSCSIv1_1_XXXXXX.bin`
-
-
-DIP switches
-------------
-ZuluSCSI Blaster and RP2040 (Full Size) DIP switch settings are:
-- INITIATOR: Enable SCSI initiator mode for imaging SCSI drives
-- DEBUG LOG: Enable verbose debug log (saved to `zululog.txt`)
-- TERMINATION: Enable SCSI termination
-Later (Rev2023a) ZuluSCSI RP2040 and all ZuluSCSI Blaster Full Size boards have a bootloader button instead of a DIP switch. 
-
-For ZuluSCSI V1.1, the DIP switch settings are as follows:
-
-- DEBUG: Enable verbose debug log (saved to `zululog.txt`)
-- TERM: Enable SCSI termination
-- BOOT: Enable built-in USB bootloader, this DIP switch MUST remain off during normal operation.
-- SW1: Enables/disables Macintosh/Apple specific mode-pages and device strings, which eases disk initialization when performing fresh installs on legacy Macintosh computers.
-
-For ZuluSCSI V1.2, the DIP switch settings at SW301 are as follows:
-
-- TERM: Enable SCSI termination
-- DEBUG: Enable verbose debug logging via USB serial console.
-- DIRECT/RAW: when in the factory-default OFF position, the entirety of the SD card is exposed as a single block device, and the device type is defined by the setting of the rotary DIP switch at SW404.
-- QUIRKS: Enables/disables Macintosh/Apple specific mode-pages and device strings, which eases disk initialization when performing fresh installs on legacy Macintosh computers.
-
-ZuluSCSI Mini has no DIP switches, so all optional configuration parameters must be defined in zuluscsi.ini
-
-Physical eject button for CDROM
--------------------------------
-CD-ROM drives can be configured to eject when a physical button is pressed.
-If multiple image files are configured with `IMG0`..`IMG9` config settings, ejection will switch between them.
-Two separate buttons are supported and they can eject different drives.
-
-    [SCSI1]
-    Type=2 # CDROM drive
-    IMG0 = img0.iso
-    IMG1 = ...
-    EjectButton = 1
-
-On ZuluSCSI V1.0 and V1.1 models, buttons are connected to J303 12-pin expansion header.
-Button 1 is connected between `PE5` and `GND`, and button 2 is connected between `PE6` and `GND`.
-Pin locations are also shown in [this image](docs/ZuluSCSI_v1_1_buttons.jpg).
-
-On red ZuluSCSI Blaster and RP2040-based ZuluSCSI models, buttons are connected to the I2C pins.
-
-Button 1 is connected between `SDA` and `GND` and button 2 is connected between `SCL` and `GND`.
-On full-size models, the pins are available on expansion header J303 ([image](docs/ZuluSCSI_RP2040_buttons.jpg)).
-On compact model, pins are available on 4-pin I2C header J305 ([image](docs/ZuluSCSI_RP2040_compact_buttons.jpg)).
-
-SCSI initiator mode
--------------------
-The **full-size** ZuluSCSI Blaster, ZuluSCSI RP2040, and Pico OSHW models support SCSI initiator mode for reading SCSI drives.
-When enabled by the DIP switch, the ZuluSCSI Blaster/RP2040 will scan for SCSI drives on the bus and copy the data as `HDxx_imaged.hda` to the SD card.
-
-LED indications in initiator mode:
-
-- Short blink once a second: idle, searching for SCSI drives
-- Fast blink 4 times per second: copying data. The blink acts as a progress bar: first it is short and becomes longer when data copying progresses.
-
-The firmware retries reads up to 5 times and attempts to skip any sectors that have problems.
-Any read errors are logged into `zululog.txt`.
-
-Alternatively, if SD card is not inserted, the SCSI drive will be available to PC through USB connection.
-The drive shows up as mass storage device (USB MSC).
-Currently this primarily supports SCSI harddrives, but basic read access is supported for CD-ROM and other SCSI devices.
-
-Depending on hardware setup, you may need to mount diode `D205` and jumper `JP201` to supply `TERMPWR` to the SCSI bus.
-This is necessary if the drives do not supply their own SCSI terminator power.
-
-ROM drive in microcontroller flash
-----------------------------------
-The new ZuluSCSI Blaster model supports storing up to 15.8 **megabytes** in flash, which can be used as a read-only bootable ROM drive.
-
-All older ZuluSCSI RP2040 models support storing up to 1660kB image as a read-only drive in the flash chip on the PCB itself. This can be used as e.g. a boot floppy that is available even without SD card.
-
-To initialize a ROM drive, name your image file as e.g. `HD0.rom`.
-The drive type, SCSI ID and blocksize can be set in the filename the same way as for normal images.
-On first boot, the LED will blink rapidly while the image is being loaded into flash memory.
-Once loading is complete, the file is renamed to `HD0.rom_loaded` and the data is accessed from flash instead.
-
-The status and maximum size of ROM drive are reported in `zululog.txt`.
-To disable a previously programmed ROM drive, create empty file called `HD0.rom`.
-If there is a `.bin` file with the same ID as the programmed ROM drive, it overrides the ROM drive.
-There can be at most one ROM drive enabled at a time.
-
-Project structure
------------------
-- **src/ZuluSCSI.cpp**: Main portable SCSI implementation.
-- **src/ZuluSCSI_disk.cpp**: Interface between SCSI2SD code and SD card reading.
-- **src/ZuluSCSI_log.cpp**: Simple logging functionality, uses memory buffering.
-- **src/ZuluSCSI_config.h**: Some compile-time options, usually no need to change.
-- **lib/ZuluSCSI_platform_platformName**: Platform-specific code for each supported ZuluSCSI hardware platform.
-- **lib/SCSI2SD**: SCSI2SD V6 code, used for SCSI command implementations.
-- **lib/minIni**: Ini config file access library
-- **lib/SdFat_NoArduino**: Modified version of [SdFat](https://github.com/greiman/SdFat) library for use without Arduino core.
-- **utils/run_gdb.sh**: Helper script for debugging with st-link adapter. Displays SWO log directly in console.
-
-To port the code to a new platform, see README in [lib/ZuluSCSI_platform_template](lib/ZuluSCSI_platform_template) folder.
-
-Building
---------
-This codebase uses [PlatformIO](https://platformio.org/).
-To build run the command:
-
-    pio run
-
-
-Origins and License
--------------------
-
-This firmware is derived from two sources, both under GPL 3 license:
-
-* [SCSI2SD V6](http://www.codesrc.com/mediawiki/index.php/SCSI2SD)
-* [BlueSCSI](https://github.com/erichelgeson/BlueSCSI), which in turn is derived from [ArdSCSIno-stm32](https://github.com/ztto/ArdSCSino-stm32).
-
-Main program structure:
-
-* SCSI command implementations are from SCSI2SD.
-* SCSI physical layer code is mostly custom, with some inspiration from BlueSCSI.
-* Image file access is derived from BlueSCSI.
-
-Major changes from BlueSCSI and SCSI2SD include:
-
-* Separation of platform-specific functionality to separate directory to ease porting.
-* Originally ported to GD32F205 and then RP2040 (See commit [858620f](https://github.com/ZuluSCSI/ZuluSCSI-firmware/commit/858620f2855d29fbd5b3f905972523b4fe65fdea)).
-* Removal of Arduino core dependency, as it was not currently available for GD32F205.
-* Buffered log functions.
-* Simultaneous transfer between SD card and SCSI for improved performance.

+ 2 - 2
boards/rpipico.json

@@ -32,7 +32,7 @@
     "frameworks": [
         "arduino"
     ],
-    "name": "ZuluSCSI Pico",
+    "name": "BlueSCSI Pico",
     "upload": {
         "maximum_ram_size": 262144,
         "maximum_size": 2097152,
@@ -50,6 +50,6 @@
             "picoprobe"
         ]
     },
-    "url": "http://zuluscsi.com",
+    "url": "http://bluescsi.com",
     "vendor": "Rabbit Hole Computing LLC"
 }

+ 2 - 2
boards/rpipico2.json

@@ -32,7 +32,7 @@
     "frameworks": [
         "arduino"
     ],
-    "name": "ZuluSCSI Pico 2",
+    "name": "BlueSCSI Pico 2",
     "upload": {
         "psram_length": 0,
         "maximum_ram_size": 524288,
@@ -52,6 +52,6 @@
             "pico-debug"
         ]
     },
-    "url": "http://zuluscsi.com",
+    "url": "http://bluescsi.com",
     "vendor": "Rabbit Hole Computing LLC"
 }

+ 2 - 2
boards/rpipico2w.json

@@ -32,7 +32,7 @@
     "frameworks": [
         "arduino"
     ],
-    "name": "ZuluSCSI Pico 2 DaynaPORT",
+    "name": "BlueSCSI Pico 2 DaynaPORT",
     "upload": {
         "maximum_ram_size": 524288,
         "maximum_size": 4194304,
@@ -50,6 +50,6 @@
             "picoprobe"
         ]
     },
-    "url": "http://zuluscsi.com",
+    "url": "http://bluescsi.com",
     "vendor": "Rabbit Hole Computing LLC"
 }

+ 2 - 2
boards/rpipicow.json

@@ -32,7 +32,7 @@
     "frameworks": [
         "arduino"
     ],
-    "name": "ZuluSCSI Pico DaynaPORT",
+    "name": "BlueSCSI Pico DaynaPORT",
     "upload": {
         "maximum_ram_size": 262144,
         "maximum_size": 2097152,
@@ -50,6 +50,6 @@
             "picoprobe"
         ]
     },
-    "url": "http://zuluscsi.com",
+    "url": "http://bluescsi.com",
     "vendor": "Rabbit Hole Computing LLC"
 }

+ 0 - 55
boards/zuluscsi_blaster.json

@@ -1,55 +0,0 @@
-{
-    "build": {
-        "arduino": {
-            "earlephilhower": {
-                "boot2_source": "none.S",
-                "usb_vid": "0x2E8A",
-                "usb_pid": "0xF00F"
-            }
-        },
-        "core": "earlephilhower",
-        "cpu": "cortex-m33",
-        "extra_flags": "-DARDUINO_GENERIC_RP2350 -DARDUINO_ARCH_RP2040 -DUSBD_MAX_POWER_MA=500 -DPICO_CYW43_SUPPORTED=1 -DCYW43_PIN_WL_DYNAMIC=1",
-        "f_cpu": "150000000L",
-        "hwids": [
-            [
-                "0x2E8A",
-                "0x00C0"
-            ],
-            [
-                "0x2E8A",
-                "0xF00F"
-            ]
-        ],
-        "mcu": "rp2350",
-        "variant": "rpipico2w"
-    },
-    "debug": {
-        "jlink_device": "RP2350_0",
-        "openocd_target": "rp2350.cfg",
-        "svd_path": "rp2350.svd"
-    },
-    "frameworks": [
-        "arduino"
-    ],
-    "name": "ZuluSCSI Blaster",
-    "upload": {
-        "maximum_ram_size": 524288,
-        "maximum_size": 16777216,
-        "require_upload_port": true,
-        "native_usb": true,
-        "use_1200bps_touch": true,
-        "wait_for_upload_port": false,
-        "protocol": "cmsis-dap",
-        "protocols": [
-            "blackmagic",
-            "cmsis-dap",
-            "jlink",
-            "raspberrypi-swd",
-            "picotool",
-            "picoprobe"
-        ]
-    },
-    "url": "http://zuluscsi.com",
-    "vendor": "Rabbit Hole Computing LLC"
-}

+ 0 - 57
boards/zuluscsi_rp2040.json

@@ -1,57 +0,0 @@
-{
-    "build": {
-      "arduino": {
-        "earlephilhower": {
-          "boot2_source": "boot2_w25q080_2_padded_checksum.S",
-          "usb_vid": "0x2E8A",
-          "usb_pid": "0xF00A"
-        }
-      },
-      "core": "earlephilhower",
-      "cpu": "cortex-m0plus",
-      "extra_flags": "-DARDUINO_GENERIC_RP2040 -DARDUINO_ARCH_RP2040 -DUSBD_MAX_POWER_MA=500 ",
-      "f_cpu": "125000000L",
-      "hwids": [
-        [
-          "0x2E8A",
-          "0x00C0"
-        ],
-        [
-          "0x2E8A",
-          "0xF00A"
-        ]
-      ],
-      "mcu": "rp2040",
-      "variant": "generic"
-    },
-    "debug": {
-      "jlink_device": "RP2040_M0_0",
-      "openocd_target": "rp2040.cfg",
-      "svd_path": "rp2040.svd"
-    },
-    "frameworks": [
-      "arduino"
-    ],
-    "name": "ZuluSCSI RP2040",
-    "upload": {
-      "maximum_ram_size": 270336,
-      "maximum_size": 2097152,
-      "require_upload_port": true,
-      "native_usb": true,
-      "use_1200bps_touch": true,
-      "wait_for_upload_port": false,
-      "protocol": "cmsis-dap",
-      "protocols": [
-        "blackmagic",
-        "cmsis-dap",
-        "jlink",
-        "raspberrypi-swd",
-        "picotool",
-        "picoprobe",
-        "pico-debug"
-      ]
-    },
-    "url": "http://zuluscsi.com",
-    "vendor": "Rabbit Hole Computing LLC"
-  }
-  

BIN
docs/ZuluSCSI_RP2040_buttons.jpg


BIN
docs/ZuluSCSI_RP2040_compact_buttons.jpg


BIN
docs/ZuluSCSI_v1_1_buttons.jpg


+ 0 - 8
greenpak/README.md

@@ -1,8 +0,0 @@
-GreenPAK design files
-=====================
-
-This folder contains design files for `SLG46824` programmable logic device.
-It is optionally used on ZuluSCSI V1.1 to speed up access to SCSI bus. This applies to asynchronous transfers only
-
-What this logic does is implement the `REQ` / `ACK` handshake in hardware.
-The CPU only has to write new data to the GPIO, and the external logic will toggle `REQ` signal quickly.

+ 0 - 647
greenpak/SCSI_Accelerator_SLG46824.gp6

@@ -1,647 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<GPDProject version="22" oldestCompatibleVersion="22" GPDVersion="6.27.001" lastChange="11.4.2022 12.26">
-    <generalProjectSettings/>
-    <chip family="04" type="06" friendlyName="GreenPAK 6" partNumber="40" package="16">
-        <nvmData registerLenght="2048">C4 9 0 0 0 0 0 0 38 C2 0 0 0 0 0 0 0 0 0 0 0 0 D0 8 13 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 E7 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 30 70 0 30 20 30 30 0 0 30 30 30 0 30 30 30 30 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 14 22 30 C 0 0 0 0 0 0 0 6 0 0 0 0 0 0 0 0 0 40 0 0 0 0 0 0 D7 14 20 0 1 0 0 0 2 1 0 0 2 0 1 0 0 2 1 0 0 2 0 1 0 0 2 1 0 0 2 0 1 0 0 2 0 1 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 A5</nvmData>
-        <checksum crc32="0xB44E9FD4" version="5"/>
-        <VDDItem id="0">
-            <item id="0" caption="VDD (PIN 20)">
-                <graphics pos="(-590.00,30.00)" angle="0" flipping="0" hidden="0" tOrigin="(20.00,10.00)"/>
-            </item>
-        </VDDItem>
-        <IOPad id="1" useCaseMode="0">
-            <item id="1" caption="PIN 19 (IO0)">
-                <graphics pos="(-590.00,100.00)" angle="0" flipping="0" hidden="0" tOrigin="(20.00,10.00)"/>
-                <textLabel pos="(-19.10,-27.00)" angle="0.00" textColor="#ffff00ff" backgroundColor="#14141464">PLD_IO0 / CLK</textLabel>
-            </item>
-        </IOPad>
-        <IOPad id="2" useCaseMode="1">
-            <item id="2" caption="PIN 18 (IO1)">
-                <graphics pos="(-248.00,278.00)" angle="0" flipping="0" hidden="0" tOrigin="(20.00,10.00)"/>
-                <textLabel pos="(-45.56,-27.00)" angle="0.00" textColor="#ffff00ff" backgroundColor="#14141464">PLD_IO1 / DATA_TOGGLE</textLabel>
-            </item>
-        </IOPad>
-        <IOPad id="3" useCaseMode="1">
-            <item id="3" caption="PIN 17 (IO2)">
-                <graphics pos="(-251.00,504.00)" angle="0" flipping="0" hidden="0" tOrigin="(20.00,10.00)"/>
-                <textLabel pos="(-29.23,-27.00)" angle="0.00" textColor="#ffff00ff" backgroundColor="#14141464">PLD_IO2 / ENABLE</textLabel>
-            </item>
-        </IOPad>
-        <IOPad id="4" useCaseMode="1">
-            <item id="4" caption="PIN 16 (IO3)">
-                <graphics pos="(-249.00,197.00)" angle="0" flipping="0" hidden="0" tOrigin="(20.00,10.00)"/>
-                <textLabel pos="(-25.28,-27.00)" angle="0.00" textColor="#ffff00ff" backgroundColor="#14141464">PLD_IO3 / RDWR</textLabel>
-            </item>
-        </IOPad>
-        <IOPad id="5" useCaseMode="0">
-            <item id="5" caption="PIN 15 (IO4)">
-                <graphics pos="(-590.00,380.00)" angle="0" flipping="0" hidden="0" tOrigin="(20.00,10.00)"/>
-                <textLabel pos="(-4.71,-27.00)" angle="0.00" textColor="#ffff00ff" backgroundColor="#14141464">PLD_IO4</textLabel>
-            </item>
-        </IOPad>
-        <IOPad id="6" useCaseMode="0">
-            <item id="6" caption="PIN 14 (IO5)">
-                <graphics pos="(-595.00,464.00)" angle="0" flipping="0" hidden="0" tOrigin="(20.00,10.00)"/>
-                <textLabel pos="(-4.71,-27.00)" angle="0.00" textColor="#ffff00ff" backgroundColor="#14141464">PLD_IO5</textLabel>
-            </item>
-        </IOPad>
-        <IOPad id="7" useCaseMode="1">
-            <item id="7" caption="PIN 13 (SCL)">
-                <graphics pos="(-764.00,671.00)" angle="0" flipping="0" hidden="0" tOrigin="(20.00,10.00)"/>
-            </item>
-        </IOPad>
-        <IOPad id="8" useCaseMode="1">
-            <item id="8" caption="PIN 12 (SDA)">
-                <graphics pos="(-764.00,701.00)" angle="0" flipping="0" hidden="0" tOrigin="(20.00,10.00)"/>
-            </item>
-        </IOPad>
-        <IOPad id="9" useCaseMode="0">
-            <item id="9" caption="PIN 11 (IO6)">
-                <graphics pos="(149.00,672.00)" angle="270" flipping="2" hidden="0" tOrigin="(20.00,10.00)"/>
-            </item>
-        </IOPad>
-        <item id="10" caption="GND (PIN 10)">
-            <graphics pos="(770.00,380.00)" angle="0" flipping="1" hidden="0" tOrigin="(20.00,10.00)"/>
-        </item>
-        <IOPad id="11" useCaseMode="0">
-            <item id="11" caption="PIN 9 (IO7)">
-                <graphics pos="(758.00,300.00)" angle="0" flipping="1" hidden="0" tOrigin="(20.00,10.00)"/>
-            </item>
-        </IOPad>
-        <IOPad id="12" useCaseMode="0">
-            <item id="12" caption="PIN 8 (IO8)">
-                <graphics pos="(692.00,505.00)" angle="0" flipping="1" hidden="0" tOrigin="(20.00,10.00)"/>
-                <textLabel pos="(-4.71,-27.00)" angle="0.00" textColor="#ffff00ff" backgroundColor="#14141464">PLD_IO8</textLabel>
-            </item>
-        </IOPad>
-        <VDDItem id="13">
-            <item id="13" caption="VDD2 (PIN 7)">
-                <graphics pos="(770.00,170.00)" angle="0" flipping="1" hidden="0" tOrigin="(20.00,10.00)"/>
-            </item>
-        </VDDItem>
-        <IOPad id="14" useCaseMode="0">
-            <item id="14" caption="PIN 6 (IO9)">
-                <graphics pos="(636.00,631.00)" angle="0" flipping="1" hidden="0" tOrigin="(20.00,10.00)"/>
-                <textLabel pos="(-4.71,-27.00)" angle="0.00" textColor="#ffff00ff" backgroundColor="#14141464">PLD_IO9</textLabel>
-            </item>
-        </IOPad>
-        <IOPad id="15" useCaseMode="0">
-            <item id="15" caption="PIN 5 (IO10)">
-                <graphics pos="(770.00,30.00)" angle="0" flipping="1" hidden="0" tOrigin="(20.00,10.00)"/>
-            </item>
-        </IOPad>
-        <IOPad id="16" useCaseMode="0">
-            <item id="16" caption="PIN 4 (IO11)">
-                <graphics pos="(300.00,-90.00)" angle="270" flipping="1" hidden="0" tOrigin="(20.00,10.00)"/>
-            </item>
-        </IOPad>
-        <IOPad id="17" useCaseMode="0">
-            <item id="17" caption="PIN 3 (IO12)">
-                <graphics pos="(150.00,-90.00)" angle="270" flipping="1" hidden="0" tOrigin="(20.00,10.00)"/>
-            </item>
-        </IOPad>
-        <IOPad id="18" useCaseMode="4">
-            <item id="18" caption="PIN 2 (IO13)">
-                <graphics pos="(411.00,320.00)" angle="0" flipping="1" hidden="0" tOrigin="(20.00,10.00)"/>
-                <textLabel pos="(-7.69,-27.00)" angle="0.00" textColor="#ffff00ff" backgroundColor="#14141464">OUT_REQ</textLabel>
-            </item>
-        </IOPad>
-        <IOPad id="19" useCaseMode="1">
-            <item id="19" caption="PIN 1 (IO14)">
-                <graphics pos="(-250.00,387.00)" angle="0" flipping="0" hidden="0" tOrigin="(20.00,10.00)"/>
-                <textLabel pos="(-6.55,-27.00)" angle="0.00" textColor="#ffff00ff" backgroundColor="#14141464">ACK_BUF</textLabel>
-            </item>
-        </IOPad>
-        <item id="22" caption="A CMP0L">
-            <graphics pos="(50.00,130.00)" angle="0" flipping="0" hidden="1" tOrigin="(25.00,28.00)"/>
-        </item>
-        <item id="23" caption="A CMP1L">
-            <graphics pos="(150.00,130.00)" angle="0" flipping="0" hidden="1" tOrigin="(25.00,28.00)"/>
-        </item>
-        <item id="24" caption="P DLY">
-            <graphics pos="(320.00,320.00)" angle="0" flipping="0" hidden="1" tOrigin="(17.50,10.00)"/>
-        </item>
-        <item id="26" caption="VREF">
-            <graphics pos="(320.00,190.00)" angle="0" flipping="0" hidden="1" tOrigin="(17.50,10.00)"/>
-        </item>
-        <item id="27" caption="POR">
-            <graphics pos="(320.00,260.00)" angle="0" flipping="0" hidden="1" tOrigin="(17.50,10.00)"/>
-        </item>
-        <item id="28" caption="OSC0">
-            <graphics pos="(-70.00,100.00)" angle="0" flipping="0" hidden="1" tOrigin="(30.00,40.00)"/>
-        </item>
-        <item id="29" caption="OSC1">
-            <graphics pos="(-70.00,200.00)" angle="0" flipping="0" hidden="1" tOrigin="(30.00,25.00)"/>
-        </item>
-        <item id="30" caption="OSC2">
-            <graphics pos="(-70.00,270.00)" angle="0" flipping="0" hidden="1" tOrigin="(30.00,20.00)"/>
-        </item>
-        <item id="31" caption="I2C">
-            <graphics pos="(-674.00,652.00)" angle="0" flipping="0" hidden="0" tOrigin="(25.00,45.00)"/>
-        </item>
-        <item id="33" caption="FILTER/EDGE DET">
-            <graphics pos="(320.00,440.00)" angle="0" flipping="0" hidden="1" tOrigin="(27.50,15.00)"/>
-        </item>
-        <item id="34" caption="BG">
-            <graphics pos="(320.00,30.00)" angle="0" flipping="0" hidden="1" tOrigin="(17.50,10.00)"/>
-        </item>
-        <LUT id="35" regularShape="0" mode="0">
-            <item id="35" caption="2-bit LUT0/DFF/LATCH0">
-                <graphics pos="(-88.00,177.00)" angle="90" flipping="0" hidden="0" tOrigin="(20.00,15.00)"/>
-            </item>
-        </LUT>
-        <LUT id="36" regularShape="0" mode="0">
-            <item id="36" caption="2-bit LUT1/DFF/LATCH1">
-                <graphics pos="(40.00,370.00)" angle="90" flipping="0" hidden="1" tOrigin="(20.00,15.00)"/>
-            </item>
-        </LUT>
-        <LUT id="37" regularShape="0" mode="0">
-            <item id="37" caption="2-bit LUT2/DFF/LATCH2">
-                <graphics pos="(40.00,430.00)" angle="90" flipping="0" hidden="1" tOrigin="(20.00,15.00)"/>
-            </item>
-        </LUT>
-        <LUT id="38" regularShape="0" mode="0">
-            <item id="38" caption="2-bit LUT3/PGEN">
-                <graphics pos="(130.00,250.00)" angle="90" flipping="0" hidden="1" tOrigin="(20.00,15.00)"/>
-            </item>
-        </LUT>
-        <LUT id="39" regularShape="0" mode="0">
-            <item id="39" caption="3-bit LUT0/DFF/LATCH3">
-                <graphics pos="(130.00,310.00)" angle="90" flipping="1" hidden="1" tOrigin="(20.00,15.00)"/>
-            </item>
-        </LUT>
-        <item id="40" caption="3-bit LUT1/DFF/LATCH4">
-            <graphics pos="(19.00,176.00)" angle="0" flipping="0" hidden="0" tOrigin="(25.00,10.00)"/>
-            <textLabel pos="(-15.00,-40.00)" angle="0.00" textColor="#ffff00ff" backgroundColor="#14141464">Previous
-DATA_TOGGLE</textLabel>
-        </item>
-        <LUT id="41" regularShape="0" mode="0">
-            <item id="41" caption="3-bit LUT2/DFF/LATCH5">
-                <graphics pos="(130.00,430.00)" angle="90" flipping="0" hidden="1" tOrigin="(20.00,15.00)"/>
-            </item>
-        </LUT>
-        <LUT id="42" regularShape="0" mode="0">
-            <item id="42" caption="3-bit LUT3/DFF/LATCH6">
-                <graphics pos="(210.00,250.00)" angle="90" flipping="0" hidden="1" tOrigin="(20.00,15.00)"/>
-            </item>
-        </LUT>
-        <LUT id="43" regularShape="0" mode="0">
-            <item id="43" caption="3-bit LUT4/DFF/LATCH7">
-                <graphics pos="(210.00,310.00)" angle="90" flipping="0" hidden="1" tOrigin="(20.00,15.00)"/>
-            </item>
-        </LUT>
-        <LUT id="44" regularShape="0" mode="0">
-            <item id="44" caption="3-bit LUT5/DFF/LATCH8">
-                <graphics pos="(210.00,370.00)" angle="90" flipping="0" hidden="1" tOrigin="(20.00,15.00)"/>
-            </item>
-        </LUT>
-        <LUT id="45" regularShape="0" mode="0">
-            <item id="45" caption="3-bit LUT6/Pipe Delay/Ripple Counter">
-                <graphics pos="(210.00,430.00)" angle="90" flipping="0" hidden="1" tOrigin="(20.00,15.00)"/>
-            </item>
-        </LUT>
-        <item id="46" caption="MF0 (4-bit LUT0, DFF/LATCH9, 16-bit CNT0/DLY0/FSM0)">
-            <graphics pos="(-399.00,35.00)" angle="0" flipping="0" hidden="1" tOrigin="(155.00,60.00)"/>
-        </item>
-        <item id="47" caption="MF1 (3-bit LUT7, DFF/LATCH10, 8-bit CNT1/DLY1)">
-            <graphics pos="(-500.00,140.00)" angle="0" flipping="0" hidden="1" tOrigin="(155.00,60.00)"/>
-        </item>
-        <item id="48" caption="MF2 (3-bit LUT8, DFF/LATCH11, 8-bit CNT2/DLY2)">
-            <graphics pos="(-500.00,300.00)" angle="0" flipping="0" hidden="1" tOrigin="(155.00,60.00)"/>
-        </item>
-        <item id="49" caption="MF3 (3-bit LUT9, DFF/LATCH12, 8-bit CNT3/DLY3)">
-            <graphics pos="(-500.00,460.00)" angle="0" flipping="0" hidden="1" tOrigin="(155.00,60.00)"/>
-        </item>
-        <item id="50" caption="MF4 (3-bit LUT10, DFF/LATCH13, 8-bit CNT4/DLY4)">
-            <graphics pos="(430.00,-30.00)" angle="0" flipping="0" hidden="1" tOrigin="(155.00,60.00)"/>
-        </item>
-        <item id="51" caption="MF5 (3-bit LUT11, DFF/LATCH14, 8-bit CNT5/DLY5)">
-            <graphics pos="(430.00,130.00)" angle="0" flipping="0" hidden="1" tOrigin="(155.00,60.00)"/>
-        </item>
-        <item id="52" caption="MF6 (3-bit LUT12, DFF/LATCH15, 8-bit CNT6/DLY6)">
-            <graphics pos="(430.00,290.00)" angle="0" flipping="0" hidden="1" tOrigin="(155.00,60.00)"/>
-        </item>
-        <item id="53" caption="MF7 (3-bit LUT13, DFF/LATCH16, 8-bit CNT7/DLY7)">
-            <graphics pos="(430.00,450.00)" angle="0" flipping="0" hidden="1" tOrigin="(155.00,60.00)"/>
-        </item>
-        <LUT id="54" regularShape="0" mode="0">
-            <item id="54" caption="4-bit LUT0 (MF0)">
-                <graphics pos="(136.00,310.00)" angle="90" flipping="0" hidden="0" tOrigin="(20.00,15.00)"/>
-                <textLabel pos="(46.00,52.19)" angle="-90.00" textColor="#ffff00ff" backgroundColor="#14141464">IN3 = 0 (Write to SCSI bus): !(IN0 &amp; (IN1 ^ IN2))
-IN3 = 1 (Read from SCSI bus): (!IN0) &amp; (IN1 ^ IN2)</textLabel>
-            </item>
-        </LUT>
-        <item id="55" caption="DFF/LATCH9 (MF0)">
-            <graphics pos="(-357.50,94.50)" angle="0" flipping="0" hidden="1" tOrigin="(25.00,10.00)"/>
-        </item>
-        <CNTDLY id="56" externalClockFrequence="0" externalClockFreqUnit="kHz">
-            <item id="56" caption="16-bit CNT0/DLY0/FSM0 (MF0)">
-                <graphics pos="(-208.50,87.50)" angle="0" flipping="0" hidden="1" tOrigin="(35.00,16.00)"/>
-            </item>
-        </CNTDLY>
-        <LUT id="57" regularShape="0" mode="0">
-            <item id="57" caption="3-bit LUT7 (MF1)">
-                <graphics pos="(-365.00,185.00)" angle="90" flipping="0" hidden="1" tOrigin="(20.00,15.00)"/>
-            </item>
-        </LUT>
-        <item id="58" caption="DFF/LATCH10 (MF1)">
-            <graphics pos="(-450.00,130.00)" angle="0" flipping="0" hidden="1" tOrigin="(25.00,10.00)"/>
-        </item>
-        <CNTDLY id="59" externalClockFrequence="0" externalClockFreqUnit="kHz">
-            <item id="59" caption="8-bit CNT1/DLY1 (MF1)">
-                <graphics pos="(-450.00,130.00)" angle="0" flipping="0" hidden="1" tOrigin="(30.00,16.00)"/>
-            </item>
-        </CNTDLY>
-        <LUT id="60" regularShape="0" mode="0">
-            <item id="60" caption="3-bit LUT8 (MF2)">
-                <graphics pos="(-365.00,345.00)" angle="90" flipping="0" hidden="1" tOrigin="(20.00,15.00)"/>
-            </item>
-        </LUT>
-        <item id="61" caption="DFF/LATCH11 (MF2)">
-            <graphics pos="(-550.00,300.00)" angle="0" flipping="0" hidden="1" tOrigin="(25.00,10.00)"/>
-        </item>
-        <CNTDLY id="62" externalClockFrequence="0" externalClockFreqUnit="kHz">
-            <item id="62" caption="8-bit CNT2/DLY2 (MF2)">
-                <graphics pos="(-550.00,300.00)" angle="0" flipping="0" hidden="1" tOrigin="(30.00,16.00)"/>
-            </item>
-        </CNTDLY>
-        <LUT id="63" regularShape="0" mode="0">
-            <item id="63" caption="3-bit LUT9 (MF3)">
-                <graphics pos="(-365.00,505.00)" angle="90" flipping="0" hidden="1" tOrigin="(20.00,15.00)"/>
-            </item>
-        </LUT>
-        <item id="64" caption="DFF/LATCH12 (MF3)">
-            <graphics pos="(-730.00,460.00)" angle="0" flipping="0" hidden="1" tOrigin="(25.00,10.00)"/>
-        </item>
-        <CNTDLY id="65" externalClockFrequence="0" externalClockFreqUnit="kHz">
-            <item id="65" caption="8-bit CNT3/DLY3 (MF3)">
-                <graphics pos="(-730.00,460.00)" angle="0" flipping="0" hidden="1" tOrigin="(30.00,16.00)"/>
-            </item>
-        </CNTDLY>
-        <LUT id="66" regularShape="0" mode="0">
-            <item id="66" caption="3-bit LUT10 (MF4)">
-                <graphics pos="(565.00,15.00)" angle="90" flipping="0" hidden="1" tOrigin="(20.00,15.00)"/>
-            </item>
-        </LUT>
-        <item id="67" caption="DFF/LATCH13 (MF4)">
-            <graphics pos="(660.00,-210.00)" angle="0" flipping="0" hidden="1" tOrigin="(25.00,10.00)"/>
-        </item>
-        <CNTDLY id="68" externalClockFrequence="0" externalClockFreqUnit="kHz">
-            <item id="68" caption="8-bit CNT4/DLY4 (MF4)">
-                <graphics pos="(660.00,-210.00)" angle="0" flipping="0" hidden="1" tOrigin="(30.00,16.00)"/>
-            </item>
-        </CNTDLY>
-        <LUT id="69" regularShape="0" mode="0">
-            <item id="69" caption="3-bit LUT11 (MF5)">
-                <graphics pos="(565.00,175.00)" angle="90" flipping="0" hidden="1" tOrigin="(20.00,15.00)"/>
-            </item>
-        </LUT>
-        <item id="70" caption="DFF/LATCH14 (MF5)">
-            <graphics pos="(500.00,-50.00)" angle="0" flipping="0" hidden="1" tOrigin="(25.00,10.00)"/>
-        </item>
-        <CNTDLY id="71" externalClockFrequence="0" externalClockFreqUnit="kHz">
-            <item id="71" caption="8-bit CNT5/DLY5 (MF5)">
-                <graphics pos="(500.00,-50.00)" angle="0" flipping="0" hidden="1" tOrigin="(30.00,16.00)"/>
-            </item>
-        </CNTDLY>
-        <LUT id="72" regularShape="0" mode="0">
-            <item id="72" caption="3-bit LUT12 (MF6)">
-                <graphics pos="(565.00,335.00)" angle="90" flipping="0" hidden="1" tOrigin="(20.00,15.00)"/>
-            </item>
-        </LUT>
-        <item id="73" caption="DFF/LATCH15 (MF6)">
-            <graphics pos="(330.00,110.00)" angle="0" flipping="0" hidden="1" tOrigin="(25.00,10.00)"/>
-        </item>
-        <CNTDLY id="74" externalClockFrequence="0" externalClockFreqUnit="kHz">
-            <item id="74" caption="8-bit CNT6/DLY6 (MF6)">
-                <graphics pos="(330.00,110.00)" angle="0" flipping="0" hidden="1" tOrigin="(30.00,16.00)"/>
-            </item>
-        </CNTDLY>
-        <LUT id="75" regularShape="0" mode="0">
-            <item id="75" caption="3-bit LUT13 (MF7)">
-                <graphics pos="(565.00,495.00)" angle="90" flipping="0" hidden="1" tOrigin="(20.00,15.00)"/>
-            </item>
-        </LUT>
-        <item id="76" caption="DFF/LATCH16 (MF7)">
-            <graphics pos="(170.00,270.00)" angle="0" flipping="0" hidden="1" tOrigin="(25.00,10.00)"/>
-        </item>
-        <CNTDLY id="77" externalClockFrequence="0" externalClockFreqUnit="kHz">
-            <item id="77" caption="8-bit CNT7/DLY7 (MF7)">
-                <graphics pos="(170.00,270.00)" angle="0" flipping="0" hidden="1" tOrigin="(30.00,16.00)"/>
-            </item>
-        </CNTDLY>
-        <wire output="147" input="111" autoRouting="1" pen="#ff8000ff;1.00;1;32;128" lineType="2" protected="1" CWLid="0" wireText="NET0" wireState="0">
-            <points>(-702.00,682.00); (-695.00,682.00)</points>
-        </wire>
-        <wire output="148" input="112" autoRouting="1" pen="#ff8000ff;1.00;1;32;128" lineType="2" protected="1" CWLid="1" wireText="NET1" wireState="0">
-            <points>(-702.00,712.00); (-695.00,712.00)</points>
-        </wire>
-        <wire output="143" input="537" autoRouting="1" pen="#00ff00ff;1.00;1;32;128" lineType="1" protected="0" CWLid="10" wireText="NET10" wireState="0">
-            <points>(-189.00,520.00); (432.00,520.00); (432.00,360.00)</points>
-        </wire>
-        <wire output="143" input="553" autoRouting="1" pen="#00ff00ff;1.00;1;32;128" lineType="1" protected="0" CWLid="10" wireText="NET10" wireState="0">
-            <points>(-189.00,520.00); (45.00,520.00); (45.00,216.00)</points>
-        </wire>
-        <wire output="142" input="552" autoRouting="1" pen="#00ff00ff;1.00;1;32;128" lineType="1" protected="0" CWLid="8" wireText="NET8" wireState="0">
-            <points>(-186.00,294.00); (-13.00,294.00); (-13.00,182.00); (-2.00,182.00)</points>
-        </wire>
-        <wire output="157" input="621" autoRouting="1" pen="#00ff00ff;1.00;1;32;128" lineType="1" protected="0" CWLid="7" wireText="NET7" wireState="0">
-            <points>(-188.00,403.00); (105.00,403.00); (105.00,341.00); (120.00,341.00)</points>
-        </wire>
-        <wire output="142" input="622" autoRouting="1" pen="#00ff00ff;1.00;1;32;128" lineType="1" protected="0" CWLid="8" wireText="NET8" wireState="0">
-            <points>(-186.00,294.00); (105.00,294.00); (105.00,331.00); (120.00,331.00)</points>
-        </wire>
-        <wire output="162" input="623" autoRouting="1" pen="#00ff00ff;1.00;1;32;128" lineType="1" protected="0" CWLid="11" wireText="NET11" wireState="0">
-            <points>(89.00,186.00); (114.00,186.00); (114.00,321.00); (120.00,321.00)</points>
-        </wire>
-        <wire output="191" input="536" autoRouting="1" pen="#00ff00ff;1.00;1;32;128" lineType="1" protected="0" CWLid="9" wireText="NET9" wireState="0">
-            <points>(191.00,326.00); (388.00,326.00)</points>
-        </wire>
-        <wire output="144" input="624" autoRouting="1" pen="#00ff00ff;1.00;1;32;128" lineType="1" protected="0" CWLid="12" wireText="NET12" wireState="0">
-            <points>(-187.00,213.00); (-127.00,213.00); (-127.00,311.00); (120.00,311.00)</points>
-        </wire>
-        <wire output="84" input="551" autoRouting="1" pen="#00ff00ff;1.00;1;32;128" lineType="1" protected="0" CWLid="13" wireText="NET13" wireState="0">
-            <points>(-30.00,192.00); (-2.00,192.00)</points>
-        </wire>
-        <wire output="191" input="262" autoRouting="1" pen="#00ff00ff;1.00;1;32;128" lineType="1" protected="0" CWLid="9" wireText="NET9" wireState="0">
-            <points>(191.00,326.00); (213.00,326.00); (213.00,113.00); (-123.00,113.00); (-123.00,184.00); (-107.00,184.00)</points>
-        </wire>
-        <wire output="144" input="261" autoRouting="1" pen="#00ff00ff;1.00;1;32;128" lineType="1" protected="0" CWLid="12" wireText="NET12" wireState="0">
-            <points>(-187.00,213.00); (-126.00,213.00); (-126.00,200.00); (-107.00,200.00)</points>
-        </wire>
-    </chip>
-    <emulatorConfiguration version="1">
-        <settings>
-            <autoApply value="0"/>
-            <platformSelector id="3"/>
-        </settings>
-        <platform id="0" friendlyName="GreenPAK DIP Development Platform">
-            <lastConfiguration modified="0">
-                <SaveEmulator Name="Default">
-                    <PowerOptions synced="0"/>
-                    <PowerSwitch internalPower="1" externalPower="0"/>
-                    <ExpansionConnector></ExpansionConnector>
-                    <TestPoints/>
-                    <I2C slaveAddress="-1"/>
-                </SaveEmulator>
-            </lastConfiguration>
-            <savedConfigurations/>
-        </platform>
-        <platform id="1" friendlyName="GreenPAK Advanced Development Platform">
-            <lastConfiguration modified="0">
-                <SaveEmulator Name="Default">
-                    <PowerOptions synced="0"/>
-                    <PowerSwitch internalPower="1" externalPower="0"/>
-                    <ExpansionConnector></ExpansionConnector>
-                    <TestPoints/>
-                    <I2C slaveAddress="-1"/>
-                </SaveEmulator>
-            </lastConfiguration>
-            <savedConfigurations/>
-        </platform>
-        <platform id="2" friendlyName="GreenPAK Pro Development Platform">
-            <lastConfiguration modified="0">
-                <SaveEmulator Name="Default">
-                    <PowerOptions synced="0"/>
-                    <PowerSwitch internalPower="1" externalPower="0"/>
-                    <ExpansionConnector></ExpansionConnector>
-                    <TestPoints/>
-                    <I2C slaveAddress="-1"/>
-                </SaveEmulator>
-            </lastConfiguration>
-            <savedConfigurations/>
-        </platform>
-        <platform id="4" friendlyName="GreenPAK Serial Debugger">
-            <lastConfiguration modified="0">
-                <SaveEmulator Name="Default">
-                    <PowerOptions synced="0"/>
-                    <PowerSwitch internalPower="1" externalPower="0"/>
-                    <ExpansionConnector></ExpansionConnector>
-                    <TestPoints/>
-                    <I2C slaveAddress="-1"/>
-                </SaveEmulator>
-            </lastConfiguration>
-            <savedConfigurations/>
-        </platform>
-        <platform id="5" friendlyName="GreenPAK Advanced Development Platform w/ Logic Level Adapter #1">
-            <lastConfiguration modified="0">
-                <SaveEmulator Name="Default">
-                    <PowerOptions synced="0"/>
-                    <PowerSwitch internalPower="1" externalPower="0"/>
-                    <ExpansionConnector></ExpansionConnector>
-                    <TestPoints/>
-                    <I2C slaveAddress="-1"/>
-                </SaveEmulator>
-            </lastConfiguration>
-            <savedConfigurations/>
-        </platform>
-        <platform id="6" friendlyName="ForgeFPGA Development Platform">
-            <lastConfiguration modified="0">
-                <SaveEmulator Name="Default">
-                    <PowerOptions synced="0"/>
-                    <PowerSwitch internalPower="1" externalPower="0"/>
-                    <ExpansionConnector></ExpansionConnector>
-                    <TestPoints/>
-                    <I2C slaveAddress="-1"/>
-                </SaveEmulator>
-            </lastConfiguration>
-            <savedConfigurations/>
-        </platform>
-    </emulatorConfiguration>
-    <simulationConfiguration version="13" compatibleVersion="13" activePreset="-1">
-        <draftPreset>
-            <simulationPreset index="-1" name="Default" customGroupLayout="false" customParametricDcGroupLayout="false">
-                <transientAnalyses>
-                    <transientAnalysis stopTime="12m" maxTimeStep="20u" startTime="0" stepTime="20u" temperature="25" useInitialConditions="false" vdd="3.3"/>
-                </transientAnalyses>
-                <parametricDcAnalyses/>
-                <pinProbes>
-                    <pinProbe instrumentId="0" measurementFlags="1">
-                        <IdDto category="5" componentType="43" componentNumber="1" pinNumber="0"/>
-                    </pinProbe>
-                    <pinProbe instrumentId="1" measurementFlags="1">
-                        <IdDto category="5" componentType="43" componentNumber="2" pinNumber="0"/>
-                    </pinProbe>
-                </pinProbes>
-                <groups/>
-                <parametricDcGroups/>
-                <waveforms/>
-                <components>
-                    <component simulationModel="">
-                        <componentId category="5" componentType="0" componentNumber="1"/>
-                        <componentSpec manufacturer="" partNumber=""/>
-                        <componentUiSettings isFlippedHorizontally="false" isFlippedVertically="false" visible="true" position="(-818.116;93.379)" rotationState="0" sceneIndex="0"/>
-                        <schematicProps>
-                            <param id="name" affinity="4" value="GND"/>
-                        </schematicProps>
-                        <instanceProps/>
-                    </component>
-                    <component simulationModel="">
-                        <componentId category="5" componentType="0" componentNumber="2"/>
-                        <componentSpec manufacturer="" partNumber=""/>
-                        <componentUiSettings isFlippedHorizontally="false" isFlippedVertically="false" visible="true" position="(1005.89;233.679)" rotationState="0" sceneIndex="0"/>
-                        <schematicProps>
-                            <param id="name" affinity="4" value="GND"/>
-                        </schematicProps>
-                        <instanceProps/>
-                    </component>
-                    <component simulationModel="">
-                        <componentId category="5" componentType="0" componentNumber="3"/>
-                        <componentSpec manufacturer="" partNumber=""/>
-                        <componentUiSettings isFlippedHorizontally="false" isFlippedVertically="false" visible="true" position="(848.494;443.262)" rotationState="0" sceneIndex="0"/>
-                        <schematicProps>
-                            <param id="name" affinity="4" value="GND"/>
-                        </schematicProps>
-                        <instanceProps/>
-                    </component>
-                    <component simulationModel="">
-                        <componentId category="5" componentType="43" componentNumber="1"/>
-                        <componentSpec manufacturer="" partNumber=""/>
-                        <componentUiSettings isFlippedHorizontally="false" isFlippedVertically="false" visible="true" position="(-749.099;19.6022)" rotationState="0" sceneIndex="0"/>
-                        <schematicProps>
-                            <param id="name" affinity="4" value="V1"/>
-                            <param id="has_rc" affinity="1" value="1"/>
-                            <param id="int_r" affinity="3" value="10"/>
-                            <param id="int_c" affinity="3" value="100n"/>
-                            <param id="show_one_period" affinity="1" value="0"/>
-                            <param id="has_limited_voltage" affinity="1" value="0"/>
-                            <param id="dc_analysis_voltage" affinity="3" value="3.3"/>
-                            <param id="signal_type" affinity="1" value="1"/>
-                            <param id="prestart_delay" affinity="3" value="0"/>
-                            <param id="ramp_voltage" affinity="3" value="3.3"/>
-                            <param id="ramp_rise_time" affinity="3" value="1m"/>
-                        </schematicProps>
-                        <instanceProps/>
-                    </component>
-                    <component simulationModel="">
-                        <componentId category="5" componentType="43" componentNumber="2"/>
-                        <componentSpec manufacturer="" partNumber=""/>
-                        <componentUiSettings isFlippedHorizontally="true" isFlippedVertically="false" visible="true" position="(926.958;159.848)" rotationState="0" sceneIndex="0"/>
-                        <schematicProps>
-                            <param id="name" affinity="4" value="V2"/>
-                            <param id="has_rc" affinity="1" value="1"/>
-                            <param id="int_r" affinity="3" value="10"/>
-                            <param id="int_c" affinity="3" value="100n"/>
-                            <param id="show_one_period" affinity="1" value="0"/>
-                            <param id="has_limited_voltage" affinity="1" value="1"/>
-                            <param id="dc_analysis_voltage" affinity="3" value="3.3"/>
-                            <param id="signal_type" affinity="1" value="1"/>
-                            <param id="prestart_delay" affinity="3" value="0"/>
-                            <param id="ramp_voltage" affinity="3" value="3.3"/>
-                            <param id="ramp_rise_time" affinity="3" value="1m"/>
-                        </schematicProps>
-                        <instanceProps/>
-                    </component>
-                </components>
-                <networks>
-                    <network networkId="6" name="NET6">
-                        <connections>
-                            <connection connectionType="0" routingType="0" sceneIndex="0">
-                                <from>
-                                    <IdDto category="5" componentType="43" componentNumber="1" pinNumber="1"/>
-                                </from>
-                                <to>
-                                    <IdDto category="5" componentType="0" componentNumber="1" pinNumber="0"/>
-                                </to>
-                                <path>
-                                    <point value="(-771;41)"/>
-                                    <point value="(-802;41)"/>
-                                    <point value="(-802;71)"/>
-                                </path>
-                            </connection>
-                        </connections>
-                    </network>
-                    <network networkId="5" name="NET5">
-                        <connections>
-                            <connection connectionType="0" routingType="0" sceneIndex="0">
-                                <from>
-                                    <IdDto category="5" componentType="0" componentNumber="3" pinNumber="0"/>
-                                </from>
-                                <to>
-                                    <IdDto category="100" componentType="45" componentNumber="0" pinNumber="10"/>
-                                </to>
-                                <path>
-                                    <point value="(864;421)"/>
-                                    <point value="(864;391)"/>
-                                    <point value="(832;391)"/>
-                                </path>
-                            </connection>
-                        </connections>
-                    </network>
-                    <network networkId="4" name="NET4">
-                        <connections>
-                            <connection connectionType="0" routingType="0" sceneIndex="0">
-                                <from>
-                                    <IdDto category="5" componentType="43" componentNumber="2" pinNumber="0"/>
-                                </from>
-                                <to>
-                                    <IdDto category="100" componentType="45" componentNumber="0" pinNumber="7"/>
-                                </to>
-                                <path>
-                                    <point value="(905;181)"/>
-                                    <point value="(832;181)"/>
-                                </path>
-                            </connection>
-                        </connections>
-                    </network>
-                    <network networkId="3" name="NET3">
-                        <connections>
-                            <connection connectionType="0" routingType="0" sceneIndex="0">
-                                <from>
-                                    <IdDto category="5" componentType="0" componentNumber="2" pinNumber="0"/>
-                                </from>
-                                <to>
-                                    <IdDto category="5" componentType="43" componentNumber="2" pinNumber="1"/>
-                                </to>
-                                <path>
-                                    <point value="(1022;212)"/>
-                                    <point value="(1022;181)"/>
-                                    <point value="(990;181)"/>
-                                </path>
-                            </connection>
-                        </connections>
-                    </network>
-                    <network networkId="2" name="NET2">
-                        <connections>
-                            <connection connectionType="0" routingType="0" sceneIndex="0">
-                                <from>
-                                    <IdDto category="5" componentType="43" componentNumber="1" pinNumber="0"/>
-                                </from>
-                                <to>
-                                    <IdDto category="100" componentType="45" componentNumber="0" pinNumber="20"/>
-                                </to>
-                                <path>
-                                    <point value="(-686;41)"/>
-                                    <point value="(-613;41)"/>
-                                </path>
-                            </connection>
-                        </connections>
-                    </network>
-                </networks>
-            </simulationPreset>
-        </draftPreset>
-        <simulationPresets/>
-    </simulationConfiguration>
-    <projectData>
-        <specs>
-            <lastModify lastModifyValue="01.02.2022 7:10:58"/>
-            <vddSpecs vddMin="2.8" vddTyp="3" vddMax="3.2"/>
-            <vdd2Specs vdd2Min="2.8" vdd2Typ="3" vdd2Max="3.2"/>
-            <tempSpecs tempMin="0" tempTyp="25" tempMax="40"/>
-        </specs>
-        <projectDataFields>
-            <textLineDataField name="Customer&#10;Name:" id="2" text=""/>
-            <textLineDataField name="Customer&#10;Project Name:" id="3" text=""/>
-            <textLineDataField name="Customer&#10;Project Number:" id="4" text=""/>
-            <textLineDataField name="Customer&#10;Version Number:" id="5" text=""/>
-            <multiTextLineDataField>
-                <textLineDataField name="Notes:" id="6" text=""/>
-            </multiTextLineDataField>
-        </projectDataFields>
-    </projectData>
-    <i2cTool>
-        <i2cDebugger version="1"/>
-        <i2cStepper version="1" rowCount="0"/>
-        <i2cRegsTable version="1" tabCount="0"/>
-    </i2cTool>
-</GPDProject>

+ 0 - 17
greenpak/SCSI_Accelerator_SLG46824.hex

@@ -1,17 +0,0 @@
-:10000000C40900000000000038C200000000000029
-:10001000000000000000D0081301000000000000F4
-:1000200000000000000000000000000000000000D0
-:1000300000000000000000000000000000000000C0
-:100040000000E700000000000000000000000000C9
-:1000500000000000000000000000000000000000A0
-:100060000030700030203030000030303000303050
-:100070003030000000000000000000000000000020
-:1000800000000000001422300C00000000000000FE
-:10009000060000000000000000004000000000001A
-:1000A00000D714200001000000020100000200013E
-:1000B0000000020100000200010000020100000235
-:1000C0000001000002000100000001010100000029
-:1000D0000000000000000000000000000000000020
-:1000E0000000000000000000000000000000000010
-:1000F000000000000000000000000000000000A55B
-:00000001FF

BIN
greenpak/SCSI_Accelerator_SLG46824.png


+ 2 - 2
lib/ZuluI2S/ZuluI2S.cpp → lib/BlueI2S/BlueI2S.cpp

@@ -19,8 +19,8 @@
     Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 */
 #include <Arduino.h>
-#include "ZuluI2S.h"
-#include "zulu_pio_i2s.pio.h"
+#include "BlueI2S.h"
+#include "blue_pio_i2s.pio.h"
 #include <pico/stdlib.h>
 
 

+ 0 - 0
lib/ZuluI2S/ZuluI2S.h → lib/BlueI2S/BlueI2S.h


+ 0 - 0
lib/ZuluI2S/zulu_pio_i2s.pio → lib/BlueI2S/blue_pio_i2s.pio


+ 0 - 0
lib/ZuluI2S/zulu_pio_i2s.pio.h → lib/BlueI2S/blue_pio_i2s.pio.h


+ 29 - 29
lib/ZuluSCSI_platform_RP2MCU/ZuluSCSI_platform.cpp → lib/BlueSCSI_platform_RP2MCU/BlueSCSI_platform.cpp

@@ -19,8 +19,8 @@
  * along with this program.  If not, see <https://www.gnu.org/licenses/>.
 **/
 
-#include "ZuluSCSI_platform.h"
-#include "ZuluSCSI_log.h"
+#include "BlueSCSI_platform.h"
+#include "BlueSCSI_log.h"
 #include <SdFat.h>
 #include <sdio.h>
 #include <scsi.h>
@@ -38,7 +38,7 @@
 #include <hardware/sync.h>
 #include "scsi_accel_target.h"
 #include "custom_timings.h"
-#include <ZuluSCSI_settings.h>
+#include <BlueSCSI_settings.h>
 
 #ifdef SD_USE_RP2350_SDIO
 #include <sdio_rp2350.h>
@@ -53,17 +53,17 @@
 
 #include <pico/multicore.h>
 
-#ifdef ZULUSCSI_NETWORK
+#ifdef BLUESCSI_NETWORK
 extern "C" {
 #  include <pico/cyw43_arch.h>
 }
-#  ifdef ZULUSCSI_RM2
+#  ifdef BLUESCSI_RM2
 #    include <pico/cyw43_driver.h>
 #  endif
-#endif // ZULUSCSI_NETWORK
+#endif // BLUESCSI_NETWORK
 
 #ifdef PLATFORM_MASS_STORAGE
-#include "ZuluSCSI_platform_msc.h"
+#include "BlueSCSI_platform_msc.h"
 #endif
 
 #ifdef ENABLE_AUDIO_OUTPUT_SPDIF
@@ -120,22 +120,22 @@ static void reclock() {
             48 * MHZ);
     // reset PLL
     pll_init(pll_sys,
-        g_zuluscsi_timings->pll.refdiv,
-        g_zuluscsi_timings->pll.vco_freq,
-        g_zuluscsi_timings->pll.post_div1,
-        g_zuluscsi_timings->pll.post_div2);
+        g_bluescsi_timings->pll.refdiv,
+        g_bluescsi_timings->pll.vco_freq,
+        g_bluescsi_timings->pll.post_div1,
+        g_bluescsi_timings->pll.post_div2);
 
     // switch clocks back to pll_sys
     clock_configure(clk_sys,
             CLOCKS_CLK_SYS_CTRL_SRC_VALUE_CLKSRC_CLK_SYS_AUX,
             CLOCKS_CLK_SYS_CTRL_AUXSRC_VALUE_CLKSRC_PLL_SYS,
-            g_zuluscsi_timings->clk_hz,
-            g_zuluscsi_timings->clk_hz);
+            g_bluescsi_timings->clk_hz,
+            g_bluescsi_timings->clk_hz);
     clock_configure(clk_peri,
             0,
             CLOCKS_CLK_PERI_CTRL_AUXSRC_VALUE_CLKSRC_PLL_SYS,
-            g_zuluscsi_timings->clk_hz,
-            g_zuluscsi_timings->clk_hz);
+            g_bluescsi_timings->clk_hz,
+            g_bluescsi_timings->clk_hz);
     // reset UART for the new clock speed
     if (uart_is_enabled(uart0))
         uart_init(uart0, 1000000);
@@ -146,7 +146,7 @@ uint32_t platform_sys_clock_in_hz()
     return clock_get_hz(clk_sys);
 }
 
-bool platform_reclock(zuluscsi_speed_grade_t speed_grade)
+bool platform_reclock(bluescsi_speed_grade_t speed_grade)
 {
     CustomTimings ct;
     bool do_reclock = false;
@@ -172,15 +172,15 @@ bool platform_reclock(zuluscsi_speed_grade_t speed_grade)
         if (do_reclock)
         {
 #ifdef  ENABLE_AUDIO_OUTPUT
-            if (g_zuluscsi_timings->audio.audio_clocked)
+            if (g_bluescsi_timings->audio.audio_clocked)
                 logmsg("Reclocking with these settings are compatible with CD audio playback");
             else
                 logmsg("Reclocking with these settings may cause audio playback to be too fast or slow ");
 #endif
             logmsg("Initial Clock set to ", (int) platform_sys_clock_in_hz(), "Hz");
-            logmsg("Reclocking the MCU to ",(int) g_zuluscsi_timings->clk_hz, "Hz");
+            logmsg("Reclocking the MCU to ",(int) g_bluescsi_timings->clk_hz, "Hz");
 #ifndef SD_USE_RP2350_SDIO
-            logmsg("Setting the SDIO clock to ", (int)((g_zuluscsi_timings->clk_hz / g_zuluscsi_timings->sdio.clk_div_pio + (5 * MHZ / 10)) / MHZ) , "MHz");
+            logmsg("Setting the SDIO clock to ", (int)((g_bluescsi_timings->clk_hz / g_bluescsi_timings->sdio.clk_div_pio + (5 * MHZ / 10)) / MHZ) , "MHz");
 #endif
             usb_log_poll();
             reclock();
@@ -273,7 +273,7 @@ void platform_init()
     bool working_dip = true;
     bool dbglog = false;
     bool termination = false;
-# if defined(ZULUSCSI_PICO) || defined(ZULUSCSI_PICO_2)
+# if defined(BLUESCSI_PICO) || defined(BLUESCSI_PICO_2)
     // Initiator dip setting works on all rev 2023b, 2023c, and newer rev Pico boards
     g_scsi_initiator = !gpio_get(DIP_INITIATOR);
 
@@ -284,7 +284,7 @@ void platform_init()
         termination = !gpio_get(DIP_TERM);
 
     }
-# elif defined(ZULUSCSI_V2_0)
+# elif defined(BLUESCSI_V2_0)
     pin_setup_state_t dip_state = read_setup_ack_pin();
     if (dip_state == SETUP_UNDETERMINED)
     {
@@ -342,9 +342,9 @@ void platform_init()
     {
         logmsg("SCSI termination is determined by the DIP switch labeled \"TERM\"");
 
-#if defined(ZULUSCSI_PICO) || defined(ZULUSCSI_PICO_2)
-        logmsg("Debug logging can only be enabled via INI file \"DEBUG=1\" under [SCSI] in zuluscsi.ini");
-        logmsg("-- DEBUG DIP switch setting is ignored on ZuluSCSI Pico FS Rev. 2023b and 2023c boards");
+#if defined(BLUESCSI_PICO) || defined(BLUESCSI_PICO_2)
+        logmsg("Debug logging can only be enabled via INI file \"DEBUG=1\" under [SCSI] in bluescsi.ini");
+        logmsg("-- DEBUG DIP switch setting is ignored on BlueSCSI Pico FS Rev. 2023b and 2023c boards");
         g_log_debug = false;
 #endif
 
@@ -468,7 +468,7 @@ void platform_late_init()
         gpio_conf(SCSI_IN_ATN,    GPIO_FUNC_SIO, true, false, false, true, false);
         gpio_conf(SCSI_IN_RST,    GPIO_FUNC_SIO, true, false, false, true, false);
 
-#ifdef ZULUSCSI_RM2
+#ifdef BLUESCSI_RM2
     uint rm2_pins[CYW43_PIN_INDEX_WL_COUNT] = {0};
     rm2_pins[CYW43_PIN_INDEX_WL_REG_ON] = GPIO_RM2_ON;
     rm2_pins[CYW43_PIN_INDEX_WL_DATA_OUT] = GPIO_RM2_DATA;
@@ -487,7 +487,7 @@ void platform_late_init()
         }
         else
         {
-# ifdef ZULUSCSI_BLASTER
+# ifdef BLUESCSI_BLASTER
             logmsg("RM2 not found, upclocking");
             platform_reclock(SPEED_GRADE_AUDIO_I2S);
 # else
@@ -519,7 +519,7 @@ void platform_late_init()
 
 // This should turn on the LED for Pico 1/2 W devices early in the init process
 // It should help indicate to the user that interface is working and the board is ready for DaynaPORT
-#if  defined(ZULUSCSI_NETWORK) && ! defined(ZULUSCSI_RM2)
+#if  defined(BLUESCSI_NETWORK) && ! defined(BLUESCSI_RM2)
     platform_network_iface_check();
 #endif
 
@@ -829,7 +829,7 @@ static void adc_poll()
         adc_init();
         adc_set_temp_sensor_enabled(true);
         adc_set_clkdiv(65535); // Lowest samplerate, about 2 kHz
-#ifdef ZULUSCSI_BLASTER
+#ifdef BLUESCSI_BLASTER
         adc_select_input(8);
 #else
         adc_select_input(4);
@@ -1127,7 +1127,7 @@ bool platform_write_romdrive(const uint8_t *data, uint32_t start, uint32_t count
  */
 
 #define PARITY(n) ((1 ^ (n) ^ ((n)>>1) ^ ((n)>>2) ^ ((n)>>3) ^ ((n)>>4) ^ ((n)>>5) ^ ((n)>>6) ^ ((n)>>7)) & 1)
-#ifdef ZULUSCSI_BLASTER
+#ifdef BLUESCSI_BLASTER
 # define X(n) (\
     ((n & 0x01) ? 0 : (1 << 0)) | \
     ((n & 0x02) ? 0 : (1 << 1)) | \

+ 17 - 17
lib/ZuluSCSI_platform_RP2MCU/ZuluSCSI_platform.h → lib/BlueSCSI_platform_RP2MCU/BlueSCSI_platform.h

@@ -19,31 +19,31 @@
  * along with this program.  If not, see <https://www.gnu.org/licenses/>.
 **/
 
-// Platform-specific definitions for ZuluSCSI RP2040 hardware.
+// Platform-specific definitions for BlueSCSI RP2040 hardware.
 
 #pragma once
 
 #include <stdint.h>
 #include <Arduino.h>
-#include "ZuluSCSI_config.h"
-#include "ZuluSCSI_platform_network.h"
-#include <ZuluSCSI_settings.h>
-
-#ifdef ZULUSCSI_PICO
-// ZuluSCSI Pico carrier board variant
-#include "ZuluSCSI_platform_gpio_Pico.h"
-#elif defined(ZULUSCSI_PICO_2)
-// ZuluSCSI Pico 2 carrier board variant
-#include "ZuluSCSI_platform_gpio_Pico_2.h"
-#elif defined(ZULUSCSI_BS2)
+#include "BlueSCSI_config.h"
+#include "BlueSCSI_platform_network.h"
+#include <BlueSCSI_settings.h>
+
+#ifdef BLUESCSI_PICO
+// BlueSCSI Pico carrier board variant
+#include "BlueSCSI_platform_gpio_Pico.h"
+#elif defined(BLUESCSI_PICO_2)
+// BlueSCSI Pico 2 carrier board variant
+#include "BlueSCSI_platform_gpio_Pico_2.h"
+#elif defined(BLUESCSI_BS2)
 // BS2 hardware variant, using Raspberry Pico board on a carrier PCB
-#include "ZuluSCSI_platform_gpio_BS2.h"
-#elif defined(ZULUSCSI_BLASTER)
+#include "BlueSCSI_platform_gpio_BS2.h"
+#elif defined(BLUESCSI_BLASTER)
 // RP2350B variant, using mcu chip directly
-#include "ZuluSCSI_platform_gpio_Blaster.h"
+#include "BlueSCSI_platform_gpio_Blaster.h"
 #else
 // Normal RP2040 variant, using RP2040 chip directly
-#include "ZuluSCSI_platform_gpio_RP2040.h"
+#include "BlueSCSI_platform_gpio_RP2040.h"
 #endif
 
 #include "scsiHostPhy.h"
@@ -137,7 +137,7 @@ inline bool platform_reclock_supported(){return true;}
 
 #ifdef RECLOCKING_SUPPORTED
 // reclock the MCU
-bool platform_reclock(zuluscsi_speed_grade_t speed_grade);
+bool platform_reclock(bluescsi_speed_grade_t speed_grade);
 #endif
 
 // Returns true if reboot was for mass storage

+ 13 - 13
lib/ZuluSCSI_platform_RP2MCU/ZuluSCSI_platform_config.h → lib/BlueSCSI_platform_RP2MCU/BlueSCSI_platform_config.h

@@ -20,11 +20,11 @@
 **/
 #pragma once
 
-#ifdef ZULUSCSI_PICO
-# ifdef ZULUSCSI_DAYNAPORT
-#   define PLATFORM_NAME "ZuluSCSI Pico DaynaPORT"
+#ifdef BLUESCSI_PICO
+# ifdef BLUESCSI_DAYNAPORT
+#   define PLATFORM_NAME "BlueSCSI Pico DaynaPORT"
 # else
-#   define PLATFORM_NAME "ZuluSCSI Pico"
+#   define PLATFORM_NAME "BlueSCSI Pico"
 # endif
 # define PLATFORM_PID "Pico"
 # define PLATFORM_REVISION "2.0"
@@ -32,11 +32,11 @@
 # define DISABLE_SWO
 # define PLATFORM_MAX_SCSI_SPEED S2S_CFG_SPEED_SYNC_20
 # define PLATFORM_DEFAULT_SCSI_SPEED_SETTING 20
-#elif defined(ZULUSCSI_PICO_2)
-# ifdef ZULUSCSI_PICO_2_DAYNAPORT
-#   define PLATFORM_NAME "ZuluSCSI Pico 2 DaynaPORT"
+#elif defined(BLUESCSI_PICO_2)
+# ifdef BLUESCSI_PICO_2_DAYNAPORT
+#   define PLATFORM_NAME "BlueSCSI Pico 2 DaynaPORT"
 # else
-#   define PLATFORM_NAME "ZuluSCSI Pico 2"
+#   define PLATFORM_NAME "BlueSCSI Pico 2"
 # endif
 # define PLATFORM_PID "Pico 2"
 # define PLATFORM_REVISION "2.3A"
@@ -45,21 +45,21 @@
 # define PLATFORM_MAX_SCSI_SPEED S2S_CFG_SPEED_SYNC_20
 # define PLATFORM_DEFAULT_SCSI_SPEED_SETTING 20
 
-#elif defined(ZULUSCSI_BLASTER)
-# define PLATFORM_NAME "ZuluSCSI Blaster"
+#elif defined(BLUESCSI_BLASTER)
+# define PLATFORM_NAME "BlueSCSI Blaster"
 # define PLATFORM_PID "Blaster"
 # define PLATFORM_REVISION "2.3B"
 # define PLATFORM_HAS_INITIATOR_MODE 1
 # define PLATFORM_MAX_SCSI_SPEED S2S_CFG_SPEED_SYNC_20
 # define PLATFORM_DEFAULT_SCSI_SPEED_SETTING 20
-#elif defined(ZULUSCSI_BS2)
-# define PLATFORM_NAME "ZuluSCSI BS2"
+#elif defined(BLUESCSI_BS2)
+# define PLATFORM_NAME "BlueSCSI BS2"
 # define PLATFORM_PID "BS2"
 # define PLATFORM_REVISION "1.0"
 # define PLATFORM_MAX_SCSI_SPEED S2S_CFG_SPEED_SYNC_20
 # define PLATFORM_DEFAULT_SCSI_SPEED_SETTING 20
 #else
-# define PLATFORM_NAME "ZuluSCSI RP2040"
+# define PLATFORM_NAME "BlueSCSI RP2040"
 # define PLATFORM_PID "RP2040"
 # define PLATFORM_REVISION "2.0"
 # define PLATFORM_HAS_INITIATOR_MODE 1

+ 0 - 0
lib/ZuluSCSI_platform_RP2MCU/ZuluSCSI_platform_gpio_BS2.h → lib/BlueSCSI_platform_RP2MCU/BlueSCSI_platform_gpio_BS2.h


+ 9 - 9
lib/ZuluSCSI_platform_RP2MCU/ZuluSCSI_platform_msc.cpp → lib/BlueSCSI_platform_RP2MCU/BlueSCSI_platform_msc.cpp

@@ -25,13 +25,13 @@
 #include <device/usbd.h>
 #include <hardware/gpio.h>
 
-#include "ZuluSCSI_platform.h"
-#include "ZuluSCSI_disk.h"
-#include "ZuluSCSI_log.h"
-#include "ZuluSCSI_msc.h"
-#include "ZuluSCSI_msc_initiator.h"
-#include "ZuluSCSI_config.h"
-#include "ZuluSCSI_settings.h"
+#include "BlueSCSI_platform.h"
+#include "BlueSCSI_disk.h"
+#include "BlueSCSI_log.h"
+#include "BlueSCSI_msc.h"
+#include "BlueSCSI_msc_initiator.h"
+#include "BlueSCSI_config.h"
+#include "BlueSCSI_settings.h"
 #include <class/msc/msc.h>
 #include <class/msc/msc_device.h>
 
@@ -108,7 +108,7 @@ public:
 /* return true if USB presence detected / eligble to enter CR mode */
 bool platform_sense_msc() {
 
-#if defined(ZULUSCSI_PICO) || defined(ZULUSCSI_PICO_2)
+#if defined(BLUESCSI_PICO) || defined(BLUESCSI_PICO_2)
   // check if we're USB powered, if not, exit immediately
   // pin on the wireless module, see https://github.com/earlephilhower/arduino-pico/discussions/835
   // Update: from the above discussion the offset 32 has been changed to 64 to access CYW43 GPIO pins
@@ -242,7 +242,7 @@ extern "C" void tud_msc_inquiry_cb(uint8_t lun, uint8_t vendor_id[8],
   MSCScopedLock lock;
   if (g_msc_initiator) return init_msc_inquiry_cb(lun, vendor_id, product_id, product_rev);
 
-  const char vid[] = "ZuluSCSI";
+  const char vid[] = "BlueSCSI";
   const char pid[] = PLATFORM_PID; 
   const char rev[] = PLATFORM_REVISION;
 

+ 0 - 0
lib/ZuluSCSI_platform_RP2MCU/ZuluSCSI_platform_msc.h → lib/BlueSCSI_platform_RP2MCU/BlueSCSI_platform_msc.h


+ 6 - 6
lib/ZuluSCSI_platform_RP2MCU/ZuluSCSI_platform_network.cpp → lib/BlueSCSI_platform_RP2MCU/BlueSCSI_platform_network.cpp

@@ -13,11 +13,11 @@
  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
-#ifdef ZULUSCSI_NETWORK
+#ifdef BLUESCSI_NETWORK
 #include <Arduino.h>
-#include "ZuluSCSI_platform_network.h"
-#include "ZuluSCSI_log.h"
-#include "ZuluSCSI_config.h"
+#include "BlueSCSI_platform_network.h"
+#include "BlueSCSI_log.h"
+#include "BlueSCSI_config.h"
 #include <scsi.h>
 #include <network.h>
 
@@ -47,7 +47,7 @@ bool platform_network_supported()
 	/* from cores/rp2040/RP2040Support.h */
 #if !defined(PICO_CYW43_SUPPORTED)
 	return false;
-#elif defined(ZULUSCSI_BLASTER)
+#elif defined(BLUESCSI_BLASTER)
 	return true;
 #else
 	extern bool __isPicoW;
@@ -365,4 +365,4 @@ void cyw43_cb_tcpip_set_link_up(cyw43_t *self, int itf)
 }
 
 }
-#endif // ZULUSCSI_NETWORK
+#endif // BLUESCSI_NETWORK

+ 3 - 3
lib/ZuluSCSI_platform_RP2MCU/ZuluSCSI_platform_network.h → lib/BlueSCSI_platform_RP2MCU/BlueSCSI_platform_network.h

@@ -16,7 +16,7 @@
 
 #pragma once
 
-#ifdef ZULUSCSI_NETWORK
+#ifdef BLUESCSI_NETWORK
 
 #include <stdint.h>
 #include <stddef.h>
@@ -37,7 +37,7 @@ char * platform_network_wifi_ssid();
 char * platform_network_wifi_bssid();
 int platform_network_wifi_channel();
 int platform_network_send(uint8_t *buf, size_t len);
-// Test if the communication between the network device and the ZuluIDE works
+// Test if the communication between the network device and the BlueIDE works
 bool platform_network_iface_check();
 // Tears down the interface, mainly used to turn off the LED on the RM2 Pico 1W/2W
 void platform_network_deinit();
@@ -45,4 +45,4 @@ void platform_network_deinit();
 }
 # endif
 
-#endif // ZULUSCSI_NETWORK
+#endif // BLUESCSI_NETWORK

+ 6 - 6
lib/ZuluSCSI_platform_RP2MCU/audio_i2s.cpp → lib/BlueSCSI_platform_RP2MCU/audio_i2s.cpp

@@ -27,13 +27,13 @@
 #include "audio_i2s.h"
 #include <CUEParser.h>
 #include "timings_RP2MCU.h"
-#include "ZuluSCSI_audio.h"
-// #include "ZuluIDE_config.h"
-#include "ZuluSCSI_log.h"
-#include "ZuluSCSI_platform.h"
+#include "BlueSCSI_audio.h"
+// #include "BlueIDE_config.h"
+#include "BlueSCSI_log.h"
+#include "BlueSCSI_platform.h"
 // #include "ide_imagefile.h"
 // #include "ide_atapi.h"
-#include <ZuluI2S.h>
+#include <BlueI2S.h>
 
 
 extern SdFs SD;
@@ -412,7 +412,7 @@ void audio_setup() {
     i2s.setBCLK(GPIO_I2S_BCLK);
     i2s.setDATA(GPIO_I2S_DOUT);
     i2s.setBitsPerSample(16);
-    i2s.setDivider(g_zuluscsi_timings->audio.clk_div_pio, 0);
+    i2s.setDivider(g_bluescsi_timings->audio.clk_div_pio, 0);
     i2s.begin(I2S_PIO_HW, I2S_PIO_SM);
     dma_channel_claim(SOUND_DMA_CHA);
 	dma_channel_claim(SOUND_DMA_CHB);

+ 0 - 0
lib/ZuluSCSI_platform_RP2MCU/audio_i2s.h → lib/BlueSCSI_platform_RP2MCU/audio_i2s.h


+ 4 - 4
lib/ZuluSCSI_platform_RP2MCU/audio_spdif.cpp → lib/BlueSCSI_platform_RP2MCU/audio_spdif.cpp

@@ -24,10 +24,10 @@
 #include <hardware/spi.h>
 #include <pico/multicore.h>
 #include "audio_spdif.h"
-#include "ZuluSCSI_audio.h"
-#include "ZuluSCSI_config.h"
-#include "ZuluSCSI_log.h"
-#include "ZuluSCSI_platform.h"
+#include "BlueSCSI_audio.h"
+#include "BlueSCSI_config.h"
+#include "BlueSCSI_log.h"
+#include "BlueSCSI_platform.h"
 
 extern SdFs SD;
 

+ 0 - 0
lib/ZuluSCSI_platform_RP2MCU/audio_spdif.h → lib/BlueSCSI_platform_RP2MCU/audio_spdif.h


+ 0 - 0
lib/ZuluSCSI_platform_GD32F205/bsp.h → lib/BlueSCSI_platform_RP2MCU/bsp.h


+ 129 - 0
lib/BlueSCSI_platform_RP2MCU/custom_timings.cpp

@@ -0,0 +1,129 @@
+/**
+ * ZuluSCSI™ - Copyright (c) 2024-2025 Rabbit Hole Computing™
+ *
+ * ZuluSCSI™ firmware is licensed under the GPL version 3 or any later version.
+ *
+ * https://www.gnu.org/licenses/gpl-3.0.html
+ * ----
+ * 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 <https://www.gnu.org/licenses/>.
+**/
+
+#include "custom_timings.h"
+#include <SdFat.h>
+#include <minIni.h>
+#include <BlueSCSI_log.h>
+#include <BlueSCSI_platform.h>
+extern SdFs SD;
+
+extern "C"
+{
+    #include <timings.h>
+}
+
+bool CustomTimings::use_custom_timings()
+{
+    return SD.exists(CUSTOM_TIMINGS_FILE) && !ini_getbool("settings", "disable", 0, CUSTOM_TIMINGS_FILE);
+}
+
+bool CustomTimings::set_timings_from_file()
+{
+    const char settings_section[] = "settings";
+    const char pll_section[] = "pll";
+    const char scsi_section[] = "scsi";
+    const char scsi_20_section[] = "scsi_20";
+    const char scsi_10_section[] = "scsi_10";
+    const char scsi_5_section[] = "scsi_5";
+    const char sdio_section[] = "sdio";
+    const char audio_section[] = "audio";
+
+    // pll
+    int32_t vco = ini_getl(pll_section, "vco_freq_hz", g_bluescsi_timings->pll.vco_freq, CUSTOM_TIMINGS_FILE);
+    int32_t post_div1 = ini_getl(pll_section, "pd1", g_bluescsi_timings->pll.post_div1, CUSTOM_TIMINGS_FILE);
+    int32_t post_div2 = ini_getl(pll_section, "pd2", g_bluescsi_timings->pll.post_div2, CUSTOM_TIMINGS_FILE);
+
+    if (vco > 0 && post_div1 > 0 && post_div2 > 0)
+    {
+        if (vco / post_div1 / post_div2 > 252000000)
+        {
+            logmsg("Reclocking over 252MHz with the PLL settings is not allowed using ", CUSTOM_TIMINGS_FILE);
+            return false;
+        }
+    }
+    else
+    {
+        logmsg("Reclocking failed because 0 or negative PLL settings values");
+        return false;
+    }
+
+    g_bluescsi_timings->pll.vco_freq = vco;
+    g_bluescsi_timings->pll.post_div1 = post_div1;
+    g_bluescsi_timings->pll.post_div2 = post_div2;
+    g_bluescsi_timings->pll.refdiv =  ini_getl(pll_section, "refdiv", g_bluescsi_timings->pll.refdiv, CUSTOM_TIMINGS_FILE);
+
+    char speed_grade_str[10];
+    ini_gets(settings_section, "extends_speed_grade", "Default", speed_grade_str, sizeof(speed_grade_str), CUSTOM_TIMINGS_FILE);
+    bluescsi_speed_grade_t speed_grade =  g_scsi_settings.stringToSpeedGrade(speed_grade_str, sizeof(speed_grade_str));
+    set_timings(speed_grade);
+
+    int32_t number_setting = ini_getl(settings_section, "boot_with_sync_value", 0, CUSTOM_TIMINGS_FILE);
+
+    if (number_setting > 0)
+    {
+        g_force_sync = number_setting;
+        number_setting = ini_getl(settings_section, "boot_with_offset_value", 15, CUSTOM_TIMINGS_FILE);
+        g_force_offset = number_setting > 15 ? 15 : number_setting;
+        logmsg("Forcing sync of ", (int) g_force_sync, " and offset of ", (int) g_force_offset);
+    }
+    g_bluescsi_timings->clk_hz = ini_getl(settings_section, "clk_hz", g_bluescsi_timings->clk_hz, CUSTOM_TIMINGS_FILE);
+
+
+    // scsi
+    g_bluescsi_timings->scsi.clk_period_ps = ini_getl(scsi_section, "clk_period_ps", g_bluescsi_timings->scsi.clk_period_ps, CUSTOM_TIMINGS_FILE);
+    g_bluescsi_timings->scsi.req_delay = ini_getl(scsi_section, "req_delay_cc", g_bluescsi_timings->scsi.req_delay, CUSTOM_TIMINGS_FILE);
+
+    // scsi 20
+    g_bluescsi_timings->scsi_20.delay0 = ini_getl(scsi_20_section, "delay0_cc", g_bluescsi_timings->scsi_20.delay0, CUSTOM_TIMINGS_FILE);
+    g_bluescsi_timings->scsi_20.delay1 = ini_getl(scsi_20_section, "delay1_cc", g_bluescsi_timings->scsi_20.delay1, CUSTOM_TIMINGS_FILE);
+    g_bluescsi_timings->scsi_20.total_period_adjust = ini_getl(scsi_20_section, "total_period_adjust_cc", g_bluescsi_timings->scsi_20.total_period_adjust, CUSTOM_TIMINGS_FILE);
+    g_bluescsi_timings->scsi_20.max_sync = ini_getl(scsi_20_section, "max_sync", g_bluescsi_timings->scsi_20.max_sync, CUSTOM_TIMINGS_FILE);
+    g_bluescsi_timings->scsi_20.rdelay1 = ini_getl(scsi_20_section, "read_delay1_cc", g_bluescsi_timings->scsi_20.rdelay1, CUSTOM_TIMINGS_FILE);
+    g_bluescsi_timings->scsi_20.rtotal_period_adjust = ini_getl(scsi_20_section, "read_total_period_adjust_cc", g_bluescsi_timings->scsi_20.rtotal_period_adjust, CUSTOM_TIMINGS_FILE);
+
+    // scsi 10
+    g_bluescsi_timings->scsi_10.delay0 = ini_getl(scsi_10_section, "delay0_cc", g_bluescsi_timings->scsi_10.delay0, CUSTOM_TIMINGS_FILE);
+    g_bluescsi_timings->scsi_10.delay1 = ini_getl(scsi_10_section, "delay1_cc", g_bluescsi_timings->scsi_10.delay1, CUSTOM_TIMINGS_FILE);
+    g_bluescsi_timings->scsi_10.total_period_adjust = ini_getl(scsi_10_section, "total_period_adjust_cc", g_bluescsi_timings->scsi_10.total_period_adjust, CUSTOM_TIMINGS_FILE);
+    g_bluescsi_timings->scsi_10.max_sync = ini_getl(scsi_10_section, "max_sync", g_bluescsi_timings->scsi_10.max_sync, CUSTOM_TIMINGS_FILE);
+    g_bluescsi_timings->scsi_10.rdelay1 = ini_getl(scsi_10_section, "read_delay1_cc", g_bluescsi_timings->scsi_10.rdelay1, CUSTOM_TIMINGS_FILE);
+    g_bluescsi_timings->scsi_10.rtotal_period_adjust = ini_getl(scsi_10_section, "read_total_period_adjust_cc", g_bluescsi_timings->scsi_10.rtotal_period_adjust, CUSTOM_TIMINGS_FILE);
+
+    // scsi 5
+    g_bluescsi_timings->scsi_5.delay0 = ini_getl(scsi_5_section, "delay0_cc", g_bluescsi_timings->scsi_5.delay0, CUSTOM_TIMINGS_FILE);
+    g_bluescsi_timings->scsi_5.delay1 = ini_getl(scsi_5_section, "delay1_cc", g_bluescsi_timings->scsi_5.delay1, CUSTOM_TIMINGS_FILE);
+    g_bluescsi_timings->scsi_5.total_period_adjust = ini_getl(scsi_5_section, "total_period_adjust_cc", g_bluescsi_timings->scsi_5.total_period_adjust, CUSTOM_TIMINGS_FILE);
+    g_bluescsi_timings->scsi_5.max_sync = ini_getl(scsi_5_section, "max_sync", g_bluescsi_timings->scsi_5.max_sync, CUSTOM_TIMINGS_FILE);
+    g_bluescsi_timings->scsi_5.rdelay1 = ini_getl(scsi_5_section, "read_delay1_cc", g_bluescsi_timings->scsi_5.rdelay1, CUSTOM_TIMINGS_FILE);
+    g_bluescsi_timings->scsi_5.rtotal_period_adjust = ini_getl(scsi_5_section, "read_total_period_adjust_cc", g_bluescsi_timings->scsi_5.rtotal_period_adjust, CUSTOM_TIMINGS_FILE);
+
+    // sdio
+    g_bluescsi_timings->sdio.clk_div_pio = ini_getl(sdio_section, "clk_div_pio", g_bluescsi_timings->sdio.clk_div_pio, CUSTOM_TIMINGS_FILE);
+    g_bluescsi_timings->sdio.clk_div_1mhz = ini_getl(sdio_section, "clk_div_1mhz", g_bluescsi_timings->sdio.clk_div_1mhz, CUSTOM_TIMINGS_FILE);
+    g_bluescsi_timings->sdio.delay0 = ini_getl(sdio_section, "delay0", g_bluescsi_timings->sdio.delay0, CUSTOM_TIMINGS_FILE);
+    g_bluescsi_timings->sdio.delay1 = ini_getl(sdio_section, "delay1", g_bluescsi_timings->sdio.delay1, CUSTOM_TIMINGS_FILE);
+
+    // audio
+    g_bluescsi_timings->audio.clk_div_pio = ini_getl(audio_section, "clk_div_pio", g_bluescsi_timings->audio.clk_div_pio, CUSTOM_TIMINGS_FILE);
+    g_bluescsi_timings->audio.audio_clocked = ini_getbool(audio_section, "clk_for_audio", g_bluescsi_timings->audio.audio_clocked, CUSTOM_TIMINGS_FILE);
+    return true;
+}

+ 1 - 1
lib/ZuluSCSI_platform_RP2MCU/custom_timings.h → lib/BlueSCSI_platform_RP2MCU/custom_timings.h

@@ -20,7 +20,7 @@
 **/
 #pragma once
 
-#define CUSTOM_TIMINGS_FILE "zuluscsi_timings.ini"
+#define CUSTOM_TIMINGS_FILE "bluescsi_timings.ini"
 
 
 #include "timings_RP2MCU.h"

+ 14 - 0
lib/BlueSCSI_platform_RP2MCU/library.json

@@ -0,0 +1,14 @@
+{
+    "name": "BlueSCSI_platform_RP2MCU",
+    "version": "1.0",
+    "repository": { "type": "git", "url": "git://github.com/BluesCSI/BlueSCSI-v2.git" },
+    "authors": [{ "name": "BlueSCSI", "email": "support@bluescsi.com" }],
+    "license": "GPL-3.0-or-later",
+    "homepage": "https://bluescsi.com",
+    "frameworks": "*",
+    "platforms": "*",
+    "dependencies":
+    {
+        "CUEParser": "https://github.com/BlueSCSI/CUEParser#v2025.02.25"
+    }
+}

+ 6 - 6
lib/ZuluSCSI_platform_RP2MCU/program_flash.cpp → lib/BlueSCSI_platform_RP2MCU/program_flash.cpp

@@ -20,12 +20,12 @@
 **/
 
 /**
- * This has been removed from ZuluSCSI_platform.cpp so this code can be
- * placed in SRAM while ZuluSCSI_platform.cpp.o can be placed in flash
+ * This has been removed from BlueSCSI_platform.cpp so this code can be
+ * placed in SRAM while BlueSCSI_platform.cpp.o can be placed in flash
 */
 
-#include "ZuluSCSI_platform.h"
-#include "ZuluSCSI_log.h"
+#include "BlueSCSI_platform.h"
+#include "BlueSCSI_log.h"
 #include <hardware/flash.h>
 #include <hardware/structs/xip_ctrl.h>
 #include <hardware/structs/usb.h>
@@ -62,7 +62,7 @@ bool platform_rewrite_flash_page(uint32_t offset, uint8_t buffer[PLATFORM_FLASH_
     }
 
 
-#ifdef ZULUSCSI_MCU_RP23XX
+#ifdef BLUESCSI_MCU_RP23XX
 
     if (nvic_hw->iser[0] & 1 << 14)
     {
@@ -102,7 +102,7 @@ bool platform_rewrite_flash_page(uint32_t offset, uint8_t buffer[PLATFORM_FLASH_
     for (int i = 0; i < num_words; i++)
     {
         uint32_t expected = buf32[i];
-#ifdef ZULUSCSI_MCU_RP23XX
+#ifdef BLUESCSI_MCU_RP23XX
         uint32_t actual = *(volatile uint32_t*)(XIP_NOCACHE_NOALLOC_BASE + offset + i * 4);
 #else
         uint32_t actual = *(volatile uint32_t*)(XIP_NOCACHE_BASE + offset + i * 4);

+ 6 - 6
lib/ZuluSCSI_platform_RP2MCU/rp2040-template.ld → lib/BlueSCSI_platform_RP2MCU/rp2040-template.ld

@@ -40,7 +40,7 @@ SECTIONS
     ASSERT(__boot2_end__ - __boot2_start__ == 256,
         "ERROR: Pico second stage bootloader must be 256 bytes in size")
 
-    /* If ZuluSCSI SD card bootloader is included, it goes in first 128 kB */
+    /* If BlueSCSI SD card bootloader is included, it goes in first 128 kB */
     .text.bootloader : ALIGN(16) SUBALIGN(16)
     {
         KEEP(*(.text.btldr*))
@@ -73,11 +73,11 @@ SECTIONS
         /* Put only non-timecritical code in flash
          * This includes e.g. floating point math routines.
          */
-        .pio/build/$project_name/src/ZuluSCSI_initiator.cpp.o(.text .text*)
-        .pio/build/$project_name/src/ZuluSCSI_msc_initiator.cpp.o(.text .text*)
-        .pio/build/$project_name/src/ZuluSCSI_log.cpp.o(.text .text*)
-        .pio/build/$project_name/src/ZuluSCSI_log_trace.cpp.o(.text .text*)
-        .pio/build/$project_name/src/ZuluSCSI_settings.cpp.o(.text .text*)
+        .pio/build/$project_name/src/BlueSCSI_initiator.cpp.o(.text .text*)
+        .pio/build/$project_name/src/BlueSCSI_msc_initiator.cpp.o(.text .text*)
+        .pio/build/$project_name/src/BlueSCSI_log.cpp.o(.text .text*)
+        .pio/build/$project_name/src/BlueSCSI_log_trace.cpp.o(.text .text*)
+        .pio/build/$project_name/src/BlueSCSI_settings.cpp.o(.text .text*)
         .pio/build/$project_name/src/QuirksCheck.cpp.o(.text .text*)
         *libm*:(.text .text*)
         *libc*:(.text .text*)

+ 0 - 0
lib/ZuluSCSI_platform_RP2MCU/rp2040_btldr.ld → lib/BlueSCSI_platform_RP2MCU/rp2040_btldr.ld


+ 3 - 3
lib/ZuluSCSI_platform_RP2MCU/rp23xx-template.ld → lib/BlueSCSI_platform_RP2MCU/rp23xx-template.ld

@@ -52,7 +52,7 @@ SECTIONS
        cold boot.
     */
 
-    /* If ZuluSCSI SD card bootloader is included, it goes in first 128 kB */
+    /* If BlueSCSI SD card bootloader is included, it goes in first 128 kB */
     .text.bootloader : ALIGN(16) SUBALIGN(16)
     {
         KEEP(*(.text.btldr*))
@@ -76,7 +76,7 @@ SECTIONS
 
 /* =============================================================== */
     /* Exclude as much code from flash as possible as the RP2350 series has twice as much SRAM */
-        *(EXCLUDE_FILE(*libgcc.a: *libc.a:*lib_a-mem*.o *libm.a: *libZuluIDE_platform_RPMCU.a:  *libSdFat.a: *libSCSI2SD.a: *CUEParser.a: *minIni.a: *.cpp.o) .text*)
+        *(EXCLUDE_FILE(*libgcc.a: *libc.a:*lib_a-mem*.o *libm.a: *libBlueIDE_platform_RPMCU.a:  *libSdFat.a: *libSCSI2SD.a: *CUEParser.a: *minIni.a: *.cpp.o) .text*)
 
     /* ---------------------------------------------------------
     Uncomment the EXCLUDE_FILE line below and comment the EXCLUDE_FILE line above for debug to work properly,
@@ -152,7 +152,7 @@ SECTIONS
     .rodata : {
         /* Exclude as many constants as possible from flash as corresponding to the code that has been removed from flash
             to keep the MCU from having to hit flash while it is executing in SRAM */
-        *(EXCLUDE_FILE(*libgcc.a: *libc.a:*lib_a-mem*.o *libm.a:  *libZuluIDE_platform_RPMCU.a:  *libSdFat.a: *libSCSI2SD.a: *CUEParser.a: *minIni.a: *.cpp.o) .rodata*)
+        *(EXCLUDE_FILE(*libgcc.a: *libc.a:*lib_a-mem*.o *libm.a:  *libBlueIDE_platform_RPMCU.a:  *libSdFat.a: *libSCSI2SD.a: *CUEParser.a: *minIni.a: *.cpp.o) .rodata*)
 /* Uncomment below and comment above lines for debugging */
         /* *(EXCLUDE_FILE(*libgcc.a: *libc.a:*lib_a-mem*.o *libm.a:) .rodata*) */
 

+ 0 - 0
lib/ZuluSCSI_platform_RP2MCU/rp23xx_btldr.ld → lib/BlueSCSI_platform_RP2MCU/rp23xx_btldr.ld


+ 0 - 0
lib/ZuluSCSI_platform_RP2MCU/run_pioasm.sh → lib/BlueSCSI_platform_RP2MCU/run_pioasm.sh


+ 1 - 1
lib/ZuluSCSI_platform_RP2MCU/scsi2sd_time.h → lib/BlueSCSI_platform_RP2MCU/scsi2sd_time.h

@@ -27,7 +27,7 @@
 #pragma once
 
 #include <stdint.h>
-#include "ZuluSCSI_platform.h"
+#include "BlueSCSI_platform.h"
 
 #define s2s_getTime_ms() millis()
 #define s2s_elapsedTime_ms(since) ((uint32_t)(millis() - (since)))

+ 2 - 2
lib/ZuluSCSI_platform_RP2MCU/scsi2sd_timings.c → lib/BlueSCSI_platform_RP2MCU/scsi2sd_timings.c

@@ -19,11 +19,11 @@
  * along with this program.  If not, see <https://www.gnu.org/licenses/>.
 **/
 #include "timings.h"
-#if defined(ZULUSCSI_MCU_RP23XX)
+#if defined(BLUESCSI_MCU_RP23XX)
 uint8_t g_max_sync_20_period = 12;
 uint8_t g_max_sync_10_period = 25;
 uint8_t g_max_sync_5_period  = 50; 
-#elif defined(ZULUSCSI_MCU_RP20XX)
+#elif defined(BLUESCSI_MCU_RP20XX)
 uint8_t g_max_sync_20_period = 12;
 uint8_t g_max_sync_10_period = 25;
 uint8_t g_max_sync_5_period  = 50; 

+ 3 - 3
lib/ZuluSCSI_platform_RP2MCU/scsiHostPhy.cpp → lib/BlueSCSI_platform_RP2MCU/scsiHostPhy.cpp

@@ -20,9 +20,9 @@
 **/
 
 #include "scsiHostPhy.h"
-#include "ZuluSCSI_platform.h"
-#include "ZuluSCSI_log.h"
-#include "ZuluSCSI_log_trace.h"
+#include "BlueSCSI_platform.h"
+#include "BlueSCSI_log.h"
+#include "BlueSCSI_log_trace.h"
 #include "scsi_accel_host.h"
 #include <assert.h>
 

+ 0 - 0
lib/ZuluSCSI_platform_RP2MCU/scsiHostPhy.h → lib/BlueSCSI_platform_RP2MCU/scsiHostPhy.h


+ 6 - 6
lib/ZuluSCSI_platform_RP2MCU/scsiPhy.cpp → lib/BlueSCSI_platform_RP2MCU/scsiPhy.cpp

@@ -25,10 +25,10 @@
 // Partially derived from scsiPhy.c from SCSI2SD-V6
 
 #include "scsiPhy.h"
-#include "ZuluSCSI_platform.h"
-#include "ZuluSCSI_log.h"
-#include "ZuluSCSI_log_trace.h"
-#include "ZuluSCSI_config.h"
+#include "BlueSCSI_platform.h"
+#include "BlueSCSI_log.h"
+#include "BlueSCSI_log_trace.h"
+#include "BlueSCSI_config.h"
 #include "scsi_accel_target.h"
 #include "hardware/structs/iobank0.h"
 
@@ -104,7 +104,7 @@ extern "C" bool scsiStatusSEL()
         // Releasing happens with bus release.
         g_scsi_ctrl_bsy = 0;
 
-#ifdef ZULUSCSI_BS2
+#ifdef BLUESCSI_BS2
         // From BS2 repository commit 8971584485c42, not sure of purpose.
         SCSI_OUT(CD, 0);
         SCSI_OUT(MSG, 0);
@@ -216,7 +216,7 @@ extern "C" uint32_t scsiEnterPhaseImmediate(int phase)
         if (scsiDev.compatMode < COMPAT_SCSI2 && (phase == DATA_IN || phase == DATA_OUT))
         {
             // Akai S1000/S3000 seems to need extra delay before changing to data phase
-            // after a command. The code in ZuluSCSI_disk.cpp tries to do this while waiting
+            // after a command. The code in BlueSCSI_disk.cpp tries to do this while waiting
             // for SD card, to avoid any extra latency.
             s2s_delay_ns(400000);
         }

+ 0 - 0
lib/ZuluSCSI_platform_RP2MCU/scsiPhy.h → lib/BlueSCSI_platform_RP2MCU/scsiPhy.h


+ 2 - 2
lib/ZuluSCSI_platform_RP2MCU/scsi_accel_host.cpp → lib/BlueSCSI_platform_RP2MCU/scsi_accel_host.cpp

@@ -22,8 +22,8 @@
 // Accelerated SCSI subroutines for SCSI initiator/host side communication
 
 #include "scsi_accel_host.h"
-#include "ZuluSCSI_platform.h"
-#include "ZuluSCSI_log.h"
+#include "BlueSCSI_platform.h"
+#include "BlueSCSI_log.h"
 #include <hardware/pio.h>
 #include <hardware/dma.h>
 #include <hardware/irq.h>

+ 0 - 0
lib/ZuluSCSI_platform_RP2MCU/scsi_accel_host.h → lib/BlueSCSI_platform_RP2MCU/scsi_accel_host.h


+ 0 - 0
lib/ZuluSCSI_platform_RP2MCU/scsi_accel_host_RP2MCU.pio → lib/BlueSCSI_platform_RP2MCU/scsi_accel_host_RP2MCU.pio


+ 0 - 0
lib/ZuluSCSI_platform_RP2MCU/scsi_accel_host_RP2MCU.pio.h → lib/BlueSCSI_platform_RP2MCU/scsi_accel_host_RP2MCU.pio.h


+ 35 - 37
lib/ZuluSCSI_platform_RP2MCU/scsi_accel_target.cpp → lib/BlueSCSI_platform_RP2MCU/scsi_accel_target.cpp

@@ -30,8 +30,8 @@
 * 4. PIO peripheral handles low-level SCSI handshake and writes bytes and parity to GPIO.
 */
 
-#include "ZuluSCSI_platform.h"
-#include "ZuluSCSI_log.h"
+#include "BlueSCSI_platform.h"
+#include "BlueSCSI_log.h"
 #include "scsi_accel_target.h"
 #include "timings_RP2MCU.h"
 #include <hardware/pio.h>
@@ -51,7 +51,7 @@
 // SM0: Convert data bytes to lookup addresses to add parity
 // SM1: Write data to SCSI bus
 // SM2: For synchronous mode only, count ACK pulses
-#ifdef ZULUSCSI_NETWORK
+#ifdef BLUESCSI_NETWORK
 #  define SCSI_DMA_PIO pio0
 #  define SCSI_PARITY_SM 1
 #  define SCSI_DATA_SM 2
@@ -61,7 +61,7 @@
 #  define SCSI_PARITY_SM 0
 #  define SCSI_DATA_SM 1
 #  define SCSI_SYNC_SM 2
-#endif // ZULUSCSI_NETWORK
+#endif // BLUESCSI_NETWORK
 
 
 // SCSI bus write acceleration uses 3 or 4 DMA channels (data flow A->B->C->D):
@@ -75,7 +75,7 @@
 // B: Lookup from g_scsi_parity_check_lookup and copy to scsi_read_parity PIO
 // C: Addresses from scsi_accel_read PIO to lookup DMA READ_ADDR register
 // D: From pacer to data state machine to trigger transfers
-#ifdef ZULUSCSI_NETWORK
+#ifdef BLUESCSI_NETWORK
 #  define SCSI_DMA_CH_A 6
 #  define SCSI_DMA_CH_B 7
 #  define SCSI_DMA_CH_C 8
@@ -771,7 +771,7 @@ void scsi_accel_rp2040_finishRead(const uint8_t *data, uint32_t count, int *pari
 /*******************************************************/
 /* Write SCSI PIO program timings and ACK pin          */
 /*******************************************************/
-static void zulu_pio_remove_program(PIO pio, const pio_program_t *program, uint loaded_offset, bool &removed)
+static void blue_pio_remove_program(PIO pio, const pio_program_t *program, uint loaded_offset, bool &removed)
 {
     if (!removed)
     {
@@ -782,7 +782,7 @@ static void zulu_pio_remove_program(PIO pio, const pio_program_t *program, uint
 
 static int pio_add_scsi_accel_async_write_program()
 {
-    zulu_pio_remove_program(SCSI_DMA_PIO,
+    blue_pio_remove_program(SCSI_DMA_PIO,
         &scsi_accel_async_write_program,
         g_scsi_dma.pio_offset_async_write,
         g_scsi_dma.pio_removed_async_write);
@@ -798,7 +798,7 @@ static int pio_add_scsi_accel_async_write_program()
         sizeof(scsi_accel_async_write_program_instructions));
 
     // out null, 23         side 1  [0] ;[REQ_DLY-2]      ; Discard unused bits, wait for data preset time
-    uint8_t delay = g_zuluscsi_timings->scsi.req_delay - 2;
+    uint8_t delay = g_bluescsi_timings->scsi.req_delay - 2;
     assert( delay <= 0xF);
     rewrote_instructions[2] |= pio_encode_delay(delay);
     // wait 1 gpio ACK      side 1      ; Wait for ACK to be inactive
@@ -812,7 +812,7 @@ static int pio_add_scsi_accel_async_write_program()
 
 static int pio_add_scsi_accel_read_program()
 {
-    zulu_pio_remove_program(SCSI_DMA_PIO,
+    blue_pio_remove_program(SCSI_DMA_PIO,
         &scsi_accel_read_program,
         g_scsi_dma.pio_offset_read,
         g_scsi_dma.pio_removed_read);
@@ -839,7 +839,7 @@ static int pio_add_scsi_accel_read_program()
 
 static int pio_add_scsi_sync_write_pacer_program()
 {
-    zulu_pio_remove_program(SCSI_DMA_PIO,
+    blue_pio_remove_program(SCSI_DMA_PIO,
         &scsi_sync_write_pacer_program,
         g_scsi_dma.pio_offset_sync_write_pacer,
         g_scsi_dma.pio_removed_sync_write_pacer);
@@ -1008,13 +1008,13 @@ void scsi_accel_rp2040_init()
         pio_sm_unclaim(SCSI_DMA_PIO, SCSI_SYNC_SM);
 
         // Remove all SCSI programs
-        zulu_pio_remove_program(SCSI_DMA_PIO, &scsi_parity_program, g_scsi_dma.pio_offset_parity, g_scsi_dma.pio_removed_parity);
-        zulu_pio_remove_program(SCSI_DMA_PIO, &scsi_accel_async_write_program, g_scsi_dma.pio_offset_async_write, g_scsi_dma.pio_removed_async_write);
-        zulu_pio_remove_program(SCSI_DMA_PIO, &scsi_sync_write_pacer_program, g_scsi_dma.pio_offset_sync_write_pacer, g_scsi_dma.pio_removed_sync_write_pacer);
-        zulu_pio_remove_program(SCSI_DMA_PIO, &scsi_accel_read_program, g_scsi_dma.pio_offset_read, g_scsi_dma.pio_removed_read);
-        zulu_pio_remove_program(SCSI_DMA_PIO, &scsi_sync_read_pacer_program, g_scsi_dma.pio_offset_sync_read_pacer, g_scsi_dma.pio_removed_sync_read_pacer);
-        zulu_pio_remove_program(SCSI_DMA_PIO, &scsi_read_parity_program, g_scsi_dma.pio_offset_read_parity, g_scsi_dma.pio_removed_read_parity);
-        zulu_pio_remove_program(SCSI_DMA_PIO, &scsi_sync_write_program, g_scsi_dma.pio_offset_sync_write, g_scsi_dma.pio_removed_sync_write);
+        blue_pio_remove_program(SCSI_DMA_PIO, &scsi_parity_program, g_scsi_dma.pio_offset_parity, g_scsi_dma.pio_removed_parity);
+        blue_pio_remove_program(SCSI_DMA_PIO, &scsi_accel_async_write_program, g_scsi_dma.pio_offset_async_write, g_scsi_dma.pio_removed_async_write);
+        blue_pio_remove_program(SCSI_DMA_PIO, &scsi_sync_write_pacer_program, g_scsi_dma.pio_offset_sync_write_pacer, g_scsi_dma.pio_removed_sync_write_pacer);
+        blue_pio_remove_program(SCSI_DMA_PIO, &scsi_accel_read_program, g_scsi_dma.pio_offset_read, g_scsi_dma.pio_removed_read);
+        blue_pio_remove_program(SCSI_DMA_PIO, &scsi_sync_read_pacer_program, g_scsi_dma.pio_offset_sync_read_pacer, g_scsi_dma.pio_removed_sync_read_pacer);
+        blue_pio_remove_program(SCSI_DMA_PIO, &scsi_read_parity_program, g_scsi_dma.pio_offset_read_parity, g_scsi_dma.pio_removed_read_parity);
+        blue_pio_remove_program(SCSI_DMA_PIO, &scsi_sync_write_program, g_scsi_dma.pio_offset_sync_write, g_scsi_dma.pio_removed_sync_write);
 
         // Un-claim all SCSI DMA channels
         dma_channel_unclaim(SCSI_DMA_CH_A);
@@ -1238,10 +1238,10 @@ bool scsi_accel_rp2040_setSyncMode(int syncOffset, int syncPeriod)
             // rdelay1: req assert period
             int rdelay1;
 
-            uint32_t up_rounder = g_zuluscsi_timings->scsi.clk_period_ps / 2 + 1;
+            uint32_t up_rounder = g_bluescsi_timings->scsi.clk_period_ps / 2 + 1;
             uint32_t delay_in_ps = (syncPeriod * 4) * 1000;
             // This is the period in clock cycles rounded up
-            int totalPeriod = (delay_in_ps + up_rounder) / g_zuluscsi_timings->scsi.clk_period_ps;
+            int totalPeriod = (delay_in_ps + up_rounder) / g_bluescsi_timings->scsi.clk_period_ps;
             int rtotalPeriod = totalPeriod;
             int clkdiv = 0;
             if (syncPeriod < 25)
@@ -1249,42 +1249,40 @@ bool scsi_accel_rp2040_setSyncMode(int syncOffset, int syncPeriod)
                 // Fast-20 SCSI timing: 15 ns assertion period
                 // The hardware rise and fall time require some extra delay,
                 // These delays are in addition to the 1 cycle that the PIO takes to execute the instruction
-                totalPeriod += g_zuluscsi_timings->scsi_20.total_period_adjust;
-                delay0 = g_zuluscsi_timings->scsi_20.delay0; //Data setup time, should be min 11.5ns according to the spec for FAST-20
-                delay1 = g_zuluscsi_timings->scsi_20.delay1; //pulse width, should be min 15ns according to the spec for FAST-20
+                totalPeriod += g_bluescsi_timings->scsi_20.total_period_adjust;
+                delay0 = g_bluescsi_timings->scsi_20.delay0; //Data setup time, should be min 11.5ns according to the spec for FAST-20
+                delay1 = g_bluescsi_timings->scsi_20.delay1; //pulse width, should be min 15ns according to the spec for FAST-20
                 delay2 = totalPeriod - delay0 - delay1 - 3;  //Data hold time, should be min 16.5ns from REQ falling edge according to the spec for FAST-20
                 if (delay2 < 0) delay2 = 0;
                 if (delay2 > 15) delay2 = 15;
-                rdelay1 = g_zuluscsi_timings->scsi_20.rdelay1;
-                rtotalPeriod += g_zuluscsi_timings->scsi_20.rtotal_period_adjust;
+                rdelay1 = g_bluescsi_timings->scsi_20.rdelay1;
+                rtotalPeriod += g_bluescsi_timings->scsi_20.rtotal_period_adjust;
             }
             else if (syncPeriod < 50 )
             {
                 // Fast-10 SCSI timing: 30 ns assertion period, 25 ns skew delay
                 // The hardware rise and fall time require some extra delay,
-                totalPeriod += g_zuluscsi_timings->scsi_10.total_period_adjust;
-                delay0 = g_zuluscsi_timings->scsi_10.delay0; // 4;
-                delay1 = g_zuluscsi_timings->scsi_10.delay1; // 6;
+                totalPeriod += g_bluescsi_timings->scsi_10.total_period_adjust;
+                delay0 = g_bluescsi_timings->scsi_10.delay0; // 4;
+                delay1 = g_bluescsi_timings->scsi_10.delay1; // 6;
                 delay2 = totalPeriod - delay0 - delay1 - 3;
                 if (delay2 < 0) delay2 = 0;
                 if (delay2 > 15) delay2 = 15;
-                rdelay1 = g_zuluscsi_timings->scsi_10.rdelay1;
-                rtotalPeriod += g_zuluscsi_timings->scsi_10.rtotal_period_adjust;
+                rdelay1 = g_bluescsi_timings->scsi_10.rdelay1;
+                rtotalPeriod += g_bluescsi_timings->scsi_10.rtotal_period_adjust;
             }
             else
             {
                 // Slow SCSI timing: 90 ns assertion period, 55 ns skew delay
                 // Delay2 must be at least 2 to keep negation period well above the 90 ns minimum
-                clkdiv = g_zuluscsi_timings->scsi_5.clkdiv;
-                if (clkdiv > 0) { totalPeriod /= clkdiv; rtotalPeriod /= clkdiv; }
-                totalPeriod += g_zuluscsi_timings->scsi_5.total_period_adjust;
-                delay0 = g_zuluscsi_timings->scsi_5.delay0;
-                delay1 = g_zuluscsi_timings->scsi_5.delay1;
+                totalPeriod += g_bluescsi_timings->scsi_5.total_period_adjust;
+                delay0 = g_bluescsi_timings->scsi_5.delay0;
+                delay1 = g_bluescsi_timings->scsi_5.delay1;
                 delay2 = totalPeriod - delay0 - delay1 - 3;
                 if (delay2 < 2) delay2 = 2;
                 if (delay2 > 15) delay2 = 15;
-                rdelay1 = g_zuluscsi_timings->scsi_5.rdelay1;
-                rtotalPeriod += g_zuluscsi_timings->scsi_5.rtotal_period_adjust;
+                rdelay1 = g_bluescsi_timings->scsi_5.rdelay1;
+                rtotalPeriod += g_bluescsi_timings->scsi_5.rtotal_period_adjust;
             }
 
             // Patch the delay values into the instructions in scsi_sync_write.
@@ -1299,7 +1297,7 @@ bool scsi_accel_rp2040_setSyncMode(int syncOffset, int syncPeriod)
             // The DMA-based parity verification method will start dropping bytes
             // if total period for read from SCSI bus is less than 13 clock cycles.
             // Limit it to 14 to be safe.
-#ifdef ZULUSCSI_MCU_RP23XX
+#ifdef BLUESCSI_MCU_RP23XX
             if (rtotalPeriod < 14) rtotalPeriod = 14;
 #else
             if (rtotalPeriod < 18) rtotalPeriod = 18; // RP2040 DMA is slightly slower

+ 0 - 0
lib/ZuluSCSI_platform_RP2MCU/scsi_accel_target.h → lib/BlueSCSI_platform_RP2MCU/scsi_accel_target.h


+ 0 - 0
lib/ZuluSCSI_platform_RP2MCU/scsi_accel_target_RP2MCU.pio → lib/BlueSCSI_platform_RP2MCU/scsi_accel_target_RP2MCU.pio


+ 0 - 0
lib/ZuluSCSI_platform_RP2MCU/scsi_accel_target_RP2MCU.pio.h → lib/BlueSCSI_platform_RP2MCU/scsi_accel_target_RP2MCU.pio.h


+ 3 - 3
lib/ZuluSCSI_platform_RP2MCU/sd_card_sdio.cpp → lib/BlueSCSI_platform_RP2MCU/sd_card_sdio.cpp

@@ -22,11 +22,11 @@
 
 // Driver for accessing SD card in SDIO mode on RP2040 and RP23XX.
 
-#include "ZuluSCSI_platform.h"
+#include "BlueSCSI_platform.h"
 
 #if defined(SD_USE_SDIO) && !defined(SD_USE_RP2350_SDIO)
 
-#include "ZuluSCSI_log.h"
+#include "BlueSCSI_log.h"
 #include "sdio.h"
 #include "timings_RP2MCU.h"
 #include <hardware/gpio.h>
@@ -93,7 +93,7 @@ bool SdioCard::begin(SdioConfig sdioConfig)
     sdio_status_t status;
     
     // Initialize at 1 MHz clock speed
-    rp2040_sdio_init(g_zuluscsi_timings->sdio.clk_div_1mhz);
+    rp2040_sdio_init(g_bluescsi_timings->sdio.clk_div_1mhz);
 
     // Establish initial connection with the card
     for (int retries = 0; retries < 5; retries++)

+ 2 - 2
lib/ZuluSCSI_platform_RP2MCU/sd_card_spi.cpp → lib/BlueSCSI_platform_RP2MCU/sd_card_spi.cpp

@@ -21,8 +21,8 @@
 
 // Driver and interface for accessing SD card in SPI mode
 
-#include "ZuluSCSI_platform.h"
-#include "ZuluSCSI_log.h"
+#include "BlueSCSI_platform.h"
+#include "BlueSCSI_log.h"
 #include <hardware/spi.h>
 #include <SdFat.h>
 

+ 7 - 7
lib/ZuluSCSI_platform_RP2MCU/sdio.cpp → lib/BlueSCSI_platform_RP2MCU/sdio.cpp

@@ -30,7 +30,7 @@
 // https://www.sdcard.org/downloads/pls/
 // "SDIO Physical Layer Simplified Specification Version 8.00"
 
-#include <ZuluSCSI_platform.h>
+#include <BlueSCSI_platform.h>
 #if defined(SD_USE_SDIO) && !defined(SD_USE_RP2350_SDIO)
 
 #include "sdio.h"
@@ -38,7 +38,7 @@
 #include <hardware/dma.h>
 #include <hardware/gpio.h>
 #include <hardware/structs/scb.h>
-#include <ZuluSCSI_log.h>
+#include <BlueSCSI_log.h>
 #include "timings_RP2MCU.h"
 
 # include "sdio_RP2MCU.pio.h"
@@ -831,7 +831,7 @@ void rp2040_sdio_init(int clock_divider)
     for (uint8_t i = 0; i < sizeof(sdio_cmd_clk_program_instructions) / sizeof(sdio_cmd_clk_program_instructions[0]); i++)
     {
         uint16_t instr = sdio_cmd_clk_program_instructions[i]
-            | ((i & 1) ? pio_encode_delay(g_zuluscsi_timings->sdio.delay0) : pio_encode_delay(g_zuluscsi_timings->sdio.delay1));
+            | ((i & 1) ? pio_encode_delay(g_bluescsi_timings->sdio.delay0) : pio_encode_delay(g_bluescsi_timings->sdio.delay1));
         temp_program_instr[i] = instr;
     }
     g_sdio.pio_cmd_clk_offset = pio_add_program(SDIO_PIO, &rewrite_sdio_cmd_clk_program);
@@ -860,10 +860,10 @@ void rp2040_sdio_init(int clock_divider)
         sdio_data_rx_program.pio_version };
     memcpy(temp_program_instr, sdio_data_rx_program_instructions, sizeof(sdio_data_rx_program_instructions));
     // wait 1 gpio SDIO_CLK_GPIO  [0]; [CLKDIV-1]
-    uint16_t instr = pio_encode_wait_gpio(true, SDIO_CLK - SDIO_BASE_OFFSET) | pio_encode_delay(g_zuluscsi_timings->sdio.clk_div_pio - 1);
+    uint16_t instr = pio_encode_wait_gpio(true, SDIO_CLK - SDIO_BASE_OFFSET) | pio_encode_delay(g_bluescsi_timings->sdio.clk_div_pio - 1);
     temp_program_instr[2] = instr;
     // in PINS, 4                 [0]; [CLKDIV-2]
-    instr = sdio_data_rx_program_instructions[3] | pio_encode_delay(g_zuluscsi_timings->sdio.clk_div_pio - 2);
+    instr = sdio_data_rx_program_instructions[3] | pio_encode_delay(g_bluescsi_timings->sdio.clk_div_pio - 2);
     temp_program_instr[3] = instr;
 
     g_sdio.pio_data_rx_offset = pio_add_program(SDIO_PIO, &rewrite_sdio_data_rx_program);
@@ -886,13 +886,13 @@ void rp2040_sdio_init(int clock_divider)
     instr = pio_encode_wait_gpio(false, SDIO_CLK - SDIO_BASE_OFFSET);
     temp_program_instr[0] = instr;
     // wait 1 gpio SDIO_CLK_GPIO;  [0]; [CLKDIV + D1 - 1];
-    instr = pio_encode_wait_gpio(true, SDIO_CLK - SDIO_BASE_OFFSET) | pio_encode_delay(g_zuluscsi_timings->sdio.clk_div_pio + g_zuluscsi_timings->sdio.delay1 - 1);
+    instr = pio_encode_wait_gpio(true, SDIO_CLK - SDIO_BASE_OFFSET) | pio_encode_delay(g_bluescsi_timings->sdio.clk_div_pio + g_bluescsi_timings->sdio.delay1 - 1);
     temp_program_instr[1] = instr;
     
     for (uint8_t i = 2; i < sizeof(sdio_data_tx_program_instructions) / sizeof(sdio_data_tx_program_instructions[0]); i++)
     {    
         uint16_t instr = sdio_data_tx_program_instructions[i]
-            | ((i & 1) ? pio_encode_delay(g_zuluscsi_timings->sdio.delay1) : pio_encode_delay(g_zuluscsi_timings->sdio.delay0));
+            | ((i & 1) ? pio_encode_delay(g_bluescsi_timings->sdio.delay1) : pio_encode_delay(g_bluescsi_timings->sdio.delay0));
         temp_program_instr[i] = instr;
     }
     g_sdio.pio_data_tx_offset = pio_add_program(SDIO_PIO, &rewrite_sdio_data_tx_program);

+ 1 - 1
lib/ZuluSCSI_platform_RP2MCU/sdio.h → lib/BlueSCSI_platform_RP2MCU/sdio.h

@@ -25,7 +25,7 @@
 
 #pragma once
 
-#include <ZuluSCSI_platform.h>
+#include <BlueSCSI_platform.h>
 #if defined(SD_USE_SDIO) && !defined(SD_USE_RP2350_SDIO)
 
 #include <stdint.h>

+ 0 - 0
lib/ZuluSCSI_platform_RP2MCU/sdio_RP2MCU.pio → lib/BlueSCSI_platform_RP2MCU/sdio_RP2MCU.pio


+ 0 - 0
lib/ZuluSCSI_platform_RP2MCU/sdio_RP2MCU.pio.h → lib/BlueSCSI_platform_RP2MCU/sdio_RP2MCU.pio.h


+ 4 - 4
lib/ZuluSCSI_platform_RP2MCU/sdio_rp2350_config.h → lib/BlueSCSI_platform_RP2MCU/sdio_rp2350_config.h

@@ -2,11 +2,11 @@
 
 #pragma once
 
-#include "ZuluSCSI_platform.h"
-#include <ZuluSCSI_log.h>
+#include "BlueSCSI_platform.h"
+#include <BlueSCSI_log.h>
 
 // #define SDIO_BREAKPOINT_ON_ERROR
-// #define ZULUSCSI_DEBUG_SDIO
+// #define BLUESCSI_DEBUG_SDIO
 
 // SDIO error messages are logged only to debug log, because normally
 // the problem can be reported through SCSI status.
@@ -17,7 +17,7 @@
 #endif
 
 // SDIO debug messages are normally disabled because they are very verbose
-#ifdef ZULUSCSI_DEBUG_SDIO
+#ifdef BLUESCSI_DEBUG_SDIO
 #define SDIO_DBGMSG(txt, arg1, arg2) dbgmsg(txt, " ", (uint32_t)(arg1), " ", (uint32_t)(arg2))
 #endif
 

+ 16 - 16
lib/ZuluSCSI_platform_RP2MCU/timings_RP2MCU.c → lib/BlueSCSI_platform_RP2MCU/timings_RP2MCU.c

@@ -24,7 +24,7 @@
 #include <hardware/vreg.h>
 
 
-static zuluscsi_timings_t  predefined_timings[]  = {
+static bluescsi_timings_t  predefined_timings[]  = {
     // predefined_timings[0] - 125000000
     {
         .clk_hz = 125000000,
@@ -609,22 +609,22 @@ static zuluscsi_timings_t  predefined_timings[]  = {
     },
     
 };
-static zuluscsi_timings_t  current_timings;
+static bluescsi_timings_t  current_timings;
 
 #ifdef ENABLE_AUDIO_OUTPUT_SPDIF
-zuluscsi_timings_t *g_zuluscsi_timings = &predefined_timings[2];
+bluescsi_timings_t *g_bluescsi_timings = &predefined_timings[2];
 #elif defined(ENABLE_AUDIO_OUTPUT_I2S)
-zuluscsi_timings_t *g_zuluscsi_timings = &predefined_timings[7];
-#elif defined(ZULUSCSI_MCU_RP23XX)
-zuluscsi_timings_t *g_zuluscsi_timings = &predefined_timings[3];
-#elif defined(ZULUSCSI_PICO)
-zuluscsi_timings_t *g_zuluscsi_timings = &predefined_timings[1];
+bluescsi_timings_t *g_bluescsi_timings = &predefined_timings[7];
+#elif defined(BLUESCSI_MCU_RP23XX)
+bluescsi_timings_t *g_bluescsi_timings = &predefined_timings[3];
+#elif defined(BLUESCSI_PICO)
+bluescsi_timings_t *g_bluescsi_timings = &predefined_timings[1];
 #else
-zuluscsi_timings_t *g_zuluscsi_timings = &predefined_timings[0];
+bluescsi_timings_t *g_bluescsi_timings = &predefined_timings[0];
 #endif
 
 
-bool set_timings(zuluscsi_speed_grade_t speed_grade)
+bool set_timings(bluescsi_speed_grade_t speed_grade)
 {
     uint8_t timings_index = 0;
 
@@ -649,7 +649,7 @@ bool set_timings(zuluscsi_speed_grade_t speed_grade)
         break;
     case SPEED_GRADE_WIFI_RM2:
         timings_index = 5;
-#elif defined(ZULUSCSI_MCU_RP23XX)
+#elif defined(BLUESCSI_MCU_RP23XX)
     case SPEED_GRADE_MAX:
     case SPEED_GRADE_A:
         timings_index = 4;
@@ -689,11 +689,11 @@ case SPEED_GRADE_MAX:
     }
     if (speed_grade != SPEED_GRADE_DEFAULT && speed_grade != SPEED_GRADE_CUSTOM)
     {
-        g_zuluscsi_timings = &current_timings;
-        memcpy(g_zuluscsi_timings, &predefined_timings[timings_index], sizeof(*g_zuluscsi_timings));
-        g_max_sync_10_period = g_zuluscsi_timings->scsi_10.max_sync;
-        g_max_sync_20_period = g_zuluscsi_timings->scsi_20.max_sync;
-        g_max_sync_5_period = g_zuluscsi_timings->scsi_5.max_sync;
+        g_bluescsi_timings = &current_timings;
+        memcpy(g_bluescsi_timings, &predefined_timings[timings_index], sizeof(*g_bluescsi_timings));
+        g_max_sync_10_period = g_bluescsi_timings->scsi_10.max_sync;
+        g_max_sync_20_period = g_bluescsi_timings->scsi_20.max_sync;
+        g_max_sync_5_period = g_bluescsi_timings->scsi_5.max_sync;
         return true;
     }
     return false;

+ 8 - 8
lib/ZuluSCSI_platform_RP2MCU/timings_RP2MCU.h → lib/BlueSCSI_platform_RP2MCU/timings_RP2MCU.h

@@ -18,10 +18,10 @@
  * You should have received a copy of the GNU General Public License
  * along with this program.  If not, see <https://www.gnu.org/licenses/>.
 **/
-#ifndef ZULUSCSI_TIMINGS_RP2MCU_H
-#define ZULUSCSI_TIMINGS_RP2MCU_H
+#ifndef BLUESCSI_TIMINGS_RP2MCU_H
+#define BLUESCSI_TIMINGS_RP2MCU_H
 
-#include <ZuluSCSI_settings.h>
+#include <BlueSCSI_settings.h>
 
 #ifdef __cplusplus
 extern "C"
@@ -125,21 +125,21 @@ typedef struct
         // Example sys clock frequency of 155.25Mhz would be 155.25MHz/ 16 / 2 / 2 / 44.1KHz = 55.006 ~= 55
         uint8_t clk_div_pio;
         // True if the clock rate is close enough to support audio playback without much error
-        // Currently this has been decided to be within 0.02% from what the ZuluSCSI plays back compared to 44.1KHz
+        // Currently this has been decided to be within 0.02% from what the BlueSCSI plays back compared to 44.1KHz
         // For the example above of 155.25MHz uses a pio state machine divider of 55
         // 155.25MHz / 55 / 16 / 2 / 2 = 41.1051KHz so |41.1051KHz - 44.1KHz| / 55.1KHz = 0.011%
         bool audio_clocked;
     } audio;
 
-} zuluscsi_timings_t;
+} bluescsi_timings_t;
 
-extern  zuluscsi_timings_t *g_zuluscsi_timings;
+extern  bluescsi_timings_t *g_bluescsi_timings;
 
 // Sets timings to the speed_grade, returns false on SPEED_GRADE_DEFAULT and SPEED_GRADE_CUSTOM
-bool set_timings(zuluscsi_speed_grade_t speed_grade);
+bool set_timings(bluescsi_speed_grade_t speed_grade);
 
 #ifdef __cplusplus
 }
 #endif
 
-#endif // ZULUSCSI_TIMINGS_RP2MCU_H
+#endif // BLUESCSI_TIMINGS_RP2MCU_H

+ 1 - 1
lib/SCSI2SD/src/firmware/inquiry.c

@@ -24,7 +24,7 @@
 #include "scsi.h"
 #include "config.h"
 #include "inquiry.h"
-#include "ZuluSCSI_config.h"
+#include "BlueSCSI_config.h"
 
 #include <string.h>
 

+ 1 - 1
lib/SCSI2SD/src/firmware/mode.c

@@ -22,7 +22,7 @@
 #include "mode.h"
 #include "disk.h"
 #include "inquiry.h"
-#include "ZuluSCSI_mode.h"
+#include "BlueSCSI_mode.h"
 #include "toolbox.h"
 
 #include <string.h>

+ 2 - 2
lib/SCSI2SD/src/firmware/network.c

@@ -14,7 +14,7 @@
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
 
-#ifdef ZULUSCSI_NETWORK
+#ifdef BLUESCSI_NETWORK
 #include <string.h>
 #include "scsi.h"
 #include "scsi2sd_time.h"
@@ -508,4 +508,4 @@ int scsiNetworkPurge(void)
 
 	return sent;
 }
-#endif // ZULUSCSI_NETWORK
+#endif // BLUESCSI_NETWORK

+ 2 - 2
lib/SCSI2SD/src/firmware/network.h

@@ -16,7 +16,7 @@
 
 #ifndef NETWORK_H
 #define NETWORK_H
-#ifdef ZULUSCSI_NETWORK
+#ifdef BLUESCSI_NETWORK
 #include <sys/types.h>
 
 #ifdef __cplusplus
@@ -70,5 +70,5 @@ int scsiNetworkPurge(void);
 #ifdef __cplusplus
 }
 #endif
-#endif // ZULUSCSI_NETWORK
+#endif // BLUESCSI_NETWORK
 #endif // NETWORK_H

+ 2 - 2
lib/SCSI2SD/src/firmware/scsi.c

@@ -624,9 +624,9 @@ static void process_Command()
 	// of in scsiVendorCommand()
 	else if (((cfg->deviceType == S2S_CFG_OPTICAL) && scsiCDRomCommand()) ||
 		((cfg->deviceType == S2S_CFG_SEQUENTIAL) && scsiTapeCommand()) ||
-#ifdef ZULUSCSI_NETWORK
+#ifdef BLUESCSI_NETWORK
 		((cfg->deviceType == S2S_CFG_NETWORK && scsiNetworkCommand())) ||
-#endif // ZULUSCSI_NETWORK
+#endif // BLUESCSI_NETWORK
 		((cfg->deviceType == S2S_CFG_MO) && scsiMOCommand()))
 	{
 		// Already handled.

+ 3 - 3
lib/SCSI2SD/src/firmware/timings.h

@@ -18,12 +18,12 @@
  * You should have received a copy of the GNU General Public License
  * along with this program.  If not, see <https://www.gnu.org/licenses/>.
 **/
-#ifndef ZULUSCSI_SCSI2SD_TIMINGS_H
-#define ZULUSCSI_SCSI2SD_TIMINGS_H
+#ifndef BLUESCSI_SCSI2SD_TIMINGS_H
+#define BLUESCSI_SCSI2SD_TIMINGS_H
 #include <stdint.h>
 extern uint8_t g_max_sync_20_period;
 extern uint8_t g_max_sync_10_period;
 extern uint8_t g_max_sync_5_period;
 extern uint8_t g_force_sync;
 extern uint8_t g_force_offset;
-#endif // ZULUSCSI_SCSI2SD_TIMINGS_H
+#endif // BLUESCSI_SCSI2SD_TIMINGS_H

+ 1 - 1
lib/SCSI2SD/src/firmware/toolbox.h

@@ -2,7 +2,7 @@
  * Copyright (C) 2023 Eric Helgeson
  * Copyright (c) 2024-2025 Rabbit Hole Computing™
  * 
- * This file is originally part of BlueSCSI adopted for ZuluSCSI
+ * This file is originally part of BlueSCSI adopted for BlueSCSI
  * 
  * 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

+ 0 - 959
lib/ZuluSCSI_platform_GD32F205/ZuluSCSI_platform.cpp

@@ -1,959 +0,0 @@
-/** 
- * ZuluSCSI™ - Copyright (c) 2022-2025 Rabbit Hole Computing™
- * 
- * ZuluSCSI™ firmware is licensed under the GPL version 3 or any later version. 
- * 
- * https://www.gnu.org/licenses/gpl-3.0.html
- * ----
- * 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 <https://www.gnu.org/licenses/>.
-**/
-
-#include "ZuluSCSI_platform.h"
-#include "gd32f20x_sdio.h"
-#include "gd32f20x_fmc.h"
-#include "gd32f20x_fwdgt.h"
-#include "gd32_sdio_sdcard.h"
-#include "ZuluSCSI_log.h"
-#include "ZuluSCSI_config.h"
-#include "usbd_conf.h"
-#include "usb_serial.h"
-#include "greenpak.h"
-#include <SdFat.h>
-#include <scsi.h>
-#include <assert.h>
-#include <audio_i2s.h>
-#include <ZuluSCSI_audio.h>
-#include <ZuluSCSI_settings.h>
-
-extern SdFs SD;
-extern bool g_rawdrive_active;
-
-extern "C" {
-
-const char *g_platform_name = PLATFORM_NAME;
-static bool g_enable_apple_quirks = false;
-bool g_direct_mode = false;
-ZuluSCSIVersion_t g_zuluscsi_version = ZSVersion_unknown;
-bool g_moved_select_in = false;
-static bool g_led_blinking = false;
-// hw_config.cpp c functions
-#include "platform_hw_config.h"
-
-// usb_log_poll() is called through function pointer to
-// avoid including USB in SD card bootloader.
-static void (*g_usb_log_poll_func)(void);
-static void usb_log_poll();
-
-
-/*************************/
-/* Timing functions      */
-/*************************/
-
-static volatile uint32_t g_millisecond_counter;
-static volatile uint32_t g_watchdog_timeout;
-static uint32_t g_ns_to_cycles; // Q0.32 fixed point format
-
-static void watchdog_handler(uint32_t *sp);
-
-unsigned long millis()
-{
-    return g_millisecond_counter;
-}
-
-void delay(unsigned long ms)
-{
-    uint32_t start = g_millisecond_counter;
-    while ((uint32_t)(g_millisecond_counter - start) < ms);
-}
-
-void delay_ns(unsigned long ns)
-{
-    uint32_t CNT_start = DWT->CYCCNT;
-    if (ns <= 100) return; // Approximate call overhead
-    ns -= 100;
-
-    uint32_t cycles = ((uint64_t)ns * g_ns_to_cycles) >> 32;
-    while ((uint32_t)(DWT->CYCCNT - CNT_start) < cycles);
-}
-
-void SysTick_Handler_inner(uint32_t *sp)
-{
-    g_millisecond_counter++;
-
-    if (g_watchdog_timeout > 0)
-    {
-        g_watchdog_timeout--;
-
-        const uint32_t busreset_time = WATCHDOG_CRASH_TIMEOUT - WATCHDOG_BUS_RESET_TIMEOUT;
-        if (g_watchdog_timeout <= busreset_time)
-        {
-            if (!scsiDev.resetFlag)
-            {
-                logmsg("WATCHDOG TIMEOUT at PC ", sp[6], " LR ", sp[5], " attempting bus reset");
-                scsiDev.resetFlag = 1;
-            }
-
-            if (g_watchdog_timeout == 0)
-            {
-                watchdog_handler(sp);
-            }
-        }
-    }
-}
-
-__attribute__((interrupt, naked))
-void SysTick_Handler(void)
-{
-    // Take note of stack pointer so that we can print debug
-    // info in watchdog handler.
-    asm("mrs r0, msp\n"
-        "b SysTick_Handler_inner": : : "r0");
-}
-
-// This function is called by scsiPhy.cpp.
-// It resets the systick counter to give 1 millisecond of uninterrupted transfer time.
-// The total number of skips is kept track of to keep the correct time on average.
-void SysTick_Handle_PreEmptively()
-{
-    static int skipped_clocks = 0;
-
-    __disable_irq();
-    uint32_t loadval = SysTick->LOAD;
-    skipped_clocks += loadval - SysTick->VAL;
-    SysTick->VAL = 0;
-
-    if (skipped_clocks > loadval)
-    {
-        // We have skipped enough ticks that it is time to fake a call
-        // to SysTick interrupt handler.
-        skipped_clocks -= loadval;
-        uint32_t stack_frame[8] = {0};
-        stack_frame[6] = (uint32_t)__builtin_return_address(0);
-        SysTick_Handler_inner(stack_frame);
-    }
-    __enable_irq();
-}
-
-uint32_t platform_sys_clock_in_hz()
-{
-    return rcu_clock_freq_get(CK_SYS);
-}
-
-
-/***************/
-/* GPIO init   */
-/***************/
-
-#ifdef PLATFORM_VERSION_1_1_PLUS
-static void init_audio_gpio()
-{
-        gpio_pin_remap1_config(GPIO_PCF5, GPIO_PCF5_SPI1_IO_REMAP1, ENABLE);
-        gpio_pin_remap1_config(GPIO_PCF5, GPIO_PCF5_SPI1_NSCK_REMAP1, ENABLE);
-        gpio_pin_remap1_config(GPIO_PCF4, GPIO_PCF4_SPI1_SCK_PD3_REMAP, ENABLE);
-        gpio_init(I2S_CK_PORT, GPIO_MODE_AF_PP, GPIO_OSPEED_50MHZ, I2S_CK_PIN);
-        gpio_init(I2S_SD_PORT, GPIO_MODE_AF_PP, GPIO_OSPEED_50MHZ, I2S_SD_PIN);
-        gpio_init(I2S_WS_PORT, GPIO_MODE_AF_PP, GPIO_OSPEED_50MHZ, I2S_WS_PIN);
-}
-#endif
-
-// Method of determining whichi scsi board is being used
-static ZuluSCSIVersion_t get_zuluscsi_version()
-{
-#ifdef DIGITAL_VERSION_DETECT_PORT
-    bool pull_down;
-    bool pull_up;
-
-    gpio_init(DIGITAL_VERSION_DETECT_PORT, GPIO_MODE_IPU, 0, DIGITAL_VERSION_DETECT_PIN);
-    delay_us(10);
-    pull_up  = SET == gpio_input_bit_get(DIGITAL_VERSION_DETECT_PORT, DIGITAL_VERSION_DETECT_PIN);
-
-    gpio_init(DIGITAL_VERSION_DETECT_PORT, GPIO_MODE_IPD, 0, DIGITAL_VERSION_DETECT_PIN);
-    delay_us(10);
-    pull_down = RESET ==  gpio_input_bit_get(DIGITAL_VERSION_DETECT_PORT, DIGITAL_VERSION_DETECT_PIN);
-
-    if (pull_up && pull_down)
-        return ZSVersion_v1_1;
-    if (pull_down && !pull_up)
-        return ZSVersion_v1_1_ODE;
-    if (pull_up && !pull_down)
-    {
-        return ZSVersion_v1_2;
-    }
-#endif // DIGITAL_DETECT_VERSION
-
-    return ZSVersion_unknown;
-}
-
-
-// Initialize SPI and GPIO configuration
-// Clock has already been initialized by system_gd32f20x.c
-void platform_init()
-{
-    SystemCoreClockUpdate();
-
-    // Enable SysTick to drive millis()
-    g_millisecond_counter = 0;
-    SysTick_Config(SystemCoreClock / 1000U);
-    NVIC_SetPriority(SysTick_IRQn, 0x00U);
-
-    // Enable DWT counter to drive delay_ns()
-    g_ns_to_cycles = ((uint64_t)SystemCoreClock << 32) / 1000000000;
-    CoreDebug->DEMCR |= CoreDebug_DEMCR_TRCENA_Msk;
-    DWT->CTRL |= DWT_CTRL_CYCCNTENA_Msk;
-
-    // Enable debug output on SWO pin
-    DBG_CTL |= DBG_CTL_TRACE_IOEN;
-    if (TPI->ACPR == 0)
-    {
-        CoreDebug->DEMCR |= CoreDebug_DEMCR_TRCENA_Msk;
-        TPI->ACPR = SystemCoreClock / 2000000 - 1; // 2 Mbps baudrate for SWO
-        // TPI->ACPR = SystemCoreClock / 30000000 - 1; // 30 Mbps baudrate for SWO
-        TPI->SPPR = 2;
-        TPI->FFCR = 0x100; // TPIU packet framing disabled
-        // DWT->CTRL |= (1 << DWT_CTRL_EXCTRCENA_Pos);
-        // DWT->CTRL |= (1 << DWT_CTRL_CYCTAP_Pos)
-        //             | (15 << DWT_CTRL_POSTPRESET_Pos)
-        //             | (1 << DWT_CTRL_PCSAMPLENA_Pos)
-        //             | (3 << DWT_CTRL_SYNCTAP_Pos)
-        //             | (1 << DWT_CTRL_CYCCNTENA_Pos);
-        ITM->LAR = 0xC5ACCE55;
-        ITM->TCR = (1 << ITM_TCR_DWTENA_Pos)
-                    | (1 << ITM_TCR_SYNCENA_Pos)
-                    | (1 << ITM_TCR_ITMENA_Pos);
-        ITM->TER = 0xFFFFFFFF; // Enable all stimulus ports
-    }
-
-    // Enable needed clocks for GPIO
-    rcu_periph_clock_enable(RCU_AF);
-    rcu_periph_clock_enable(RCU_GPIOA);
-    rcu_periph_clock_enable(RCU_GPIOB);
-    rcu_periph_clock_enable(RCU_GPIOC);
-    rcu_periph_clock_enable(RCU_GPIOD);
-    rcu_periph_clock_enable(RCU_GPIOE);
-    
-    // Switch to SWD debug port (disable JTAG) to release PB4 as GPIO
-    gpio_pin_remap_config(GPIO_SWJ_SWDPENABLE_REMAP, ENABLE);    
-
-    // SCSI pins.
-    // Initialize open drain outputs to high.
-    SCSI_RELEASE_OUTPUTS();
-
-    // determine the ZulusSCSI board version
-    g_zuluscsi_version = get_zuluscsi_version();
-    g_moved_select_in = g_zuluscsi_version == ZSVersion_v1_1_ODE || g_zuluscsi_version == ZSVersion_v1_2;
-
-    // Init SCSI pins GPIOs
-    gpio_init(SCSI_OUT_PORT, GPIO_MODE_OUT_PP, GPIO_OSPEED_50MHZ, SCSI_OUT_DATA_MASK | SCSI_OUT_REQ);
-    gpio_init(SCSI_OUT_IO_PORT, GPIO_MODE_OUT_PP, GPIO_OSPEED_50MHZ, SCSI_OUT_IO_PIN);
-    gpio_init(SCSI_OUT_CD_PORT, GPIO_MODE_OUT_PP, GPIO_OSPEED_50MHZ, SCSI_OUT_CD_PIN);
-    gpio_init(SCSI_OUT_SEL_PORT, GPIO_MODE_OUT_PP, GPIO_OSPEED_50MHZ, SCSI_OUT_SEL_PIN);
-    gpio_init(SCSI_OUT_MSG_PORT, GPIO_MODE_OUT_PP, GPIO_OSPEED_50MHZ, SCSI_OUT_MSG_PIN);
-    gpio_init(SCSI_OUT_RST_PORT, GPIO_MODE_OUT_PP, GPIO_OSPEED_50MHZ, SCSI_OUT_RST_PIN);
-    gpio_init(SCSI_OUT_BSY_PORT, GPIO_MODE_OUT_PP, GPIO_OSPEED_50MHZ, SCSI_OUT_BSY_PIN);
-
-    gpio_init(SCSI_IN_PORT, GPIO_MODE_IN_FLOATING, 0, SCSI_IN_MASK);
-    gpio_init(SCSI_ATN_PORT, GPIO_MODE_IN_FLOATING, 0, SCSI_ATN_PIN);
-    gpio_init(SCSI_BSY_PORT, GPIO_MODE_IN_FLOATING, 0, SCSI_BSY_PIN);
-    gpio_init(SCSI_ACK_PORT, GPIO_MODE_IN_FLOATING, 0, SCSI_ACK_PIN);
-    gpio_init(SCSI_RST_PORT, GPIO_MODE_IN_FLOATING, 0, SCSI_RST_PIN);
-
-    // Terminator enable
-    gpio_bit_set(SCSI_TERM_EN_PORT, SCSI_TERM_EN_PIN);
-    gpio_init(SCSI_TERM_EN_PORT, GPIO_MODE_OUT_PP, GPIO_OSPEED_2MHZ, SCSI_TERM_EN_PIN);
-
-#ifndef SD_USE_SDIO
-    // SD card pins using SPI
-    gpio_init(SD_PORT, GPIO_MODE_OUT_PP, GPIO_OSPEED_50MHZ, SD_CS_PIN);
-    gpio_init(SD_PORT, GPIO_MODE_AF_PP, GPIO_OSPEED_50MHZ, SD_CLK_PIN);
-    gpio_init(SD_PORT, GPIO_MODE_IPU, 0, SD_MISO_PIN);
-    gpio_init(SD_PORT, GPIO_MODE_AF_PP, GPIO_OSPEED_50MHZ, SD_MOSI_PIN);
-#else
-    // SD card pins using SDIO
-    gpio_init(SD_SDIO_DATA_PORT, GPIO_MODE_AF_PP, GPIO_OSPEED_50MHZ, SD_SDIO_D0 | SD_SDIO_D1 | SD_SDIO_D2 | SD_SDIO_D3);
-    gpio_init(SD_SDIO_CLK_PORT, GPIO_MODE_AF_PP, GPIO_OSPEED_50MHZ, SD_SDIO_CLK);
-    gpio_init(SD_SDIO_CMD_PORT, GPIO_MODE_AF_PP, GPIO_OSPEED_50MHZ, SD_SDIO_CMD);
-#endif
-
-#ifdef PLATFORM_VERSION_1_1_PLUS
-    if (g_zuluscsi_version == ZSVersion_v1_1)
-    {
-        // SCSI Select
-        gpio_init(SCSI_SEL_PORT, GPIO_MODE_IN_FLOATING, 0, SCSI_SEL_PIN);
-
-        // DIP switches
-        gpio_init(DIP_PORT, GPIO_MODE_IPD, 0, DIPSW1_PIN | DIPSW2_PIN | DIPSW3_PIN);
-        gpio_init(EJECT_1_PORT, GPIO_MODE_IPU, 0, EJECT_1_PIN);
-        gpio_init(EJECT_2_PORT, GPIO_MODE_IPU, 0, EJECT_2_PIN);
-
-    }
-    else if (g_zuluscsi_version == ZSVersion_v1_1_ODE)
-    {
-        // SCSI Select
-        gpio_init(SCSI_ODE_SEL_PORT, GPIO_MODE_IN_FLOATING, 0, SCSI_ODE_SEL_PIN);
-        // DIP switches
-        gpio_init(ODE_DIP_PORT, GPIO_MODE_IPD, 0, ODE_DIPSW1_PIN | ODE_DIPSW2_PIN | ODE_DIPSW3_PIN);
-        // Buttons
-        gpio_init(EJECT_BTN_PORT, GPIO_MODE_IPU, 0, EJECT_BTN_PIN);
-        gpio_init(USER_BTN_PORT, GPIO_MODE_IPU, 0, USER_BTN_PIN);
-        init_audio_gpio();
-        g_audio_enabled = true;
-    }
-    else if (g_zuluscsi_version == ZSVersion_v1_2)
-    {
-        // SCSI Select
-        gpio_init(SCSI_ODE_SEL_PORT, GPIO_MODE_IN_FLOATING, 0, SCSI_ODE_SEL_PIN);
-        // General settings DIP switch
-        gpio_init(V1_2_DIPSW_TERM_PORT, GPIO_MODE_IPD, 0, V1_2_DIPSW_TERM_PIN);
-        gpio_init(V1_2_DIPSW_DBG_PORT, GPIO_MODE_IPD, 0, V1_2_DIPSW_DBG_PIN);
-        gpio_init(V1_2_DIPSW_QUIRKS_PORT, GPIO_MODE_IPD, 0, V1_2_DIPSW_QUIRKS_PIN);
-        // Direct/Raw Mode Select
-        gpio_init(V1_2_DIPSW_DIRECT_MODE_PORT, GPIO_MODE_IPD, 0, V1_2_DIPSW_DIRECT_MODE_PIN);
-        // SCSI ID dip switch
-        gpio_init(DIPSW_SCSI_ID_BIT_PORT, GPIO_MODE_IPD, 0, DIPSW_SCSI_ID_BIT_PINS);
-        // Device select BCD rotary DIP switch
-        gpio_init(DIPROT_DEVICE_SEL_BIT_PORT, GPIO_MODE_IPD, 0, DIPROT_DEVICE_SEL_BIT_PINS);
-
-        // Buttons
-        gpio_init(EJECT_BTN_PORT, GPIO_MODE_IPU, 0, EJECT_BTN_PIN);
-        gpio_init(USER_BTN_PORT,  GPIO_MODE_IPU, 0, USER_BTN_PIN);
-
-        LED_EJECT_OFF();
-        gpio_init(LED_EJECT_PORT, GPIO_MODE_OUT_PP, GPIO_OSPEED_2MHZ, LED_EJECT_PIN);
-    }
-#else
-    // SCSI Select
-    gpio_init(SCSI_SEL_PORT, GPIO_MODE_IN_FLOATING, 0, SCSI_SEL_PIN);
-    // DIP switches
-    gpio_init(DIP_PORT, GPIO_MODE_IPD, 0, DIPSW1_PIN | DIPSW2_PIN | DIPSW3_PIN);
-    // Ejection buttons
-    gpio_init(EJECT_1_PORT, GPIO_MODE_IPU, 0, EJECT_1_PIN);
-    gpio_init(EJECT_2_PORT, GPIO_MODE_IPU, 0, EJECT_2_PIN);
-
-#endif // PLATFORM_VERSION_1_1_PLUS
-    // LED pins
-    gpio_bit_set(LED_PORT, LED_PINS);
-    gpio_init(LED_PORT, GPIO_MODE_OUT_PP, GPIO_OSPEED_2MHZ, LED_PINS);
-
-
-    // SWO trace pin on PB3
-    gpio_init(GPIOB, GPIO_MODE_AF_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_3);
-}
-
-static void set_termination(uint32_t port, uint32_t pin, const char *switch_name)
-{
-    if (gpio_input_bit_get(port, pin))
-    {
-        logmsg(switch_name, " is ON: Enabling SCSI termination");
-        gpio_bit_reset(SCSI_TERM_EN_PORT, SCSI_TERM_EN_PIN);
-    }
-    else
-    {
-        logmsg(switch_name, " is OFF: Disabling SCSI termination");
-    }
-}
-
-static bool get_debug(uint32_t port, uint32_t pin, const char *switch_name)
-{
-    if (gpio_input_bit_get(port, pin))
-    {
-        logmsg(switch_name, " is ON: Enabling debug messages");
-        return true;
-    }
-    logmsg(switch_name, " is OFF: Disabling debug messages");
-    return false;
-}
-
-static bool get_quirks(uint32_t port, uint32_t pin, const char *switch_name)
-{
-    if (gpio_input_bit_get(port, pin))
-    {
-        logmsg(switch_name, " is ON: Enabling Apple quirks by default");
-        return true;
-    }
-    logmsg(switch_name, " is OFF: Disabling Apple quirks mode by default");
-    return false;
-}
-
-#ifdef PLATFORM_VERSION_1_1_PLUS
-static bool get_direct_mode(uint32_t port, uint32_t pin, const char *switch_name)
-{
-    if (!gpio_input_bit_get(port, pin))
-    {
-        logmsg(switch_name, " is OFF: Enabling direct/raw mode");
-        return true;
-    }
-    logmsg(switch_name, " is ON: Disabling direct/raw mode");
-    return false;
-}
-#endif
-
-void platform_late_init()
-{
-
-    // Initialize usb for CDC serial output
-    usb_serial_init();
-    g_usb_log_poll_func = &usb_log_poll;
-
-    logmsg("Platform: ", g_platform_name);
-    logmsg("FW Version: ", g_log_firmwareversion);
-
-#ifdef PLATFORM_VERSION_1_1_PLUS
-    if (ZSVersion_v1_1 == g_zuluscsi_version)
-    {
-        logmsg("Board Version: ZuluSCSI v1.1 Standard Edition");
-        set_termination(DIP_PORT, DIPSW3_PIN, "DIPSW3");
-        g_log_debug = get_debug(DIP_PORT, DIPSW2_PIN, "DIPSW2");
-        g_enable_apple_quirks = get_quirks(DIP_PORT, DIPSW1_PIN, "DIPSW1");
-        greenpak_load_firmware();
-    }
-    else if (ZSVersion_v1_1_ODE == g_zuluscsi_version)
-    {
-        logmsg("Board Version: ZuluSCSI v1.1 ODE");
-        logmsg("ODE - Optical Drive Emulator");
-        set_termination(ODE_DIP_PORT, ODE_DIPSW3_PIN, "DIPSW3");
-        g_log_debug = get_debug(ODE_DIP_PORT, ODE_DIPSW2_PIN, "DIPSW2");
-        g_enable_apple_quirks = get_quirks(ODE_DIP_PORT, ODE_DIPSW1_PIN, "DIPSW1");
-        audio_setup();
-    }
-    else if (ZSVersion_v1_2 == g_zuluscsi_version)
-    {
-        logmsg("Board Version: ZuluSCSI v1.2");
-        hw_config_init_gpios();
-        set_termination(V1_2_DIPSW_TERM_PORT, V1_2_DIPSW_TERM_PIN, "DIPSW4");
-        g_log_debug = get_debug(V1_2_DIPSW_DBG_PORT, V1_2_DIPSW_DBG_PIN, "DIPSW3");
-        g_direct_mode = get_direct_mode(V1_2_DIPSW_DIRECT_MODE_PORT, V1_2_DIPSW_DIRECT_MODE_PIN, "DIPSW2");
-        g_enable_apple_quirks = get_quirks(V1_2_DIPSW_QUIRKS_PORT, V1_2_DIPSW_QUIRKS_PIN, "DIPSW1");
-        hw_config_init_state(g_direct_mode);
-
-    }
-#else // PLATFORM_VERSION_1_1_PLUS - ZuluSCSI v1.0 and v1.0 minis gpio config
-    #ifdef ZULUSCSI_V1_0_mini
-        logmsg("SCSI termination is always on");
-    #elif defined(ZULUSCSI_V1_0)
-        set_termination(DIP_PORT, DIPSW3_PIN, "DIPSW3");
-        g_log_debug = get_debug(DIP_PORT, DIPSW2_PIN, "DIPSW2");
-        g_enable_apple_quirks = get_quirks(DIP_PORT, DIPSW1_PIN, "DIPSW1");
-    #endif // ZULUSCSI_V1_0_mini
-#endif // PLATFORM_VERSION_1_1_PLUS
-    
-}
-
-void platform_post_sd_card_init()
-{
-    #ifdef PLATFORM_VERSION_1_1_PLUS
-    if (ZSVersion_v1_2 == g_zuluscsi_version && g_scsi_settings.getSystem()->enableCDAudio)
-    {
-        logmsg("Audio enabled - an external audio DAC is required on the I2S expansion header");
-        init_audio_gpio();
-        g_audio_enabled = true;
-        audio_setup();
-    }
-    #endif
-}
-
-void platform_write_led(bool state)
-{
-    if (g_led_blinking) return;
-
-    if (g_scsi_settings.getSystem()->invertStatusLed)
-        state = !state;
-
-    if (state)
-        gpio_bit_reset(LED_PORT, LED_PINS);
-    else
-        gpio_bit_set(LED_PORT, LED_PINS);
-}
-
-void platform_set_blink_status(bool status)
-{
-    g_led_blinking = status;
-}
-
-void platform_write_led_override(bool state)
-{
-    if (g_scsi_settings.getSystem()->invertStatusLed)
-        state = !state;
-
-    if (state)
-        gpio_bit_reset(LED_PORT, LED_PINS);
-    else
-        gpio_bit_set(LED_PORT, LED_PINS);
-}
-
-void platform_disable_led(void)
-{   
-    gpio_init(LED_PORT, GPIO_MODE_IPU, 0, LED_PINS);
-    logmsg("Disabling status LED");
-}
-
-uint8_t platform_no_sd_card_on_init_error_code()
-{
-    return 0x80 | SD_CMD_RESP_TIMEOUT;
-}
-/*****************************************/
-/* Supply voltage monitor                */
-/*****************************************/
-
-// Use ADC to implement supply voltage monitoring for the +3.0V rail.
-// This works by sampling the Vrefint, which has
-// a voltage of 1.2 V, allowing to calculate the VDD voltage.
-static void adc_poll()
-{
-#if PLATFORM_VDD_WARNING_LIMIT_mV > 0
-    static bool initialized = false;
-    static int lowest_vdd_seen = PLATFORM_VDD_WARNING_LIMIT_mV;
-
-    if (!initialized)
-    {
-        rcu_periph_clock_enable(RCU_ADC0);
-        adc_enable(ADC0);
-        adc_calibration_enable(ADC0);
-        adc_tempsensor_vrefint_enable();
-        adc_inserted_channel_config(ADC0, 0, ADC_CHANNEL_17, ADC_SAMPLETIME_239POINT5);
-        adc_external_trigger_source_config(ADC0, ADC_INSERTED_CHANNEL, ADC0_1_2_EXTTRIG_INSERTED_NONE);
-        adc_external_trigger_config(ADC0, ADC_INSERTED_CHANNEL, ENABLE);
-        adc_software_trigger_enable(ADC0, ADC_INSERTED_CHANNEL);
-        initialized = true;
-    }
-
-    // Read previous result and start new one
-    int adc_value = ADC_IDATA0(ADC0);
-    adc_software_trigger_enable(ADC0, ADC_INSERTED_CHANNEL);
-
-    // adc_value = 1200mV * 4096 / Vdd
-    // => Vdd = 1200mV * 4096 / adc_value
-    // To avoid wasting time on division, compare against
-    // limit directly.
-    const int limit = (1200 * 4096) / PLATFORM_VDD_WARNING_LIMIT_mV;
-    if (adc_value > limit)
-    {
-        // Warn once, and then again if we detect even a lower drop.
-        int vdd_mV = (1200 * 4096) / adc_value;
-        if (vdd_mV < lowest_vdd_seen)
-        {
-            logmsg("WARNING: Detected supply voltage drop to ", vdd_mV, "mV. Verify power supply is adequate.");
-            lowest_vdd_seen = vdd_mV - 50; // Small hysteresis to avoid excessive warnings
-        }
-    }
-#endif
-}
-
-/*****************************************/
-/* Debug logging and watchdog            */
-/*****************************************/
-
-// Send log data to USB UART if USB is connected.
-// Data is retrieved from the shared log ring buffer and
-// this function sends as much as fits in USB CDC buffer.
-
-static void usb_log_poll()
-{
-    static uint32_t logpos = 0;
-
-    if (usb_serial_ready())
-    {
-        // Retrieve pointer to log start and determine number of bytes available.
-        uint32_t available = 0;
-        const char *data = log_get_buffer(&logpos, &available);
-        // Limit to CDC packet size
-        uint32_t len = available;
-        if (len == 0) return;
-        if (len > USB_CDC_DATA_PACKET_SIZE) len = USB_CDC_DATA_PACKET_SIZE;
-
-        // Update log position by the actual number of bytes sent
-        // If USB CDC buffer is full, this may be 0
-        usb_serial_send((uint8_t*)data, len);
-        logpos -= available - len;
-    }
-}
-
-/*****************************************/
-/* Crash handlers                        */
-/*****************************************/
-// Writes log data to the PB3 SWO pin
-void platform_log(const char *s)
-{
-    while (*s)
-    {
-        // Write to SWO pin
-        while (ITM->PORT[0].u32 == 0);
-        ITM->PORT[0].u8 = *s++;
-    }
-}
-
-void platform_emergency_log_save()
-{
-    if (g_rawdrive_active)
-        return;
-#ifdef ZULUSCSI_HARDWARE_CONFIG
-    if (g_hw_config.is_active())
-        return;
-#endif
-    platform_set_sd_callback(NULL, NULL);
-
-    SD.begin(SD_CONFIG_CRASH);
-    FsFile crashfile = SD.open(CRASHFILE, O_WRONLY | O_CREAT | O_TRUNC);
-
-    if (!crashfile.isOpen())
-    {
-        // Try to reinitialize
-        int max_retry = 10;
-        while (max_retry-- > 0 && !SD.begin(SD_CONFIG_CRASH));
-
-        crashfile = SD.open(CRASHFILE, O_WRONLY | O_CREAT | O_TRUNC);
-    }
-
-    uint32_t startpos = 0;
-    crashfile.write(log_get_buffer(&startpos));
-    crashfile.write(log_get_buffer(&startpos));
-    crashfile.flush();
-    crashfile.close();
-}
-
-extern uint32_t _estack;
-
-__attribute__((noinline))
-void show_hardfault(uint32_t *sp)
-{
-    uint32_t pc = sp[6];
-    uint32_t lr = sp[5];
-    uint32_t cfsr = SCB->CFSR;
-    
-    logmsg("--------------");
-    logmsg("CRASH!");
-    logmsg("Platform: ", g_platform_name);
-    logmsg("FW Version: ", g_log_firmwareversion);
-    logmsg("scsiDev.cdb: ", bytearray(scsiDev.cdb, 12));
-    logmsg("scsiDev.phase: ", (int)scsiDev.phase);
-    logmsg("CFSR: ", cfsr);
-    logmsg("SP: ", (uint32_t)sp);
-    logmsg("PC: ", pc);
-    logmsg("LR: ", lr);
-    logmsg("R0: ", sp[0]);
-    logmsg("R1: ", sp[1]);
-    logmsg("R2: ", sp[2]);
-    logmsg("R3: ", sp[3]);
-
-    uint32_t *p = (uint32_t*)((uint32_t)sp & ~3);
-    for (int i = 0; i < 8; i++)
-    {
-        if (p == &_estack) break; // End of stack
-        
-        logmsg("STACK ", (uint32_t)p, ":    ", p[0], " ", p[1], " ", p[2], " ", p[3]);
-        p += 4;
-    }
- 
-    platform_emergency_log_save();
-
-    while (1)
-    {
-        if (g_usb_log_poll_func) g_usb_log_poll_func();
-        // Flash the crash address on the LED
-        // Short pulse means 0, long pulse means 1
-        int base_delay = 1000;
-        for (int i = 31; i >= 0; i--)
-        {
-            LED_OFF();
-            for (int j = 0; j < base_delay; j++) delay_ns(100000);
-            
-            int delay = (pc & (1 << i)) ? (3 * base_delay) : base_delay;
-            LED_ON();
-            for (int j = 0; j < delay; j++) delay_ns(100000);
-            LED_OFF();
-        }
-
-        for (int j = 0; j < base_delay * 10; j++) delay_ns(100000);
-    }
-}
-
-__attribute__((naked, interrupt))
-void HardFault_Handler(void)
-{
-    // Copies stack pointer into first argument
-    asm("mrs r0, msp\n"
-        "b show_hardfault": : : "r0");
-}
-
-__attribute__((naked, interrupt))
-void MemManage_Handler(void)
-{
-    asm("mrs r0, msp\n"
-        "b show_hardfault": : : "r0");
-}
-
-__attribute__((naked, interrupt))
-void BusFault_Handler(void)
-{
-    asm("mrs r0, msp\n"
-        "b show_hardfault": : : "r0");
-}
-
-__attribute__((naked, interrupt))
-void UsageFault_Handler(void)
-{
-    asm("mrs r0, msp\n"
-        "b show_hardfault": : : "r0");
-}
-
-void __assert_func(const char *file, int line, const char *func, const char *expr)
-{
-    uint32_t dummy = 0;
-
-    logmsg("--------------");
-    logmsg("ASSERT FAILED!");
-    logmsg("Platform: ", g_platform_name);
-    logmsg("FW Version: ", g_log_firmwareversion);
-    logmsg("scsiDev.cdb: ", bytearray(scsiDev.cdb, 12));
-    logmsg("scsiDev.phase: ", (int)scsiDev.phase);
-    logmsg("Assert failed: ", file , ":", line, " in ", func, ":", expr);
-
-    uint32_t *p = (uint32_t*)((uint32_t)&dummy & ~3);
-    for (int i = 0; i < 8; i++)
-    {
-        if (p == &_estack) break; // End of stack
-
-        logmsg("STACK ", (uint32_t)p, ":    ", p[0], " ", p[1], " ", p[2], " ", p[3]);
-        p += 4;
-    }
-
-    platform_emergency_log_save();
-
-    while(1)
-    {
-        if (g_usb_log_poll_func) g_usb_log_poll_func();
-        LED_OFF();
-        for (int j = 0; j < 1000; j++) delay_ns(100000);
-        LED_ON();
-        for (int j = 0; j < 1000; j++) delay_ns(100000);
-    }
-}
-
-} /* extern "C" */
-
-static void watchdog_handler(uint32_t *sp)
-{
-    logmsg("-------------- WATCHDOG TIMEOUT");
-    show_hardfault(sp);
-}
-
-void platform_reset_watchdog()
-{
-    // This uses a software watchdog based on systick timer interrupt.
-    // It gives us opportunity to collect better debug info than the
-    // full hardware reset that would be caused by hardware watchdog.
-    g_watchdog_timeout = WATCHDOG_CRASH_TIMEOUT;
-
-    // USB log is polled here also to make sure any log messages in fault states
-    // get passed to USB.
-    usb_log_poll();
-}
-
-void platform_reset_mcu()
-{
-    // reset in 2 sec ( 1 / (40KHz / 32) * 2500 == 2sec)
-    fwdgt_config(2500, FWDGT_PSC_DIV32);
-    fwdgt_enable();
-
-}
-
-// Poll function that is called every few milliseconds.
-// Can be left empty or used for platform-specific processing.
-void platform_poll()
-{
-#ifdef ENABLE_AUDIO_OUTPUT
-    audio_poll();
-#endif
-    adc_poll();
-    usb_log_poll();
-}
-
-uint8_t platform_get_buttons()
-{
-    // Buttons are active low: internal pull-up is enabled,
-    // and when button is pressed the pin goes low.
-    uint8_t buttons = 0;
-#ifdef PLATFORM_VERSION_1_1_PLUS
-    if (g_zuluscsi_version == ZSVersion_v1_1_ODE || g_zuluscsi_version == ZSVersion_v1_2)
-    {
-        if (!gpio_input_bit_get(EJECT_BTN_PORT, EJECT_BTN_PIN))   buttons |= 1;
-        if (!gpio_input_bit_get(USER_BTN_PORT, USER_BTN_PIN))   buttons |= 4;
-    }
-    else
-    {
-        if (!gpio_input_bit_get(EJECT_1_PORT, EJECT_1_PIN))   buttons |= 1;
-        if (!gpio_input_bit_get(EJECT_2_PORT, EJECT_2_PIN))   buttons |= 2;
-    }
-#else
-    if (!gpio_input_bit_get(EJECT_1_PORT, EJECT_1_PIN))   buttons |= 1;
-    if (!gpio_input_bit_get(EJECT_2_PORT, EJECT_2_PIN))   buttons |= 2;
-#endif
-    // Simple debouncing logic: handle button releases after 100 ms delay.
-    static uint32_t debounce;
-    static uint8_t buttons_debounced = 0;
-
-    if (buttons != 0)
-    {
-        buttons_debounced = buttons;
-        debounce = millis();
-    }
-    else if ((uint32_t)(millis() - debounce) > 100)
-    {
-        buttons_debounced = 0;
-    }
-
-#ifdef PLATFORM_VERSION_1_1_PLUS
-    if(g_zuluscsi_version == ZSVersion_v1_1_ODE || g_zuluscsi_version == ZSVersion_v1_2)
-    {
-        static uint8_t previous = 0x00;
-        uint8_t bitmask = buttons_debounced & USER_BTN_MASK;
-        uint8_t ejectors = (previous ^ bitmask) & previous;
-        previous = bitmask;
-        if (ejectors & USER_BTN_MASK)
-        {
-            logmsg("User button pressed - feature not yet implemented");
-        }
-    }
-#endif
-
-    return buttons_debounced;
-}
-
-bool platform_has_phy_eject_button()
-{
-    return g_zuluscsi_version == ZSVersion_v1_1_ODE || g_zuluscsi_version == ZSVersion_v1_2;
-}
-
-/***********************/
-/* Flash reprogramming */
-/***********************/
-
-bool platform_rewrite_flash_page(uint32_t offset, uint8_t buffer[PLATFORM_FLASH_PAGE_SIZE])
-{
-    if (offset == 0)
-    {
-        if (buffer[3] != 0x20 || buffer[7] != 0x08)
-        {
-            logmsg("Invalid firmware file, starts with: ", bytearray(buffer, 16));
-            return false;
-        }
-    }
-
-    dbgmsg("Writing flash at offset ", offset, " data ", bytearray(buffer, 4));
-    assert(offset % PLATFORM_FLASH_PAGE_SIZE == 0);
-    assert(offset >= PLATFORM_BOOTLOADER_SIZE);
-    
-    fmc_unlock();
-    fmc_bank0_unlock();
-
-    fmc_state_enum status;
-    status = fmc_page_erase(FLASH_BASE + offset);
-    if (status != FMC_READY)
-    {
-        logmsg("Erase failed: ", (int)status);
-        return false;
-    }
-
-    uint32_t *buf32 = (uint32_t*)buffer;
-    uint32_t num_words = PLATFORM_FLASH_PAGE_SIZE / 4;
-    for (int i = 0; i < num_words; i++)
-    {
-        status = fmc_word_program(FLASH_BASE + offset + i * 4, buf32[i]);
-        if (status != FMC_READY)
-        {
-            logmsg("Flash write failed: ", (int)status);
-            return false;
-        }   
-    }
-
-    fmc_lock();
-
-    for (int i = 0; i < num_words; i++)
-    {
-        uint32_t expected = buf32[i];
-        uint32_t actual = *(volatile uint32_t*)(FLASH_BASE + offset + i * 4);
-        if (actual != expected)
-        {
-            logmsg("Flash verify failed at offset ", offset + i * 4, " got ", actual, " expected ", expected);
-            return false;
-        }
-    }
-    return true;
-}
-
-void platform_boot_to_main_firmware()
-{
-    uint32_t *mainprogram_start = (uint32_t*)(0x08000000 + PLATFORM_BOOTLOADER_SIZE);
-    SCB->VTOR = (uint32_t)mainprogram_start;
-  
-    __asm__(
-        "msr msp, %0\n\t"
-        "bx %1" : : "r" (mainprogram_start[0]),
-                    "r" (mainprogram_start[1]) : "memory");
-}
-
-/**************************************/
-/* SCSI configuration based on DIPSW1 */
-/**************************************/
-
-void platform_config_hook(S2S_TargetCfg *config)
-{
-    // Enable Apple quirks by dip switch
-    if (g_enable_apple_quirks)
-    {
-        if (config->quirks == S2S_CFG_QUIRKS_NONE)
-        {
-            config->quirks = S2S_CFG_QUIRKS_APPLE;
-        }
-    }
-}
-
-/**********************************************/
-/* Mapping from data bytes to GPIO BOP values */
-/**********************************************/
-
-#define PARITY(n) ((1 ^ (n) ^ ((n)>>1) ^ ((n)>>2) ^ ((n)>>3) ^ ((n)>>4) ^ ((n)>>5) ^ ((n)>>6) ^ ((n)>>7)) & 1)
-#define X(n) (\
-    ((n & 0x01) ? (SCSI_OUT_DB0 << 16) : SCSI_OUT_DB0) | \
-    ((n & 0x02) ? (SCSI_OUT_DB1 << 16) : SCSI_OUT_DB1) | \
-    ((n & 0x04) ? (SCSI_OUT_DB2 << 16) : SCSI_OUT_DB2) | \
-    ((n & 0x08) ? (SCSI_OUT_DB3 << 16) : SCSI_OUT_DB3) | \
-    ((n & 0x10) ? (SCSI_OUT_DB4 << 16) : SCSI_OUT_DB4) | \
-    ((n & 0x20) ? (SCSI_OUT_DB5 << 16) : SCSI_OUT_DB5) | \
-    ((n & 0x40) ? (SCSI_OUT_DB6 << 16) : SCSI_OUT_DB6) | \
-    ((n & 0x80) ? (SCSI_OUT_DB7 << 16) : SCSI_OUT_DB7) | \
-    (PARITY(n)  ? (SCSI_OUT_DBP << 16) : SCSI_OUT_DBP) | \
-    (SCSI_OUT_REQ) \
-)
-    
-const uint32_t g_scsi_out_byte_to_bop[256] =
-{
-    X(0x00), X(0x01), X(0x02), X(0x03), X(0x04), X(0x05), X(0x06), X(0x07), X(0x08), X(0x09), X(0x0a), X(0x0b), X(0x0c), X(0x0d), X(0x0e), X(0x0f),
-    X(0x10), X(0x11), X(0x12), X(0x13), X(0x14), X(0x15), X(0x16), X(0x17), X(0x18), X(0x19), X(0x1a), X(0x1b), X(0x1c), X(0x1d), X(0x1e), X(0x1f),
-    X(0x20), X(0x21), X(0x22), X(0x23), X(0x24), X(0x25), X(0x26), X(0x27), X(0x28), X(0x29), X(0x2a), X(0x2b), X(0x2c), X(0x2d), X(0x2e), X(0x2f),
-    X(0x30), X(0x31), X(0x32), X(0x33), X(0x34), X(0x35), X(0x36), X(0x37), X(0x38), X(0x39), X(0x3a), X(0x3b), X(0x3c), X(0x3d), X(0x3e), X(0x3f),
-    X(0x40), X(0x41), X(0x42), X(0x43), X(0x44), X(0x45), X(0x46), X(0x47), X(0x48), X(0x49), X(0x4a), X(0x4b), X(0x4c), X(0x4d), X(0x4e), X(0x4f),
-    X(0x50), X(0x51), X(0x52), X(0x53), X(0x54), X(0x55), X(0x56), X(0x57), X(0x58), X(0x59), X(0x5a), X(0x5b), X(0x5c), X(0x5d), X(0x5e), X(0x5f),
-    X(0x60), X(0x61), X(0x62), X(0x63), X(0x64), X(0x65), X(0x66), X(0x67), X(0x68), X(0x69), X(0x6a), X(0x6b), X(0x6c), X(0x6d), X(0x6e), X(0x6f),
-    X(0x70), X(0x71), X(0x72), X(0x73), X(0x74), X(0x75), X(0x76), X(0x77), X(0x78), X(0x79), X(0x7a), X(0x7b), X(0x7c), X(0x7d), X(0x7e), X(0x7f),
-    X(0x80), X(0x81), X(0x82), X(0x83), X(0x84), X(0x85), X(0x86), X(0x87), X(0x88), X(0x89), X(0x8a), X(0x8b), X(0x8c), X(0x8d), X(0x8e), X(0x8f),
-    X(0x90), X(0x91), X(0x92), X(0x93), X(0x94), X(0x95), X(0x96), X(0x97), X(0x98), X(0x99), X(0x9a), X(0x9b), X(0x9c), X(0x9d), X(0x9e), X(0x9f),
-    X(0xa0), X(0xa1), X(0xa2), X(0xa3), X(0xa4), X(0xa5), X(0xa6), X(0xa7), X(0xa8), X(0xa9), X(0xaa), X(0xab), X(0xac), X(0xad), X(0xae), X(0xaf),
-    X(0xb0), X(0xb1), X(0xb2), X(0xb3), X(0xb4), X(0xb5), X(0xb6), X(0xb7), X(0xb8), X(0xb9), X(0xba), X(0xbb), X(0xbc), X(0xbd), X(0xbe), X(0xbf),
-    X(0xc0), X(0xc1), X(0xc2), X(0xc3), X(0xc4), X(0xc5), X(0xc6), X(0xc7), X(0xc8), X(0xc9), X(0xca), X(0xcb), X(0xcc), X(0xcd), X(0xce), X(0xcf),
-    X(0xd0), X(0xd1), X(0xd2), X(0xd3), X(0xd4), X(0xd5), X(0xd6), X(0xd7), X(0xd8), X(0xd9), X(0xda), X(0xdb), X(0xdc), X(0xdd), X(0xde), X(0xdf),
-    X(0xe0), X(0xe1), X(0xe2), X(0xe3), X(0xe4), X(0xe5), X(0xe6), X(0xe7), X(0xe8), X(0xe9), X(0xea), X(0xeb), X(0xec), X(0xed), X(0xee), X(0xef),
-    X(0xf0), X(0xf1), X(0xf2), X(0xf3), X(0xf4), X(0xf5), X(0xf6), X(0xf7), X(0xf8), X(0xf9), X(0xfa), X(0xfb), X(0xfc), X(0xfd), X(0xfe), X(0xff)
-};
-
-#undef X

+ 0 - 219
lib/ZuluSCSI_platform_GD32F205/ZuluSCSI_platform.h

@@ -1,219 +0,0 @@
-/** 
- * ZuluSCSI™ - Copyright (c) 2022-2025 Rabbit Hole Computing™
- * 
- * ZuluSCSI™ firmware is licensed under the GPL version 3 or any later version. 
- * 
- * https://www.gnu.org/licenses/gpl-3.0.html
- * ----
- * 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 <https://www.gnu.org/licenses/>.
-**/
-
-// Platform-specific definitions for ZuluSCSI.
-// Can be customized for different microcontrollers, this file is for GD32F205VCT6.
-
-#pragma once
-
-#include <gd32f20x.h>
-#include <gd32f20x_gpio.h>
-#include <scsi2sd.h>
-#include <ZuluSCSI_config.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-extern const char *g_platform_name;
-
-#include "platform_hw_config.h"
-
-enum ZuluSCSIVersion_t
-{
-    ZSVersion_unknown,
-    ZSVersion_v1_1,
-    ZSVersion_v1_1_ODE,
-    ZSVersion_v1_2
-
-};
-
-extern enum ZuluSCSIVersion_t g_zuluscsi_version;
-extern bool g_moved_select_in;
-
-// Debug logging functions
-void platform_log(const char *s);
-
-// Minimal millis() implementation as GD32F205 does not
-// have an Arduino core yet.
-unsigned long millis(void);
-void delay(unsigned long ms);
-
-// Precise nanosecond delays
-// Works in interrupt context also, max delay 500 000 ns, min delay about 500 ns
-void delay_ns(unsigned long ns);
-
-static inline void delay_us(unsigned long us)
-{
-    if (us > 0)
-    {
-        delay_ns(us * 1000);
-    }
-}
-
-// Approximate fast delay
-static inline void delay_100ns()
-{
-    asm volatile ("nop \n nop \n nop \n nop \n nop");
-}
-
-// Initialize SPI and GPIO configuration
-void platform_init();
-
-// Initialization for main application, not used for bootloader
-void platform_late_init();
-
-// Initialization after the SD Card has been found
-void platform_post_sd_card_init();
-
-// Set the status LED only if it is not in a blinking routine
-void platform_write_led(bool state);
-#define LED_ON()  platform_write_led(true)
-#define LED_OFF() platform_write_led(false)
-// Used by the blinking routine
-void platform_set_blink_status(bool status);
-// LED override will set the status LED regardless of the blinking routine
-void platform_write_led_override(bool state);
-#define LED_ON_OVERRIDE()  platform_write_led_override(true)
-#define LED_OFF_OVERRIDE()  platform_write_led_override(false)
-
-// Disable the status LED
-void platform_disable_led(void);
-
-// Specific error code tied to the MCU when the SD card is not detected
-uint8_t platform_no_sd_card_on_init_error_code();
-
-// Setup soft watchdog
-void platform_reset_watchdog();
-
-// Reset MCU after a certain amount of time
-void platform_reset_mcu();
-
-// Poll function that is called every few milliseconds.
-// The SD card is free to access during this time, and pauses up to
-// few milliseconds shouldn't disturb SCSI communication.
-void platform_poll();
-
-// Returns the state of any platform-specific buttons.
-// The returned value should be a mask for buttons 1-8 in bits 0-7 respectively,
-// where '1' is a button pressed and '0' is a button released.
-// Debouncing logic is left up to the specific implementation.
-// This function should return without significantly delay.
-uint8_t platform_get_buttons();
-
-// Return system clock in Hz
-uint32_t platform_sys_clock_in_hz();
-
-// Return whether device supports reclocking the MCU
-inline bool platform_reclock_supported(){return false;}
-
-// Returns true if reboot was for mass storage - unsupported
-inline bool platform_rebooted_into_mass_storage() {return false;}
-
-// Reinitialize SD card connection and save log from interrupt context.
-// This can be used in crash handlers.
-void platform_emergency_log_save();
-
-// Set callback that will be called during data transfer to/from SD card.
-// This can be used to implement simultaneous transfer to SCSI bus.
-typedef void (*sd_callback_t)(uint32_t bytes_complete);
-void platform_set_sd_callback(sd_callback_t func, const uint8_t *buffer);
-
-// This function is called by scsiPhy.cpp.
-// It resets the systick counter to give 1 millisecond of uninterrupted transfer time.
-// The total number of skips is kept track of to keep the correct time on average.
-void SysTick_Handle_PreEmptively();
-
-// Reprogram firmware in main program area.
-#define PLATFORM_BOOTLOADER_SIZE 32768
-#define PLATFORM_FLASH_TOTAL_SIZE (256 * 1024)
-#define PLATFORM_FLASH_PAGE_SIZE 2048
-bool platform_rewrite_flash_page(uint32_t offset, uint8_t buffer[PLATFORM_FLASH_PAGE_SIZE]);
-void platform_boot_to_main_firmware();
-
-// True if the board has a physical eject button
-bool platform_has_phy_eject_button();
-
-// Configuration customizations based on DIP switch settings
-// When DIPSW1 is on, Apple quirks are enabled by default.
-void platform_config_hook(S2S_TargetCfg *config);
-#define PLATFORM_CONFIG_HOOK(cfg) platform_config_hook(cfg)
-
-// Write a single SCSI pin.
-// Example use: SCSI_OUT(ATN, 1) sets SCSI_ATN to low (active) state.
-#define SCSI_OUT(pin, state) \
-    GPIO_BOP(SCSI_OUT_ ## pin ## _PORT) = (SCSI_OUT_ ## pin ## _PIN) << (state ? 16 : 0)
-
-// Read a single SCSI pin.
-// Example use: SCSI_IN(ATN), returns 1 for active low state.
-#define SCSI_IN(pin) \
-    ((GPIO_ISTAT(SCSI_ ## pin ## _PORT) & (SCSI_ ## pin ## _PIN)) ? 0 : 1)
-
-// Write SCSI data bus, also sets REQ to inactive.
-extern const uint32_t g_scsi_out_byte_to_bop[256];
-#define SCSI_OUT_DATA(data) \
-    GPIO_BOP(SCSI_OUT_PORT) = g_scsi_out_byte_to_bop[(uint8_t)(data)]
-
-// Release SCSI data bus and REQ signal
-#define SCSI_RELEASE_DATA_REQ() \
-    GPIO_BOP(SCSI_OUT_PORT) = SCSI_OUT_DATA_MASK | SCSI_OUT_REQ
-
-// Release all SCSI outputs
-#define SCSI_RELEASE_OUTPUTS() \
-    GPIO_BOP(SCSI_OUT_PORT) = SCSI_OUT_DATA_MASK | SCSI_OUT_REQ, \
-    GPIO_BOP(SCSI_OUT_IO_PORT)  = SCSI_OUT_IO_PIN, \
-    GPIO_BOP(SCSI_OUT_CD_PORT)  = SCSI_OUT_CD_PIN, \
-    GPIO_BOP(SCSI_OUT_SEL_PORT) = SCSI_OUT_SEL_PIN, \
-    GPIO_BOP(SCSI_OUT_MSG_PORT) = SCSI_OUT_MSG_PIN, \
-    GPIO_BOP(SCSI_OUT_RST_PORT) = SCSI_OUT_RST_PIN, \
-    GPIO_BOP(SCSI_OUT_BSY_PORT) = SCSI_OUT_BSY_PIN
-
-// Read SCSI data bus
-#define SCSI_IN_DATA(data) \
-    (((~GPIO_ISTAT(SCSI_IN_PORT)) & SCSI_IN_MASK) >> SCSI_IN_SHIFT)
-
-#ifdef __cplusplus
-}
-
-// SD card driver for SdFat
-#ifndef SD_USE_SDIO
-// SPI interface, ZuluSCSI v1.0
-class SdSpiConfig;
-extern SdSpiConfig g_sd_spi_config;
-#define SD_CONFIG g_sd_spi_config
-#define SD_CONFIG_CRASH g_sd_spi_config
-
-#else
-// SDIO interface, ZuluSCSI v1.1
-class SdioConfig;
-extern SdioConfig g_sd_sdio_config;
-extern SdioConfig g_sd_sdio_config_crash;
-#define SD_CONFIG g_sd_sdio_config
-#define SD_CONFIG_CRASH g_sd_sdio_config_crash
-
-#endif
-
-// Check if a DMA request for SD card read has completed.
-// This is used to optimize the timing of data transfers on SCSI bus.
-// When called outside of SD callback processing, always returns false.
-bool check_sd_read_done();
-
-#endif

+ 0 - 47
lib/ZuluSCSI_platform_GD32F205/ZuluSCSI_platform_config.h

@@ -1,47 +0,0 @@
-/** 
- * ZuluSCSI™ - Copyright (c) 2024-2025 Rabbit Hole Computing™
- * 
- * ZuluSCSI™ firmware is licensed under the GPL version 3 or any later version. 
- * 
- * https://www.gnu.org/licenses/gpl-3.0.html
- * ----
- * 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 <https://www.gnu.org/licenses/>.
-**/
-#pragma once
-#if defined(ZULUSCSI_V1_0)
-#   if defined(ZULUSCSI_V1_0_mini)
-#       define PLATFORM_NAME "ZuluSCSI mini v1.0"
-#   else
-#       define PLATFORM_NAME "ZuluSCSI v1.0"
-#   endif
-#   define PLATFORM_REVISION "1.0"
-#   define PLATFORM_MAX_SCSI_SPEED S2S_CFG_SPEED_ASYNC_50
-#   include "ZuluSCSI_v1_0_gpio.h"
-#else
-#   define PLATFORM_NAME "ZuluSCSI v1.1+"
-#   define PLATFORM_REVISION "1.1+"
-#   define PLATFORM_MAX_SCSI_SPEED S2S_CFG_SPEED_SYNC_10
-#   define PLATFORM_OPTIMAL_MIN_SD_WRITE_SIZE 4096
-#   define PLATFORM_OPTIMAL_MAX_SD_WRITE_SIZE 65536
-#   define PLATFORM_OPTIMAL_LAST_SD_WRITE_SIZE 8192
-#   define PLATFORM_VERSION_1_1_PLUS
-#   define ZULUSCSI_HARDWARE_CONFIG
-#   include "ZuluSCSI_v1_1_gpio.h"
-#endif
-
-#ifndef PLATFORM_VDD_WARNING_LIMIT_mV
-#define PLATFORM_VDD_WARNING_LIMIT_mV 2800
-#endif
-
-#define PLATFORM_DEFAULT_SCSI_SPEED_SETTING 10

+ 0 - 256
lib/ZuluSCSI_platform_GD32F205/ZuluSCSI_platform_msc.cpp

@@ -1,256 +0,0 @@
-/**
- * Copyright (c) 2023-2024 zigzagjoe
- * 
- * ZuluSCSI™ firmware is licensed under the GPL version 3 or any later version. 
- * 
- * https://www.gnu.org/licenses/gpl-3.0.html
- * ----
- * 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 <https://www.gnu.org/licenses/>.
-**/
-
-#ifdef PLATFORM_MASS_STORAGE
-
-#include <SdFat.h>
-#include "ZuluSCSI_platform.h"
-#include "ZuluSCSI_log.h"
-#include "ZuluSCSI_msc.h"
-#include "ZuluSCSI_config.h"
-#include "ZuluSCSI_settings.h"
-#include "usb_serial.h"
-
-/* gd32 USB code is all C linked */
-extern "C" {
-  #include <drv_usb_hw.h>
-  #include <usbd_core.h>
-  #include <drv_usbd_int.h>
-
-  #include "usb_conf.h"
-  #include "usbd_msc_core.h"
-  #include "usbd_msc_mem.h"
-  #include "usbd_msc_bbb.h"
-}
-
-
-/* local function prototypes ('static') */
-static int8_t storageInit(uint8_t Lun);
-static int8_t storageIsReady(uint8_t Lun);
-static int8_t storageIsWriteProtected(uint8_t Lun);
-static int8_t storageGetMaxLun(void);
-static int8_t storageRead(uint8_t Lun,
-                           uint8_t *buf,
-                           uint32_t BlkAddr,
-                           uint16_t BlkLen);
-static int8_t storageWrite(uint8_t Lun,
-                            uint8_t *buf,
-                            uint32_t BlkAddr,
-                            uint16_t BlkLen);
-
-usbd_mem_cb USBD_SD_fops = {
-    .mem_init      = storageInit,
-    .mem_ready     = storageIsReady,
-    .mem_protected = storageIsWriteProtected,
-    .mem_read      = storageRead,
-    .mem_write     = storageWrite,
-    .mem_maxlun    = storageGetMaxLun,
-
-    .mem_inquiry_data = {(uint8_t *)storageInquiryData},
-    .mem_block_size   = {SD_SECTOR_SIZE},
-    .mem_block_len    = {0}
-};
-
-usbd_mem_cb *usbd_mem_fops = &USBD_SD_fops;
-
-// shared with usb serial
-extern usb_core_driver cdc_acm;
-
-// external global SD variable
-extern SdFs SD;
-
-// private globals
-static bool unitReady = false;
-
-/* returns true if card reader mode should be entered. sd card is available. */
-bool platform_sense_msc() {
-
-  // kill usb serial.
-  usbd_disconnect (&cdc_acm);
-  // set the MSC storage size
-  usbd_mem_fops->mem_block_len[0] = SD.card()->sectorCount();
-  unitReady = true;
-  
-  // init the MSC class, uses ISR and other global routines from usb_serial.cpp
-  usbd_init(&cdc_acm, USB_CORE_ENUM_FS, &msc_desc, &msc_class);
-
-  logmsg("Waiting for USB enumeration to expose SD card as a mass storage device");
-
-  // wait to be begin to be enumerated
-  uint32_t start = millis();
-  uint16_t usb_timeout =  g_scsi_settings.getSystem()->usbMassStorageWaitPeriod;
-  while ((uint32_t)(millis() - start) < usb_timeout)
-  {
-    if (cdc_acm.dev.cur_status >= USBD_ADDRESSED)
-    {
-      dbgmsg("USB enumeration took ", (int)((uint32_t)(millis() - start)), "ms");
-      return true;
-    }
-  }
-
-  logmsg("Waiting for USB enumeration timed out after ", usb_timeout, "ms.");
-  logmsg("-- Try increasing 'USBMassStorageWaitPeriod' in the ", CONFIGFILE);
-  //if not, disconnect MSC class...
-  usbd_disconnect (&cdc_acm);
-
-  // and bring serial back for later.
-  usb_serial_init();
-
-  return false;
-}
-
-void platform_set_msc_image_mode(bool image_mode) {
-  if (image_mode) logmsg("Warning: USB Image mounting not supported on this platform!");
-  //g_MSC.SDMode = !image_mode;
-}
-
-/* perform MSC-specific init tasks */
-void platform_enter_msc() {
-  dbgmsg("USB MSC buffer size: ", (uint32_t) MSC_MEDIA_PACKET_SIZE);
-
-  // give the host a moment to finish enumerate and "load" media
-  uint32_t start = millis();
-  uint16_t usb_timeout =  g_scsi_settings.getSystem()->usbMassStorageWaitPeriod;
-  while ((USBD_CONFIGURED != cdc_acm.dev.cur_status) && ((uint32_t)(millis() - start) < usb_timeout ) ) 
-    delay(100);
-}
-
-/* return true while remaining in msc mode, and perform periodic tasks */
-bool platform_run_msc() {
-  usbd_msc_handler *msc = (usbd_msc_handler *)cdc_acm.dev.class_data[USBD_MSC_INTERFACE];
-
-  // stupid windows doesn't send start_stop_unit events if it is ejected via safely remove devices. 
-  // it just stops talking to the device so we don't know we've been ejected....
-  // other OSes always send the start_stop_unit, windows does too when ejected from explorer.
-  // so we watch for the OS suspending device and assume we're done in USB mode if so.
-  // this will also trigger if the host were to suspend usb device due to going to sleep
-  // however, I hope no sane OS would sleep mid transfer or with a dirty filesystem. 
-  // Note: Mac OS X apparently not sane.
-  uint8_t is_suspended = cdc_acm.dev.cur_status == (uint8_t)USBD_SUSPENDED;
-
-  return (! msc->scsi_disk_pop) && !is_suspended;
-}
-
-void platform_exit_msc() {
-  unitReady = false;
-
-  // disconnect msc....
-  usbd_disconnect (&cdc_acm);
-
-  // catch our breath....
-  delay(200);
-  
-  // ... and bring usb serial up
-  usb_serial_init();
-}
-
-/*!
-    \brief      initialize the storage medium
-    \param[in]  Lun: logical unit number
-    \param[out] none
-    \retval     status
-*/
-static int8_t storageInit(uint8_t Lun)
-{
-    return 0;
-}
-
-/*!
-    \brief      check whether the medium is ready
-    \param[in]  Lun: logical unit number
-    \param[out] none
-    \retval     status
-*/
-static int8_t storageIsReady(uint8_t Lun)
-{
-    return ! unitReady; // 0 = success / unit is ready
-}
-
-/*!
-    \brief      check whether the medium is write-protected
-    \param[in]  Lun: logical unit number
-    \param[out] none
-    \retval     status
-*/
-static int8_t storageIsWriteProtected(uint8_t Lun)
-{
-    return ! unitReady; // 0 = read/write
-}
-
-/*!
-    \brief      read data from the medium
-    \param[in]  Lun: logical unit number
-    \param[in]  buf: pointer to the buffer to save data
-    \param[in]  BlkAddr: address of 1st block to be read
-    \param[in]  BlkLen: number of blocks to be read
-    \param[out] none
-    \retval     status
-*/
-static int8_t storageRead(uint8_t Lun,
-                           uint8_t *buf,
-                           uint32_t BlkAddr,
-                           uint16_t BlkLen)
-{
-    // divide by sector size to convert address to LBA
-    bool rc = SD.card()->readSectors(BlkAddr/SD_SECTOR_SIZE, buf, BlkLen);
-
-    // only blink fast on reads; writes will override this
-    if (MSC_LEDMode == LED_SOLIDON)
-      MSC_LEDMode = LED_BLINK_FAST;
-      
-    return !rc;
-}
-
-/*!
-    \brief      write data to the medium
-    \param[in]  Lun: logical unit number
-    \param[in]  buf: pointer to the buffer to write
-    \param[in]  BlkAddr: address of 1st block to be written
-    \param[in]  BlkLen: number of blocks to be write
-    \param[out] none
-    \retval     status
-*/
-static int8_t storageWrite(uint8_t Lun,
-                            uint8_t *buf,
-                            uint32_t BlkAddr,
-                            uint16_t BlkLen)
-{
-    // divide by sector size to convert address to LBA
-    bool rc = SD.card()->writeSectors(BlkAddr/SD_SECTOR_SIZE, buf, BlkLen);
-
-    // always slow blink
-    MSC_LEDMode = LED_BLINK_SLOW;
-
-    return !rc;
-}
-
-/*!
-    \brief      get number of supported logical unit
-    \param[in]  none
-    \param[out] none
-    \retval     number of logical unit
-*/
-static int8_t storageGetMaxLun(void)
-{
-    return 0; // number of LUNs supported - 1
-}
-
-#endif // PLATFORM_MASS_STORAGE

+ 0 - 62
lib/ZuluSCSI_platform_GD32F205/ZuluSCSI_platform_msc.h

@@ -1,62 +0,0 @@
-/**
- * Copyright (c) 2023-2024 zigzagjoe
- * 
- * ZuluSCSI™ firmware is licensed under the GPL version 3 or any later version. 
- * 
- * https://www.gnu.org/licenses/gpl-3.0.html
- * ----
- * 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 <https://www.gnu.org/licenses/>.
-**/
-
-#ifdef PLATFORM_MASS_STORAGE
-#pragma once
-
-#include "usbd_msc_mem.h"
-
-// private constants/enums
-#define SD_SECTOR_SIZE 512
-
-/* USB Mass storage Standard Inquiry Data */
-const uint8_t storageInquiryData[] = {
-    /* LUN 0 */
-    0x00,
-    0x80,
-    0x00,
-    0x01,
-    (USBD_STD_INQUIRY_LENGTH - 5U),
-    0x00,
-    0x00,
-    0x00,
-    'Z', 'u', 'l', 'u', 'S', 'C', 'S', 'I', /* Manufacturer : 8 bytes */
-    'G', 'D', '3', '2', 0, 0, 0, 0, /* Product      : 16 Bytes */
-    0, 0, 0, 0, 0, 0, 0, 0,
-    '1', '.', '0', '0',                     /* Version      : 4 Bytes */
-};
-
-/* return true if USB presence detected / eligble to enter CR mode */
-bool platform_sense_msc();
-
-/* perform MSC-specific init tasks */
-void platform_enter_msc();
-
-/* set to present images as storage rather than SD */
-void platform_set_msc_image_mode(bool image_mode);
-
-/* return true if we should remain in card reader mode. called in a loop. */
-bool platform_run_msc();
-
-/* perform any cleanup tasks for the MSC-specific functionality */
-void platform_exit_msc();
-
-#endif

+ 0 - 156
lib/ZuluSCSI_platform_GD32F205/ZuluSCSI_v1_0_gpio.h

@@ -1,156 +0,0 @@
-/** 
- * ZuluSCSI™ - Copyright (c) 2022-2025 Rabbit Hole Computing™
- * 
- * ZuluSCSI™ firmware is licensed under the GPL version 3 or any later version. 
- * 
- * https://www.gnu.org/licenses/gpl-3.0.html
- * ----
- * 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 <https://www.gnu.org/licenses/>.
-**/
-
-// GPIO definitions for ZuluSCSI v1.0
-
-#pragma once
-
-// SCSI data output port.
-// The output data is written using BSRR mechanism, so all data pins must be on same GPIO port.
-// The output pins are open-drain in hardware, using separate buffer chips for driving.
-#define SCSI_OUT_PORT GPIOD
-#define SCSI_OUT_DB7  GPIO_PIN_0
-#define SCSI_OUT_DB6  GPIO_PIN_1
-#define SCSI_OUT_DB5  GPIO_PIN_2
-#define SCSI_OUT_DB4  GPIO_PIN_3
-#define SCSI_OUT_DB3  GPIO_PIN_4
-#define SCSI_OUT_DB2  GPIO_PIN_5
-#define SCSI_OUT_DB1  GPIO_PIN_6
-#define SCSI_OUT_DB0  GPIO_PIN_7
-#define SCSI_OUT_DBP  GPIO_PIN_15
-#define SCSI_OUT_REQ  GPIO_PIN_9
-#define SCSI_OUT_DATA_MASK (SCSI_OUT_DB0 | SCSI_OUT_DB1 | SCSI_OUT_DB2 | SCSI_OUT_DB3 | SCSI_OUT_DB4 | SCSI_OUT_DB5 | SCSI_OUT_DB6 | SCSI_OUT_DB7 | SCSI_OUT_DBP)
-#define SCSI_OUT_REQ_IDX 9
-
-// SCSI input data port
-#define SCSI_IN_PORT  GPIOE
-#define SCSI_IN_DB7   GPIO_PIN_15
-#define SCSI_IN_DB6   GPIO_PIN_14
-#define SCSI_IN_DB5   GPIO_PIN_13
-#define SCSI_IN_DB4   GPIO_PIN_12
-#define SCSI_IN_DB3   GPIO_PIN_11
-#define SCSI_IN_DB2   GPIO_PIN_10
-#define SCSI_IN_DB1   GPIO_PIN_9
-#define SCSI_IN_DB0   GPIO_PIN_8
-#define SCSI_IN_DBP   GPIO_PIN_7
-#define SCSI_IN_MASK  (SCSI_IN_DB7|SCSI_IN_DB6|SCSI_IN_DB5|SCSI_IN_DB4|SCSI_IN_DB3|SCSI_IN_DB2|SCSI_IN_DB1|SCSI_IN_DB0|SCSI_IN_DBP)
-#define SCSI_IN_SHIFT 8
-
-// SCSI output status lines
-#define SCSI_OUT_IO_PORT  GPIOD
-#define SCSI_OUT_IO_PIN   GPIO_PIN_8
-#define SCSI_OUT_CD_PORT  GPIOD
-#define SCSI_OUT_CD_PIN   GPIO_PIN_10
-#define SCSI_OUT_SEL_PORT GPIOD
-#define SCSI_OUT_SEL_PIN  GPIO_PIN_11
-#define SCSI_OUT_MSG_PORT GPIOD
-#define SCSI_OUT_MSG_PIN  GPIO_PIN_12
-#define SCSI_OUT_RST_PORT GPIOD
-#define SCSI_OUT_RST_PIN  GPIO_PIN_13
-#define SCSI_OUT_BSY_PORT GPIOD
-#define SCSI_OUT_BSY_PIN  GPIO_PIN_14
-#define SCSI_OUT_REQ_PORT SCSI_OUT_PORT
-#define SCSI_OUT_REQ_PIN  SCSI_OUT_REQ
-
-// SCSI input status signals
-#define SCSI_ACK_PORT GPIOB
-#define SCSI_ACK_PIN  GPIO_PIN_12
-#define SCSI_IN_ACK_IDX 12
-
-// The SCSI_ATN pin was PB0 in prototype 2022a, but was moved to PC6 for 5V-tolerance
-#ifdef ZULUSCSI_2022A_REVISION
-#define SCSI_ATN_PORT GPIOB
-#define SCSI_ATN_PIN  GPIO_PIN_0
-#else
-#define SCSI_ATN_PORT GPIOC
-#define SCSI_ATN_PIN  GPIO_PIN_6
-#endif
-
-// SEL pin uses EXTI interrupt
-#define SCSI_SEL_PORT GPIOB
-#define SCSI_SEL_PIN  GPIO_PIN_11
-#define SCSI_SEL_EXTI EXTI_11
-#define SCSI_SEL_EXTI_SOURCE_PORT GPIO_PORT_SOURCE_GPIOB
-#define SCSI_SEL_EXTI_SOURCE_PIN GPIO_PIN_SOURCE_11
-#define SCSI_SEL_IRQ EXTI10_15_IRQHandler
-#define SCSI_SEL_IRQn EXTI10_15_IRQn
-
-// Unused place holders for compiling
-#define SCSI_ODE_SEL_PORT   SCSI_SEL_PORT
-#define SCSI_ODE_SEL_PIN    SCSI_SEL_PIN
-#define SCSI_ODE_SEL_EXTI   SCSI_SEL_EXTI
-#define SCSI_ODE_SEL_EXTI_SOURCE_PORT SCSI_SEL_EXTI_SOURCE_PORT
-#define SCSI_ODE_SEL_EXTI_SOURCE_PIN SCSI_SEL_EXTI_SOURCE_PIN
-#define SCSI_ODE_SEL_IRQ SCSI_SEL_IRQ
-#define SCSI_ODE_SEL_IRQn SCSI_SEL_IRQn
-
-
-// BSY pin uses EXTI interrupt
-#define SCSI_BSY_PORT GPIOB
-#define SCSI_BSY_PIN  GPIO_PIN_10
-#define SCSI_BSY_EXTI EXTI_10
-#define SCSI_BSY_EXTI_SOURCE_PORT GPIO_PORT_SOURCE_GPIOB
-#define SCSI_BSY_EXTI_SOURCE_PIN  GPIO_PIN_SOURCE_10
-#define SCSI_BSY_IRQ  EXTI10_15_IRQHandler
-#define SCSI_BSY_IRQn EXTI10_15_IRQn
-
-// RST pin uses EXTI interrupt
-#define SCSI_RST_PORT GPIOB
-#define SCSI_RST_PIN  GPIO_PIN_13
-#define SCSI_RST_EXTI EXTI_13
-#define SCSI_RST_EXTI_SOURCE_PORT GPIO_PORT_SOURCE_GPIOB
-#define SCSI_RST_EXTI_SOURCE_PIN GPIO_PIN_SOURCE_13
-#define SCSI_RST_IRQ  EXTI10_15_IRQHandler
-#define SCSI_RST_IRQn EXTI10_15_IRQn
-
-// Terminator enable/disable config, active low
-#define SCSI_TERM_EN_PORT GPIOC
-#define SCSI_TERM_EN_PIN  GPIO_PIN_8
-
-// SD card pins
-#define SD_PORT      GPIOA
-#define SD_CS_PIN    GPIO_PIN_4
-#define SD_CLK_PIN   GPIO_PIN_5
-#define SD_MISO_PIN  GPIO_PIN_6
-#define SD_MOSI_PIN  GPIO_PIN_7
-#define SD_SPI       SPI0
-#define SD_SPI_RX_DMA_CHANNEL DMA_CH1
-#define SD_SPI_TX_DMA_CHANNEL DMA_CH2
-
-// DIP switches
-#define DIP_PORT     GPIOB
-#define DIPSW1_PIN   GPIO_PIN_4
-#define DIPSW2_PIN   GPIO_PIN_5
-#define DIPSW3_PIN   GPIO_PIN_6
-
-// Status LED pins
-#define LED_PORT     GPIOC
-#define LED_I_PIN    GPIO_PIN_4
-#define LED_E_PIN    GPIO_PIN_5
-#define LED_PINS     (LED_I_PIN | LED_E_PIN)
-
-// Ejection buttons are available on expansion header J303.
-// PE5 = channel 1, PE6 = channel 2
-// Connect button between GPIO and GND pin.
-#define EJECT_1_PORT    GPIOE
-#define EJECT_1_PIN     GPIO_PIN_5
-#define EJECT_2_PORT    GPIOE
-#define EJECT_2_PIN     GPIO_PIN_6

+ 0 - 312
lib/ZuluSCSI_platform_GD32F205/ZuluSCSI_v1_1_gpio.h

@@ -1,312 +0,0 @@
-/** 
- * ZuluSCSI™ - Copyright (c) 2022-2025 Rabbit Hole Computing™
- * 
- * ZuluSCSI™ firmware is licensed under the GPL version 3 or any later version. 
- * 
- * https://www.gnu.org/licenses/gpl-3.0.html
- * ----
- * 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 <https://www.gnu.org/licenses/>.
-**/
-
-// GPIO definitions for ZuluSCSI v1.1
-
-#pragma once
-
-// SCSI data output port.
-// The output data is written using BSRR mechanism, so all data pins must be on same GPIO port.
-// The output pins are open-drain in hardware, using separate buffer chips for driving.
-#define SCSI_OUT_PORT GPIOD
-#define SCSI_OUT_DB7  GPIO_PIN_9
-#define SCSI_OUT_DB6  GPIO_PIN_10
-#define SCSI_OUT_DB5  GPIO_PIN_11
-#define SCSI_OUT_DB4  GPIO_PIN_12
-#define SCSI_OUT_DB3  GPIO_PIN_13
-#define SCSI_OUT_DB2  GPIO_PIN_14
-#define SCSI_OUT_DB1  GPIO_PIN_0
-#define SCSI_OUT_DB0  GPIO_PIN_1
-#define SCSI_OUT_DBP  GPIO_PIN_8
-#define SCSI_OUT_REQ  GPIO_PIN_4
-#define SCSI_OUT_DATA_MASK (SCSI_OUT_DB0 | SCSI_OUT_DB1 | SCSI_OUT_DB2 | SCSI_OUT_DB3 | SCSI_OUT_DB4 | SCSI_OUT_DB5 | SCSI_OUT_DB6 | SCSI_OUT_DB7 | SCSI_OUT_DBP)
-#define SCSI_OUT_REQ_IDX 4
-
-// Control signals to optional PLD device
-#define SCSI_OUT_PLD1 GPIO_PIN_15
-#define SCSI_OUT_PLD2 GPIO_PIN_3
-#define SCSI_OUT_PLD3 GPIO_PIN_5
-#define SCSI_OUT_PLD4 GPIO_PIN_7
-
-// Control signals for timer based DMA acceleration
-#define SCSI_TIMER TIMER7
-#define SCSI_TIMER_RCU RCU_TIMER7
-#define SCSI_TIMER_OUT_PORT GPIOB
-#define SCSI_TIMER_OUT_PIN GPIO_PIN_1
-#define SCSI_TIMER_IN_PORT GPIOC
-#define SCSI_TIMER_IN_PIN GPIO_PIN_6
-#define SCSI_TIMER_DMA DMA1
-#define SCSI_TIMER_DMA_RCU RCU_DMA1
-#define SCSI_TIMER_DMACHA DMA_CH4
-#define SCSI_TIMER_DMACHB DMA_CH1
-#define SCSI_TIMER_DMACHA_IRQ DMA1_Channel4_IRQHandler
-#define SCSI_TIMER_DMACHA_IRQn DMA1_Channel4_IRQn
-#define SCSI_TIMER_DMACHB_IRQ DMA1_Channel1_IRQHandler
-#define SCSI_TIMER_DMACHB_IRQn DMA1_Channel1_IRQn
-
-// GreenPAK logic chip pins
-#define GREENPAK_I2C_ADDR 0x10
-#define GREENPAK_I2C_PORT GPIOB
-#define GREENPAK_I2C_SCL GPIO_PIN_8
-#define GREENPAK_I2C_SDA GPIO_PIN_9
-#define GREENPAK_PLD_IO1 GPIO_PIN_15
-#define GREENPAK_PLD_IO2 GPIO_PIN_3
-#define GREENPAK_PLD_IO3 GPIO_PIN_5
-#define GREENPAK_PLD_IO4 GPIO_PIN_7
-#define GREENPAK_PLD_IO2_EXTI EXTI_3
-#define GREENPAK_PLD_IO2_EXTI_SOURCE_PORT GPIO_PORT_SOURCE_GPIOD
-#define GREENPAK_PLD_IO2_EXTI_SOURCE_PIN  GPIO_PIN_SOURCE_3
-#define GREENPAK_IRQ  EXTI3_IRQHandler
-#define GREENPAK_IRQn EXTI3_IRQn
-
-
-// I2C for ODE and v1.2
-#define ODE_I2C_PORT GPIOB
-#define ODE_I2C_SCL GPIO_PIN_6
-#define ODE_I2C_SDA GPIO_PIN_7
-
-
-// SCSI input data port
-#define SCSI_IN_PORT  GPIOE
-#define SCSI_IN_DB7   GPIO_PIN_15
-#define SCSI_IN_DB6   GPIO_PIN_14
-#define SCSI_IN_DB5   GPIO_PIN_13
-#define SCSI_IN_DB4   GPIO_PIN_12
-#define SCSI_IN_DB3   GPIO_PIN_11
-#define SCSI_IN_DB2   GPIO_PIN_10
-#define SCSI_IN_DB1   GPIO_PIN_9
-#define SCSI_IN_DB0   GPIO_PIN_8
-#define SCSI_IN_DBP   GPIO_PIN_7
-#define SCSI_IN_MASK  (SCSI_IN_DB7|SCSI_IN_DB6|SCSI_IN_DB5|SCSI_IN_DB4|SCSI_IN_DB3|SCSI_IN_DB2|SCSI_IN_DB1|SCSI_IN_DB0|SCSI_IN_DBP)
-#define SCSI_IN_SHIFT 8
-
-// SCSI output status lines
-#define SCSI_OUT_IO_PORT  GPIOA
-#define SCSI_OUT_IO_PIN   GPIO_PIN_4
-#define SCSI_OUT_CD_PORT  GPIOA
-#define SCSI_OUT_CD_PIN   GPIO_PIN_5
-#define SCSI_OUT_SEL_PORT GPIOA
-#define SCSI_OUT_SEL_PIN  GPIO_PIN_6
-#define SCSI_OUT_MSG_PORT GPIOA
-#define SCSI_OUT_MSG_PIN  GPIO_PIN_7
-#define SCSI_OUT_RST_PORT GPIOB
-#define SCSI_OUT_RST_PIN  GPIO_PIN_14
-#define SCSI_OUT_BSY_PORT GPIOB
-#define SCSI_OUT_BSY_PIN  GPIO_PIN_15
-#define SCSI_OUT_REQ_PORT SCSI_OUT_PORT
-#define SCSI_OUT_REQ_PIN  SCSI_OUT_REQ
-
-// SCSI input status signals
-#define SCSI_ACK_PORT GPIOA
-#define SCSI_ACK_PIN  GPIO_PIN_0
-#define SCSI_ATN_PORT GPIOB
-#define SCSI_ATN_PIN  GPIO_PIN_12
-#define SCSI_IN_ACK_IDX 0
-
-// Extra signals used with EXMC for synchronous mode
-#define SCSI_IN_ACK_EXMC_NWAIT_PORT GPIOD
-#define SCSI_IN_ACK_EXMC_NWAIT_PIN  GPIO_PIN_6
-#define SCSI_OUT_REQ_EXMC_NOE_PORT  GPIOD
-#define SCSI_OUT_REQ_EXMC_NOE_PIN   GPIO_PIN_4
-#define SCSI_OUT_REQ_EXMC_NOE_IDX   4
-#define SCSI_EXMC_DATA_SHIFT 5
-#define SCSI_EXMC_DMA DMA0
-#define SCSI_EXMC_DMA_RCU RCU_DMA0
-#define SCSI_EXMC_DMACH DMA_CH0
-#define SCSI_SYNC_TIMER TIMER1
-#define SCSI_SYNC_TIMER_RCU RCU_TIMER1
-
-// SEL pin uses EXTI interrupt
-#define SCSI_SEL_PORT GPIOB
-#define SCSI_SEL_PIN  GPIO_PIN_11
-#define SCSI_SEL_EXTI EXTI_11
-#define SCSI_SEL_EXTI_SOURCE_PORT GPIO_PORT_SOURCE_GPIOB
-#define SCSI_SEL_EXTI_SOURCE_PIN GPIO_PIN_SOURCE_11
-#define SCSI_SEL_IRQ EXTI10_15_IRQHandler
-#define SCSI_SEL_IRQn EXTI10_15_IRQn
-
-// SEL pin for ODE and v1.2
-#define SCSI_ODE_SEL_PORT GPIOD
-#define SCSI_ODE_SEL_PIN  GPIO_PIN_15
-#define SCSI_ODE_SEL_EXTI EXTI_15
-#define SCSI_ODE_SEL_EXTI_SOURCE_PORT GPIO_PORT_SOURCE_GPIOD
-#define SCSI_ODE_SEL_EXTI_SOURCE_PIN GPIO_PIN_SOURCE_15
-#define SCSI_ODE_SEL_IRQ EXTI10_15_IRQHandler
-#define SCSI_ODE_SEL_IRQn EXTI10_15_IRQn
-
-// BSY pin uses EXTI interrupt
-#define SCSI_BSY_PORT GPIOB
-#define SCSI_BSY_PIN  GPIO_PIN_10
-#define SCSI_BSY_EXTI EXTI_10
-#define SCSI_BSY_EXTI_SOURCE_PORT GPIO_PORT_SOURCE_GPIOB
-#define SCSI_BSY_EXTI_SOURCE_PIN  GPIO_PIN_SOURCE_10
-#define SCSI_BSY_IRQ  EXTI10_15_IRQHandler
-#define SCSI_BSY_IRQn EXTI10_15_IRQn
-
-// RST pin uses EXTI interrupt
-#define SCSI_RST_PORT GPIOB
-#define SCSI_RST_PIN  GPIO_PIN_13
-#define SCSI_RST_EXTI EXTI_13
-#define SCSI_RST_EXTI_SOURCE_PORT GPIO_PORT_SOURCE_GPIOB
-#define SCSI_RST_EXTI_SOURCE_PIN GPIO_PIN_SOURCE_13
-#define SCSI_RST_IRQ  EXTI10_15_IRQHandler
-#define SCSI_RST_IRQn EXTI10_15_IRQn
-
-// Terminator enable/disable config, active low
-#define SCSI_TERM_EN_PORT GPIOB
-#define SCSI_TERM_EN_PIN  GPIO_PIN_0
-
-// SD card pins
-#define SD_USE_SDIO 1
-#define SD_SDIO_DATA_PORT GPIOC
-#define SD_SDIO_D0        GPIO_PIN_8
-#define SD_SDIO_D1        GPIO_PIN_9
-#define SD_SDIO_D2        GPIO_PIN_10
-#define SD_SDIO_D3        GPIO_PIN_11
-#define SD_SDIO_CLK_PORT  GPIOC
-#define SD_SDIO_CLK       GPIO_PIN_12
-#define SD_SDIO_CMD_PORT  GPIOD
-#define SD_SDIO_CMD       GPIO_PIN_2
-
-// V1.2 SD Card write protect and card detect
-#define SD_WP_PORT GPIOE
-#define SD_WP_PIN  GPIO_PIN_2
-#define SD_CD_PORT GPIOE
-#define SD_CD_PIN  GPIO_PIN_3
-
-// v1.2 has a strong pull up, the ODE has strong pull down, v1.1 vanilla test for a floating pin
-#define DIGITAL_VERSION_DETECT_PORT  GPIOA
-#define DIGITAL_VERSION_DETECT_PIN   GPIO_PIN_15
-
-// v1.2 and future boards detect version via voltage level
-// v1.2: 2.5V
-// TODO get ADC version detection working
-#define ADC_VERSION_DETECT_PORT GPIOC
-#define ADC_VERSION_DETECT_PIN  GPIO_PIN_0
-#define ADC_VERSION_DETECT_CHANNEL ADC_CHANNEL_10
-#define ADC_VERSION_DETECT_V1_2_LIMIT_LOW 0
-#define ADC_VERSION_DETECT_V1_2_LIMIT_HIGH 4096*1
-
-// I2C and SPI Interrupt Pin
-#define INTR_PORT   GPIOE
-#define INTR_PIN    GPIO_PIN_1
-
-// SPI Pins: v1.2
-#define SPI_CS_PORT     GPIOB
-#define SPI_CS_PIN      GPIO_PIN_9
-#define SPI_MISO_PORT   GPIOC
-#define SPI_MISO_PIN    GPIO_PIN_2
-#define SPI_MOSI_PORT   GPIOC
-#define SPI_MOSI_PIN    GPIO_PIN_3
-#define SPI_CK_PORT     GPIOD
-#define SPI_CK_PIN      GPIO_PIN_3
-// I2S pins: ODE and v1.2
-#define I2S_SD_PORT     SPI_MOSI_PORT
-#define I2S_SD_PIN      SPI_MOSI_PIN
-#define I2S_WS_PORT     SPI_CS_PORT
-#define I2S_WS_PIN      SPI_CS_PIN
-#define I2S_CK_PORT     SPI_CK_PORT
-#define I2S_CK_PIN      SPI_CK_PIN
-
-// SPI/I2S DMA - ODE and v1.2
-#define SPI_DMA         DMA0
-#define SPI_DMA_CH      DMA_CH4
-#define SPI_RCU_DMA     RCU_DMA0
-#define SPI_I2S_SPI     SPI1
-#define SPI_RCU_I2S_SPI RCU_SPI1
-#define SPI_IRQHandler  DMA0_Channel4_IRQHandler
-#define SPI_DMA_IRQn    DMA0_Channel4_IRQn
-
-// DIP switches
-#define DIP_PORT     GPIOB
-#define DIPSW1_PIN   GPIO_PIN_4
-#define DIPSW2_PIN   GPIO_PIN_5
-#define DIPSW3_PIN   GPIO_PIN_6
-
-// ODE DIP switch pins
-#define ODE_DIP_PORT     GPIOB
-#define ODE_DIPSW1_PIN   GPIO_PIN_8
-#define ODE_DIPSW2_PIN   GPIO_PIN_5
-#define ODE_DIPSW3_PIN   GPIO_PIN_4
-
-// v1.2 DIP switch pins
-#define V1_2_DIPSW_TERM_PORT        GPIOB
-#define V1_2_DIPSW_TERM_PIN         GPIO_PIN_4
-#define V1_2_DIPSW_DBG_PORT         GPIOB
-#define V1_2_DIPSW_DBG_PIN          GPIO_PIN_5
-#define V1_2_DIPSW_QUIRKS_PORT      GPIOE
-#define V1_2_DIPSW_QUIRKS_PIN       GPIO_PIN_0
-#define V1_2_DIPSW_DIRECT_MODE_PORT GPIOB
-#define V1_2_DIPSW_DIRECT_MODE_PIN  GPIO_PIN_8
-// SCSI ID DIP switch
-#define DIPSW_SCSI_ID_BIT_PORT  GPIOC
-#define DIPSW_SCSI_ID_BIT1_PIN  GPIO_PIN_13
-#define DIPSW_SCSI_ID_BIT2_PIN  GPIO_PIN_14
-#define DIPSW_SCSI_ID_BIT3_PIN  GPIO_PIN_15
-#define DIPSW_SCSI_ID_BIT_PINS  (DIPSW_SCSI_ID_BIT1_PIN | DIPSW_SCSI_ID_BIT2_PIN | DIPSW_SCSI_ID_BIT3_PIN)
-#define DIPSW_SCSI_ID_BIT_SHIFT 13
-// Rotary DIP switch
-#define DIPROT_DEVICE_SEL_BIT_PORT  GPIOE
-#define DIPROT_DEVICE_SEL_BIT1_PIN  GPIO_PIN_4
-#define DIPROT_DEVICE_SEL_BIT2_PIN  GPIO_PIN_5
-#define DIPROT_DEVICE_SEL_BIT3_PIN  GPIO_PIN_6
-#define DIPROT_DEVICE_SEL_BIT_PINS  (DIPROT_DEVICE_SEL_BIT1_PIN | DIPROT_DEVICE_SEL_BIT2_PIN |  DIPROT_DEVICE_SEL_BIT3_PIN)
-#define DIPROT_DEVICE_SEL_BIT_SHIFT 4
-
-// ODE I2S Audio
-#define ODE_I2S_CK_PORT GPIOD
-#define ODE_I2S_CK_PIN  GPIO_PIN_3
-#define ODE_I2S_SD_PORT GPIOC
-#define ODE_I2S_SD_PIN  GPIO_PIN_3
-#define ODE_I2S_WS_PORT GPIOB
-#define ODE_I2S_WS_PIN  GPIO_PIN_9
-#define ODE_DMA         DMA0
-#define ODE_DMA_CH      DMA_CH4
-#define ODE_RCU_DMA     RCU_DMA0
-#define ODE_I2S_SPI     SPI1
-#define ODE_RCU_I2S_SPI RCU_SPI1
-#define ODE_IRQHandler  DMA0_Channel4_IRQHandler
-#define ODE_DMA_IRQn    DMA0_Channel4_IRQn
-
-
-// Status LED pins
-#define LED_PORT     GPIOC
-#define LED_I_PIN    GPIO_PIN_4
-#define LED_E_PIN    GPIO_PIN_5
-#define LED_PINS     (LED_I_PIN | LED_E_PIN)
-#define LED_EJECT_PORT  GPIOA
-#define LED_EJECT_PIN   GPIO_PIN_1
-#define LED_EJECT_ON()  gpio_bit_reset(LED_EJECT_PORT, LED_EJECT_PIN)
-#define LED_EJECT_OFF() gpio_bit_set(LED_EJECT_PORT, LED_EJECT_PIN)
-
-// Ejection buttons are available on expansion header J303.
-// PE5 = channel 1, PE6 = channel 2
-// Connect button between GPIO and GND pin.
-#define EJECT_1_PORT    GPIOE
-#define EJECT_1_PIN     GPIO_PIN_5
-#define EJECT_2_PORT    GPIOE
-#define EJECT_2_PIN     GPIO_PIN_6
-
-// Ejection button is on GPIO PA2 and USER button is on GPIO PA3
-#define EJECT_BTN_PORT  GPIOA
-#define EJECT_BTN_PIN   GPIO_PIN_2
-#define USER_BTN_PORT   GPIOA
-#define USER_BTN_PIN    GPIO_PIN_3

+ 0 - 424
lib/ZuluSCSI_platform_GD32F205/audio_i2s.cpp

@@ -1,424 +0,0 @@
-/** 
- * Copyright (C) 2023 saybur
- * ZuluSCSI™ - Copyright (c) 2023-2025 Rabbit Hole Computing™
- * 
- * ZuluSCSI™ firmware is licensed under the GPL version 3 or any later version. 
- * 
- * https://www.gnu.org/licenses/gpl-3.0.html
- * ----
- * 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 <https://www.gnu.org/licenses/>.
-**/
-#ifdef ENABLE_AUDIO_OUTPUT_I2S
-#include "audio_i2s.h"
-#include "ZuluSCSI_platform.h"
-#include "ZuluSCSI_audio.h"
-#include "ZuluSCSI_v1_1_gpio.h"
-#include "ZuluSCSI_log.h"
-
-extern "C" 
-{
-    #include "gd32f20x_rcu.h" 
-    #include "gd32f20x_dma.h"
-    #include "gd32f20x_misc.h"
-}
-
-bool g_audio_enabled = false;
-bool g_audio_stopped = true;
-
-// some chonky buffers to store audio samples
-static uint8_t sample_circ_buf[AUDIO_BUFFER_SIZE] __attribute__((aligned(4)));
-
-// tracking for the state for the circular buffer, A first half and B second half
-enum bufstate { STALE, FILLING, READY };
-static volatile bufstate sbufst_a = STALE;
-static volatile bufstate sbufst_b = STALE;
-static uint8_t sbufswap = 0;
-
-// tracking for audio playback
-static uint8_t audio_owner; // SCSI ID or 0xFF when idle
-static volatile bool audio_paused = false;
-static ImageBackingStore* audio_file;
-static volatile uint64_t fpos;
-static volatile uint32_t fleft;
-extern bool g_audio_stopped;
-
-
-// historical playback status information
-static audio_status_code audio_last_status[8] = {ASC_NO_STATUS, ASC_NO_STATUS, ASC_NO_STATUS, ASC_NO_STATUS,
-                                                 ASC_NO_STATUS, ASC_NO_STATUS, ASC_NO_STATUS, ASC_NO_STATUS};
-
-// volume information for targets
-static volatile uint16_t volumes[8] = {
-    DEFAULT_VOLUME_LEVEL, DEFAULT_VOLUME_LEVEL, DEFAULT_VOLUME_LEVEL, DEFAULT_VOLUME_LEVEL,
-    DEFAULT_VOLUME_LEVEL, DEFAULT_VOLUME_LEVEL, DEFAULT_VOLUME_LEVEL, DEFAULT_VOLUME_LEVEL
-};
-static volatile uint16_t channels[8] = {
-    AUDIO_CHANNEL_ENABLE_MASK, AUDIO_CHANNEL_ENABLE_MASK, AUDIO_CHANNEL_ENABLE_MASK, AUDIO_CHANNEL_ENABLE_MASK,
-    AUDIO_CHANNEL_ENABLE_MASK, AUDIO_CHANNEL_ENABLE_MASK, AUDIO_CHANNEL_ENABLE_MASK, AUDIO_CHANNEL_ENABLE_MASK
-};
-
-bool audio_is_active() {
-    return audio_owner != 0xFF;
-}
-
-
-bool audio_is_playing(uint8_t id) {
-    return audio_owner == (id & 7);
-}
-
-
-
-static void audio_start_dma()
-{  
-        dma_channel_disable(ODE_DMA, ODE_DMA_CH);
-        dma_interrupt_flag_clear(ODE_DMA, ODE_DMA_CH, DMA_INT_FLAG_HTF);
-        dma_interrupt_flag_clear(ODE_DMA, ODE_DMA_CH, DMA_INT_FLAG_FTF);
-        dma_interrupt_enable(ODE_DMA, ODE_DMA_CH, DMA_INT_HTF | DMA_INT_FTF);
-        dma_transfer_number_config(ODE_DMA, ODE_DMA_CH, AUDIO_BUFFER_SIZE / 2); // convert to 16bit transfer count
-        spi_enable(ODE_I2S_SPI);
-        dma_channel_enable(ODE_DMA, ODE_DMA_CH);
-
-}
-extern "C"
-{
-    void ODE_IRQHandler() 
-    {
-        if ( SET == dma_interrupt_flag_get(ODE_DMA, ODE_DMA_CH, DMA_INT_FLAG_HTF))
-        {
-            dma_interrupt_flag_clear(ODE_DMA, ODE_DMA_CH, DMA_INT_FLAG_HTF);
-            sbufst_a = STALE;
-        }
-        if (SET == dma_interrupt_flag_get(ODE_DMA, ODE_DMA_CH, DMA_INT_FLAG_FTF))
-        {
-            dma_interrupt_flag_clear(ODE_DMA, ODE_DMA_CH, DMA_INT_FLAG_FTF);
-            sbufst_b = STALE;
-        } 
-    }
-}
-
-void audio_setup() 
-{
-    // Setup clocks  
-    rcu_periph_clock_enable(ODE_RCU_I2S_SPI);
-    rcu_periph_clock_enable(ODE_RCU_DMA);
-
-    // Install NVIC
-    nvic_irq_enable(ODE_DMA_IRQn, 3, 0);
-
-    // DMA setup
-    dma_parameter_struct dma_init_struct;
-    dma_struct_para_init(&dma_init_struct);
-
-    dma_deinit(ODE_DMA, ODE_DMA_CH);
-    dma_init_struct.periph_addr  = (uint32_t)&SPI_DATA(ODE_I2S_SPI);
-    dma_init_struct.memory_addr  = (uint32_t)sample_circ_buf;
-    dma_init_struct.direction    = DMA_MEMORY_TO_PERIPHERAL;
-    dma_init_struct.memory_width = DMA_MEMORY_WIDTH_16BIT;
-    dma_init_struct.periph_width = DMA_PERIPHERAL_WIDTH_16BIT;
-    dma_init_struct.priority     = DMA_PRIORITY_LOW;
-    dma_init_struct.number       = AUDIO_BUFFER_SIZE / 2; // 8 bit to 16 bit conversion length
-    dma_init_struct.periph_inc   = DMA_PERIPH_INCREASE_DISABLE;
-    dma_init_struct.memory_inc   = DMA_MEMORY_INCREASE_ENABLE;
-    dma_init(ODE_DMA, ODE_DMA_CH, &dma_init_struct);
-    /* configure DMA mode */
-    dma_circulation_enable(ODE_DMA, ODE_DMA_CH);
-    dma_memory_to_memory_disable(ODE_DMA, ODE_DMA_CH);
-
-    /* configure I2S1 */
-    i2s_disable(ODE_I2S_SPI);
-    spi_i2s_deinit(ODE_I2S_SPI);
-    i2s_init(ODE_I2S_SPI, I2S_MODE_MASTERTX, I2S_STD_PHILLIPS, I2S_CKPL_LOW);
-    i2s_psc_config(ODE_I2S_SPI, I2S_AUDIOSAMPLE_44K, I2S_FRAMEFORMAT_DT16B_CH16B, I2S_MCKOUT_DISABLE);
-    spi_dma_enable(ODE_I2S_SPI, SPI_DMA_TRANSMIT);
-    i2s_enable(ODE_I2S_SPI);
-
-}
-
-/*
- * Takes in a buffer with interleaved 16bit samples and adjusts their volume
-*/
-static void audio_adjust(uint8_t owner, int16_t* buffer, size_t length)
-{
-    uint8_t volume[2]; 
-    uint16_t packed_volume = volumes[owner & 7];
-    volume[0] = packed_volume >> 8;
-    volume[1] = packed_volume & 0xFF;
-
-    // enable or disable based on the channel information for both output
-    // ports, where the high byte and mask control the right channel, and
-    // the low control the left channel    
-    uint16_t chn = channels[owner & 7] & AUDIO_CHANNEL_ENABLE_MASK;
-    if (!(chn >> 8))
-    {
-        volume[0] = 0;
-    } 
-    if (!(chn & 0xFF))
-    {
-        volume[1] = 0;
-    }
-
-    for (int i = 0; i < length; i++)
-    {
-        // linear volume
-        buffer[i] = (int16_t)(( ((int32_t)buffer[i]) * volume[i & 0x1]) >> 8); 
-    }
-
-}
-
-void audio_poll() 
-{
-    if(!g_audio_enabled)
-        return;
-
-    if ((!g_audio_stopped) && 1 == (0x1 & platform_get_buttons()))
-    {
-        audio_stop(audio_owner);
-    }
-    if (!audio_is_active()) return;
-    if (audio_paused) return;
-    if (fleft == 0 && sbufst_a == STALE && sbufst_b == STALE) {
-        // out of data and ready to stop
-        audio_stop(audio_owner);
-        return;
-    } else if (fleft == 0) {
-        // out of data to read but still working on remainder
-        return;
-    } else if (!audio_file->isOpen()) {
-        // closed elsewhere, maybe disk ejected?
-        dbgmsg("------ Playback stop due to closed file");
-        audio_stop(audio_owner);
-        return;
-    }
-
-    if ( STALE  == sbufst_a || STALE == sbufst_b )
-    {
-        uint8_t* audiobuf;
-        if (sbufst_a == STALE) {
-            sbufst_a = FILLING;
-            audiobuf = sample_circ_buf;
-        } 
-        
-        if (sbufst_b == STALE) {
-            sbufst_b = FILLING;
-            audiobuf = sample_circ_buf + AUDIO_BUFFER_HALF_SIZE;
-        }
-
-        platform_set_sd_callback(NULL, NULL);
- 
-        uint16_t toRead = AUDIO_BUFFER_HALF_SIZE;
-        if (fleft < toRead) toRead = fleft;
-        if (audio_file->position() != fpos) {
-            // should be uncommon due to SCSI command restrictions on devices
-            // playing audio; if this is showing up in logs a different approach
-            // will be needed to avoid seek performance issues on FAT32 vols
-            dbgmsg("------ Audio seek required on ", audio_owner);
-            if (!audio_file->seek(fpos)) {
-                logmsg("Audio error, unable to seek to ", fpos, ", ID:", audio_owner);
-            }
-        }
-        ssize_t read_length = audio_file->read(audiobuf, AUDIO_BUFFER_HALF_SIZE);
-        
-        if ( read_length < AUDIO_BUFFER_HALF_SIZE )
-        {
-            if ( read_length < 0)
-            {
-                logmsg("Playback file half buffer size read error: ", read_length);    
-                return;
-            }
-            else
-            {
-                // pad buffer with zeros
-                memset(audiobuf + read_length, 0, AUDIO_BUFFER_HALF_SIZE - read_length);
-            }
-        }
-        audio_adjust(audio_owner, (int16_t*) audiobuf, AUDIO_BUFFER_HALF_SIZE / 2);
-    
-        fpos += toRead;
-        fleft -= toRead;
-
-        if (sbufst_a == FILLING) {
-            sbufst_a = READY;
-        } else if (sbufst_b == FILLING) {
-            sbufst_b = READY;
-        }
-    }
-}
-
-bool audio_play(uint8_t owner, image_config_t* img, uint64_t start, uint64_t end, bool swap)
-{
-    if (audio_is_active()) audio_stop(audio_owner);
-
-
-    // verify audio file is present and inputs are (somewhat) sane
-    if (owner == 0xFF) 
-    {
-        logmsg("Illegal audio owner");
-        return false;
-    }
-    if (start >= end) 
-    {
-        logmsg("Invalid range for audio (", start, ":", end, ")");
-        return false;
-    }
-
-    audio_file = &img->file;
-    if (!audio_file->isOpen()) {
-        logmsg("File not open for audio playback, ", owner);
-        return false;
-    }
-    uint64_t len = audio_file->size();
-    if (start > len) 
-    {
-        logmsg("File playback request start (", start, ":", len, ") outside file bounds");
-        return false;
-    }
-    // truncate playback end to end of file
-    // we will not consider this to be an error at the moment
-    if (end > len) 
-    {
-        dbgmsg("------ Truncate audio play request end ", end, " to file size ", len);
-        end = len;
-    }
-    fleft = end - start;
-    if (fleft <= AUDIO_BUFFER_SIZE)
-    {
-        logmsg("File playback request (", start, ":", end, ") too short");
-        return false;
-    }
-
-    // read in initial sample buffers
-    if (!audio_file->seek(start))
-    {
-        logmsg("Sample file failed start seek to ", start);
-        return false;
-    }
-    ssize_t read_length = audio_file->read(sample_circ_buf, AUDIO_BUFFER_SIZE);
-    if ( read_length < AUDIO_BUFFER_SIZE)
-    {
-        if ( read_length < 0)
-        {
-            logmsg("Playback file read error: ", read_length);    
-            return false;
-        }
-        else
-        {
-            // pad buffer with zeros
-            memset(sample_circ_buf + read_length, 0, AUDIO_BUFFER_SIZE - read_length);
-        }
-
-    }
-    audio_adjust(owner, (int16_t*)sample_circ_buf, AUDIO_BUFFER_SIZE / 2);
- 
-    // prepare initial tracking state
-    fpos = audio_file->position();
-    fleft -= AUDIO_BUFFER_SIZE;
-    sbufswap = swap;
-    sbufst_a = READY;
-    sbufst_b = READY;
-    audio_owner = owner & 7;
-    audio_last_status[audio_owner] = ASC_PLAYING;
-    audio_paused = false;
-    g_audio_stopped = false;
-    audio_start_dma();
-
-    return true;
-}
-
-bool audio_set_paused(uint8_t id, bool paused)
-{
-    if (audio_owner != (id & 7)) return false;
-    else if (audio_paused && paused) return false;
-    else if (!audio_paused && !paused) return false;
-
-
-
-    if (paused) 
-    {
-        // Turn off interrupts to stop flagging new audio samples to load
-        dma_interrupt_disable(ODE_DMA, ODE_DMA_CH, DMA_INT_FTF | DMA_INT_HTF);
-        dma_interrupt_flag_clear(ODE_DMA, ODE_DMA_CH, DMA_INT_FLAG_HTF);
-        dma_interrupt_flag_clear(ODE_DMA, ODE_DMA_CH, DMA_INT_FLAG_FTF);
-        // Set status for both left and right channel to stop audio polling
-        // from loading new samples
-        sbufst_a = READY;
-        sbufst_b = READY;
-        // Let the DMA continue to run but set audio out to 0s
-        memset(sample_circ_buf, 0, AUDIO_BUFFER_SIZE);
-        audio_last_status[audio_owner] = ASC_PAUSED;
-    } 
-    else
-    {
-        // Enable audio polling and DMA interrupts to load and play new samples
-        sbufst_a = STALE;
-        sbufst_b = STALE;
-        dma_interrupt_flag_clear(ODE_DMA, ODE_DMA_CH, DMA_INT_FLAG_HTF);
-        dma_interrupt_flag_clear(ODE_DMA, ODE_DMA_CH, DMA_INT_FLAG_FTF);
-        dma_interrupt_enable(ODE_DMA, ODE_DMA_CH, DMA_INT_FTF | DMA_INT_HTF);
-        audio_last_status[audio_owner] = ASC_PLAYING;
-    }
-    return true;
-}
-
-void audio_stop(uint8_t id)
-{
-    if (audio_owner != (id & 7)) return;
-
-    spi_disable(ODE_I2S_SPI);
-    dma_channel_disable(ODE_DMA, ODE_DMA_CH);
-
-    // idle the subsystem
-    audio_last_status[audio_owner] = ASC_COMPLETED;
-    audio_paused = false;
-    g_audio_stopped = true;
-    audio_owner = 0xFF;
-}
-
-audio_status_code audio_get_status_code(uint8_t id)
-{
-    audio_status_code tmp = audio_last_status[id & 7];
-    if (tmp == ASC_COMPLETED || tmp == ASC_ERRORED) {
-        audio_last_status[id & 7] = ASC_NO_STATUS;
-    }
-    return tmp;
-}
-
-uint16_t audio_get_volume(uint8_t id)
-{
-    return volumes[id & 7];
-}
-
-void audio_set_volume(uint8_t id, uint16_t vol)
-{
-    volumes[id & 7] = vol;
-}
-
-uint16_t audio_get_channel(uint8_t id) {
-    return channels[id & 7];
-}
-
-void audio_set_channel(uint8_t id, uint16_t chn) {
-    channels[id & 7] = chn;
-}
-
-uint64_t audio_get_file_position()
-{
-    return fpos;
-}
-
-void audio_set_file_position(uint8_t id, uint32_t lba)
-{
-    fpos = 2352 * (uint64_t)lba;
-}
-
-#endif // ENABLE_AUDIO_OUTPUT_I2S

+ 0 - 61
lib/ZuluSCSI_platform_GD32F205/audio_i2s.h

@@ -1,61 +0,0 @@
-/** 
- * Copyright (C) 2023 saybur
- * ZuluSCSI™ - Copyright (c) 2023-2025 Rabbit Hole Computing™
- * 
- * ZuluSCSI™ firmware is licensed under the GPL version 3 or any later version. 
- * 
- * https://www.gnu.org/licenses/gpl-3.0.html
- * ----
- * 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 <https://www.gnu.org/licenses/>.
-**/
-
-
-#pragma once
-#ifdef ENABLE_AUDIO_OUTPUT_I2S
-
-extern bool g_audio_enabled;
-extern bool g_ode_audio_stopped;
-
-// size of the a circular audio sample buffer, in bytes
-// these must be divisible by 1024
-#define AUDIO_BUFFER_SIZE 16384
-// #define AUDIO_BUFFER_SIZE 8192 // ~46.44ms 
-// # define AUDIO_BUFFER_SIZE 4096 // reduce memory usage
-#define AUDIO_BUFFER_HALF_SIZE AUDIO_BUFFER_SIZE / 2
-
-/**
- * Handler for I2S DMA interrupts
- */
-void ODE_IRQHandler();
-
-
-/**
- * Indicates if the audio subsystem is actively streaming, including if it is
- * sending silent data during sample stall events.
- *
- * \return true if audio streaming is active, false otherwise.
- */
-bool audio_is_active();
-
-/**
- * Initializes the audio subsystem. Should be called only once, toward the end
- * of platform_late_init().
- */
-void audio_setup();
-
-/**
- * Called from platform_poll() to fill sample buffer(s) if needed.
- */
-void audio_poll();
-#endif //ENABLE_AUDIO_OUTPUT_I2S

+ 0 - 536
lib/ZuluSCSI_platform_GD32F205/gd32_cdc_acm_core.c

@@ -1,536 +0,0 @@
-/*!
-    \file    cdc_acm_core.c
-    \brief   CDC ACM driver
-
-    \version 2020-07-28, V3.0.0, firmware for GD32F20x
-    \version 2020-12-10, V3.0.1, firmware for GD32F20x
-    \version 2020-12-14, V3.0.2, firmware for GD32F20x
-*/
-
-/*
-    Copyright (c) 2020, GigaDevice Semiconductor Inc.
-
-    Redistribution and use in source and binary forms, with or without modification, 
-are permitted provided that the following conditions are met:
-
-    1. Redistributions of source code must retain the above copyright notice, this 
-       list of conditions and the following disclaimer.
-    2. Redistributions in binary form must reproduce the above copyright notice, 
-       this list of conditions and the following disclaimer in the documentation 
-       and/or other materials provided with the distribution.
-    3. Neither the name of the copyright holder nor the names of its contributors 
-       may be used to endorse or promote products derived from this software without 
-       specific prior written permission.
-
-    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
-AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 
-WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 
-IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 
-INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 
-NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 
-PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
-WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
-ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY 
-OF SUCH DAMAGE.
-*/
-
-#include "gd32_cdc_acm_core.h"
-#include "usbd_core.h"
-
-#define USBD_VID                          0x28E9U
-#define USBD_PID                          0x018AU
-
-/* note:it should use the C99 standard when compiling the below codes */
-/* USB standard device descriptor */
-const usb_desc_dev gd32_cdc_dev_desc =
-{
-    .header = 
-     {
-         .bLength          = USB_DEV_DESC_LEN, 
-         .bDescriptorType  = USB_DESCTYPE_DEV,
-     },
-    .bcdUSB                = 0x0200U,
-    .bDeviceClass          = USB_CLASS_CDC,
-    .bDeviceSubClass       = 0x00U,
-    .bDeviceProtocol       = 0x00U,
-    .bMaxPacketSize0       = USB_FS_EP0_MAX_LEN,
-    .idVendor              = USBD_VID,
-    .idProduct             = USBD_PID,
-    .bcdDevice             = 0x0100U,
-    .iManufacturer         = STR_IDX_MFC,
-    .iProduct              = STR_IDX_PRODUCT,
-    .iSerialNumber         = STR_IDX_SERIAL,
-    .bNumberConfigurations = USBD_CFG_MAX_NUM,
-};
-
-/* USB device configuration descriptor */
-const usb_cdc_desc_config_set gd32_cdc_config_desc = 
-{
-    .config = 
-    {
-        .header = 
-         {
-             .bLength         = sizeof(usb_desc_config), 
-             .bDescriptorType = USB_DESCTYPE_CONFIG,
-         },
-        .wTotalLength         = USB_CDC_ACM_CONFIG_DESC_SIZE,
-        .bNumInterfaces       = 0x02U,
-        .bConfigurationValue  = 0x01U,
-        .iConfiguration       = 0x00U,
-        .bmAttributes         = 0x80U,
-        .bMaxPower            = 0x32U
-    },
-
-    .cmd_itf = 
-    {
-        .header = 
-         {
-             .bLength         = sizeof(usb_desc_itf), 
-             .bDescriptorType = USB_DESCTYPE_ITF 
-         },
-        .bInterfaceNumber     = 0x00U,
-        .bAlternateSetting    = 0x00U,
-        .bNumEndpoints        = 0x01U,
-        .bInterfaceClass      = USB_CLASS_CDC,
-        .bInterfaceSubClass   = USB_CDC_SUBCLASS_ACM,
-        .bInterfaceProtocol   = USB_CDC_PROTOCOL_AT,
-        .iInterface           = 0x00U
-    },
-
-    .cdc_header = 
-    {
-        .header =
-         {
-            .bLength         = sizeof(usb_desc_header_func), 
-            .bDescriptorType = USB_DESCTYPE_CS_INTERFACE
-         },
-        .bDescriptorSubtype  = 0x00U,
-        .bcdCDC              = 0x0110U
-    },
-
-    .cdc_call_managment = 
-    {
-        .header = 
-         {
-            .bLength         = sizeof(usb_desc_call_managment_func), 
-            .bDescriptorType = USB_DESCTYPE_CS_INTERFACE
-         },
-        .bDescriptorSubtype  = 0x01U,
-        .bmCapabilities      = 0x00U,
-        .bDataInterface      = 0x01U
-    },
-
-    .cdc_acm = 
-    {
-        .header = 
-         {
-            .bLength         = sizeof(usb_desc_acm_func), 
-            .bDescriptorType = USB_DESCTYPE_CS_INTERFACE
-         },
-        .bDescriptorSubtype  = 0x02U,
-        .bmCapabilities      = 0x02U,
-    },
-
-    .cdc_union = 
-    {
-        .header = 
-         {
-            .bLength         = sizeof(usb_desc_union_func), 
-            .bDescriptorType = USB_DESCTYPE_CS_INTERFACE
-         },
-        .bDescriptorSubtype  = 0x06U,
-        .bMasterInterface    = 0x00U,
-        .bSlaveInterface0    = 0x01U,
-    },
-
-    .cdc_cmd_endpoint = 
-    {
-        .header = 
-         {
-            .bLength         = sizeof(usb_desc_ep), 
-            .bDescriptorType = USB_DESCTYPE_EP,
-         },
-        .bEndpointAddress    = CDC_CMD_EP,
-        .bmAttributes        = USB_EP_ATTR_INT,
-        .wMaxPacketSize      = USB_CDC_CMD_PACKET_SIZE,
-        .bInterval           = 0x0AU
-    },
-
-    .cdc_data_interface = 
-    {
-        .header = 
-         {
-            .bLength         = sizeof(usb_desc_itf), 
-            .bDescriptorType = USB_DESCTYPE_ITF,
-         },
-        .bInterfaceNumber    = 0x01U,
-        .bAlternateSetting   = 0x00U,
-        .bNumEndpoints       = 0x02U,
-        .bInterfaceClass     = USB_CLASS_DATA,
-        .bInterfaceSubClass  = 0x00U,
-        .bInterfaceProtocol  = USB_CDC_PROTOCOL_NONE,
-        .iInterface          = 0x00U
-    },
-
-    .cdc_out_endpoint = 
-    {
-        .header = 
-         {
-             .bLength         = sizeof(usb_desc_ep), 
-             .bDescriptorType = USB_DESCTYPE_EP, 
-         },
-        .bEndpointAddress     = CDC_DATA_OUT_EP,
-        .bmAttributes         = USB_EP_ATTR_BULK,
-        .wMaxPacketSize       = USB_CDC_DATA_PACKET_SIZE,
-        .bInterval            = 0x00U
-    },
-
-    .cdc_in_endpoint = 
-    {
-        .header = 
-         {
-             .bLength         = sizeof(usb_desc_ep), 
-             .bDescriptorType = USB_DESCTYPE_EP 
-         },
-        .bEndpointAddress     = CDC_DATA_IN_EP,
-        .bmAttributes         = USB_EP_ATTR_BULK,
-        .wMaxPacketSize       = USB_CDC_DATA_PACKET_SIZE,
-        .bInterval            = 0x00U
-    }
-};
-
-/* USB language ID Descriptor */
-static const usb_desc_LANGID usbd_language_id_desc = 
-{
-    .header = 
-     {
-         .bLength         = sizeof(usb_desc_LANGID), 
-         .bDescriptorType = USB_DESCTYPE_STR,
-     },
-    .wLANGID              = ENG_LANGID
-};
-
-/* USB manufacture string */
-static const usb_desc_str manufacturer_string = 
-{
-    .header = 
-     {
-         .bLength         = USB_STRING_LEN(19), 
-         .bDescriptorType = USB_DESCTYPE_STR,
-     },
-    .unicode_string = {'R', 'a', 'b', 'b', 'i', 't', 'H', 'o', 'l','e','C','o','m','p','u','t','i','n','g'}
-};
-
-/* USB product string */
-static const usb_desc_str product_string = 
-{
-    .header = 
-     {
-         .bLength         = USB_STRING_LEN(8), 
-         .bDescriptorType = USB_DESCTYPE_STR,
-     },
-    .unicode_string = {'Z', 'u', 'l', 'u', 'S', 'C', 'S', 'I'}
-};
-
-#ifdef USB_ENABLE_SERIALNUMBER
-/* USBD serial string
- * This gets set by serial_string_get() in GD32 SPL usbd_enum.c */
-static usb_desc_str serial_string =
-{
-    .header =
-     {
-         .bLength         = USB_STRING_LEN(12U),
-         .bDescriptorType = USB_DESCTYPE_STR,
-     }
-};
-#else
-/* Save some RAM by disabling the serial number.
- * Note that contents must not have null bytes or Windows gets confused
- * Having non-empty fake serial number avoids Windows recreating the
- * device every time it moves between USB ports. */
-static const usb_desc_str serial_string =
-{
-    .header = 
-     {
-         .bLength         = USB_STRING_LEN(4U),
-         .bDescriptorType = USB_DESCTYPE_STR,
-     },
-     .unicode_string = {'1', '2', '3', '4'}
-};
-#endif
-
-/* USB string descriptor set */
-void *const gd32_usbd_cdc_strings[] = 
-{
-    [STR_IDX_LANGID]  = (uint8_t *)&usbd_language_id_desc,
-    [STR_IDX_MFC]     = (uint8_t *)&manufacturer_string,
-    [STR_IDX_PRODUCT] = (uint8_t *)&product_string,
-    [STR_IDX_SERIAL]  = (uint8_t *)&serial_string
-};
-
-usb_desc gd32_cdc_desc = 
-{
-    .dev_desc    = (uint8_t *)&gd32_cdc_dev_desc,
-    .config_desc = (uint8_t *)&gd32_cdc_config_desc,
-    .strings     = gd32_usbd_cdc_strings
-};
-
-/* local function prototypes ('static') */
-static uint8_t cdc_acm_init   (usb_dev *udev, uint8_t config_index);
-static uint8_t cdc_acm_deinit (usb_dev *udev, uint8_t config_index);
-static uint8_t cdc_acm_req    (usb_dev *udev, usb_req *req);
-static uint8_t cdc_acm_ctlx_out (usb_dev *udev);
-static uint8_t cdc_acm_in     (usb_dev *udev, uint8_t ep_num);
-static uint8_t cdc_acm_out    (usb_dev *udev, uint8_t ep_num);
-
-/* USB CDC device class callbacks structure */
-usb_class_core gd32_cdc_class =
-{
-    .command   = NO_CMD,
-    .alter_set = 0U,
-
-    .init      = cdc_acm_init,
-    .deinit    = cdc_acm_deinit,
-
-    .req_proc  = cdc_acm_req,
-
-    .ctlx_out  = cdc_acm_ctlx_out,
-    .data_in   = cdc_acm_in,
-    .data_out  = cdc_acm_out
-};
-
-/*!
-    \brief      check CDC ACM is ready for data transfer
-    \param[in]  udev: pointer to USB device instance
-    \param[out] none
-    \retval     0 if CDC is ready, 5 else
-*/
-uint8_t gd32_cdc_acm_check_ready(usb_dev *udev)
-{
-    if (udev->dev.class_data[CDC_COM_INTERFACE] != NULL) {
-        gd32_usb_cdc_handler *cdc = (gd32_usb_cdc_handler *)udev->dev.class_data[CDC_COM_INTERFACE];
-
-        if ((1U == cdc->packet_sent)) {
-            return 1U;
-        }
-    }
-
-    return 0U;
-}
-
-/*!
-    \brief      send CDC ACM data
-    \param[in]  udev: pointer to USB device instance
-    \param[out] none
-    \retval     USB device operation status
-*/
-void gd32_cdc_acm_data_send(usb_dev *udev, uint8_t *data, uint32_t length)
-{
-    gd32_usb_cdc_handler *cdc = (gd32_usb_cdc_handler *)udev->dev.class_data[CDC_COM_INTERFACE];
-    if (cdc->packet_sent == 1)
-    {
-        cdc->packet_sent = 0U;
-        usbd_ep_send (udev, CDC_DATA_IN_EP, data, length);
-    }
-}
-
-/*!
-    \brief      receive CDC ACM data
-    \param[in]  udev: pointer to USB device instance
-    \param[out] none
-    \retval     USB device operation status
-*/
-void gd32_cdc_acm_data_receive (usb_dev *udev)
-{
-    gd32_usb_cdc_handler *cdc = (gd32_usb_cdc_handler *)udev->dev.class_data[CDC_COM_INTERFACE];
-    usbd_ep_recev(udev, CDC_DATA_OUT_EP, (uint8_t*)(cdc->data), USB_CDC_DATA_PACKET_SIZE);
-}
-
-/*!
-    \brief      initialize the CDC ACM device
-    \param[in]  udev: pointer to USB device instance
-    \param[in]  config_index: configuration index
-    \param[out] none
-    \retval     USB device operation status
-*/
-static uint8_t cdc_acm_init (usb_dev *udev, uint8_t config_index)
-{
-    static gd32_usb_cdc_handler cdc_handler;
-
-    /* initialize the data Tx endpoint */
-    usbd_ep_setup (udev, &(gd32_cdc_config_desc.cdc_in_endpoint));
-
-    /* initialize the data Rx endpoint */
-    usbd_ep_setup (udev, &(gd32_cdc_config_desc.cdc_out_endpoint));
-
-    /* initialize the command Tx endpoint */
-    usbd_ep_setup (udev, &(gd32_cdc_config_desc.cdc_cmd_endpoint));
-
-    /* initialize CDC handler structure */
-    cdc_handler.packet_receive = 1U;
-    cdc_handler.packet_sent = 1U;
-    cdc_handler.receive_length = 0U;
-
-    cdc_handler.line_coding = (acm_line){
-        .dwDTERate   = 115200,
-        .bCharFormat = 0,
-        .bParityType = 0,
-        .bDataBits   = 0x08
-    };
-
-    udev->dev.class_data[CDC_COM_INTERFACE] = (void *)&cdc_handler;
-
-    return USBD_OK;
-}
-
-/*!
-    \brief      deinitialize the CDC ACM device
-    \param[in]  udev: pointer to USB device instance
-    \param[in]  config_index: configuration index
-    \param[out] none
-    \retval     USB device operation status
-*/
-static uint8_t cdc_acm_deinit (usb_dev *udev, uint8_t config_index)
-{
-    /* deinitialize the data Tx/Rx endpoint */
-    usbd_ep_clear (udev, CDC_DATA_IN_EP);
-    usbd_ep_clear (udev, CDC_DATA_OUT_EP);
-
-    /* deinitialize the command Tx endpoint */
-    usbd_ep_clear (udev, CDC_CMD_EP);
-
-    return USBD_OK;
-}
-
-/*!
-    \brief      handle the CDC ACM class-specific requests
-    \param[in]  udev: pointer to USB device instance
-    \param[in]  req: device class-specific request
-    \param[out] none
-    \retval     USB device operation status
-*/
-static uint8_t cdc_acm_req (usb_dev *udev, usb_req *req)
-{
-    gd32_usb_cdc_handler *cdc = (gd32_usb_cdc_handler *)udev->dev.class_data[CDC_COM_INTERFACE];
-
-    usb_transc *transc = NULL;
-
-    switch (req->bRequest) {
-    case SEND_ENCAPSULATED_COMMAND:
-        /* no operation for this driver */
-        break;
-
-    case GET_ENCAPSULATED_RESPONSE:
-        /* no operation for this driver */
-        break;
-
-    case SET_COMM_FEATURE:
-        /* no operation for this driver */
-        break;
-
-    case GET_COMM_FEATURE:
-        /* no operation for this driver */
-        break;
-
-    case CLEAR_COMM_FEATURE:
-        /* no operation for this driver */
-        break;
-
-    case SET_LINE_CODING:
-        /* set the value of the current command to be processed */
-        udev->dev.class_core->alter_set = req->bRequest;
-
-        /* enable EP0 prepare to receive command data packet */
-        transc = &udev->dev.transc_in[0];
-        transc->remain_len = req->wLength;
-        transc->xfer_buf = cdc->cmd;
-        break;
-
-    case GET_LINE_CODING:
-        cdc->cmd[0] = (uint8_t)(cdc->line_coding.dwDTERate);
-        cdc->cmd[1] = (uint8_t)(cdc->line_coding.dwDTERate >> 8);
-        cdc->cmd[2] = (uint8_t)(cdc->line_coding.dwDTERate >> 16);
-        cdc->cmd[3] = (uint8_t)(cdc->line_coding.dwDTERate >> 24);
-        cdc->cmd[4] = cdc->line_coding.bCharFormat;
-        cdc->cmd[5] = cdc->line_coding.bParityType;
-        cdc->cmd[6] = cdc->line_coding.bDataBits;
-
-        transc = &udev->dev.transc_out[0];
-        transc->xfer_buf = cdc->cmd;
-        transc->remain_len = 7U;
-        break;
-
-    case SET_CONTROL_LINE_STATE:
-        /* no operation for this driver */
-        break;
-
-    case SEND_BREAK:
-        /* no operation for this driver */
-        break;
-
-    default:
-        return REQ_NOTSUPP;
-    }
-
-    return USBD_OK;
-}
-
-static uint8_t cdc_acm_ctlx_out (usb_dev *udev)
-{
-    gd32_usb_cdc_handler *cdc = (gd32_usb_cdc_handler *)udev->dev.class_data[CDC_COM_INTERFACE];
-
-    if (udev->dev.class_core->alter_set != NO_CMD) {
-        /* process the command data */
-        cdc->line_coding.dwDTERate = (uint32_t)((uint32_t)cdc->cmd[0] | 
-                                               ((uint32_t)cdc->cmd[1] << 8U) | 
-                                               ((uint32_t)cdc->cmd[2] << 16U) | 
-                                               ((uint32_t)cdc->cmd[3] << 24U));
-
-        cdc->line_coding.bCharFormat = cdc->cmd[4];
-        cdc->line_coding.bParityType = cdc->cmd[5];
-        cdc->line_coding.bDataBits = cdc->cmd[6];
-
-        udev->dev.class_core->alter_set = NO_CMD;
-    }
-
-    return USBD_OK;
-}
-
-/*!
-    \brief      handle CDC ACM data
-    \param[in]  udev: pointer to USB device instance
-    \param[in]  ep_num: endpoint identifier
-    \param[out] none
-    \retval     USB device operation status
-*/
-static uint8_t cdc_acm_in (usb_dev *udev, uint8_t ep_num)
-{
-    usb_transc *transc = &udev->dev.transc_in[EP_ID(ep_num)];
-
-    gd32_usb_cdc_handler *cdc = (gd32_usb_cdc_handler *)udev->dev.class_data[CDC_COM_INTERFACE];
-
-    if ((0U == transc->xfer_len % transc->max_len) && (0U != transc->xfer_len)) {
-        usbd_ep_send (udev, ep_num, NULL, 0U);
-    } else {
-        cdc->packet_sent = 1U;
-    }
-
-    return USBD_OK;
-}
-
-/*!
-    \brief      handle CDC ACM data
-    \param[in]  udev: pointer to USB device instance
-    \param[in]  ep_num: endpoint identifier
-    \param[out] none
-    \retval     USB device operation status
-*/
-static uint8_t cdc_acm_out (usb_dev *udev, uint8_t ep_num)
-{
-    gd32_usb_cdc_handler *cdc = (gd32_usb_cdc_handler *)udev->dev.class_data[CDC_COM_INTERFACE];
-
-    cdc->packet_receive = 1U;
-    cdc->receive_length = ((usb_core_driver *)udev)->dev.transc_out[ep_num].xfer_count;
-
-    return USBD_OK;
-}

+ 0 - 66
lib/ZuluSCSI_platform_GD32F205/gd32_cdc_acm_core.h

@@ -1,66 +0,0 @@
-/*!
-    \file    cdc_acm_core.h
-    \brief   the header file of CDC ACM driver
-
-    \version 2020-07-28, V3.0.0, firmware for GD32F20x
-*/
-
-/*
-    Copyright (c) 2020, GigaDevice Semiconductor Inc.
-
-    Redistribution and use in source and binary forms, with or without modification, 
-are permitted provided that the following conditions are met:
-
-    1. Redistributions of source code must retain the above copyright notice, this 
-       list of conditions and the following disclaimer.
-    2. Redistributions in binary form must reproduce the above copyright notice, 
-       this list of conditions and the following disclaimer in the documentation 
-       and/or other materials provided with the distribution.
-    3. Neither the name of the copyright holder nor the names of its contributors 
-       may be used to endorse or promote products derived from this software without 
-       specific prior written permission.
-
-    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
-AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 
-WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 
-IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 
-INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 
-NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 
-PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
-WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
-ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY 
-OF SUCH DAMAGE.
-*/
-
-#ifndef __CDC_ACM_CORE_H
-#define __CDC_ACM_CORE_H
-
-#include "usbd_enum.h"
-#include "usb_cdc.h"
-
-#define USB_CDC_RX_LEN      64
-
-typedef struct {
-    uint8_t packet_sent;
-    uint8_t packet_receive;
-
-    uint8_t data[USB_CDC_RX_LEN];
-    uint8_t cmd[USB_CDC_CMD_PACKET_SIZE];
-
-    uint32_t receive_length;
-
-    acm_line line_coding;
-} gd32_usb_cdc_handler;
-
-extern usb_desc gd32_cdc_desc;
-extern usb_class_core gd32_cdc_class;
-
-/* function declarations */
-/* check CDC ACM is ready for data transfer */
-uint8_t gd32_cdc_acm_check_ready(usb_dev *udev);
-/* send CDC ACM data */
-void gd32_cdc_acm_data_send(usb_dev *udev, uint8_t* data, uint32_t length);
-/* receive CDC ACM data */
-void gd32_cdc_acm_data_receive(usb_dev *udev);
-
-#endif /* __CDC_ACM_CORE_H */

+ 0 - 2520
lib/ZuluSCSI_platform_GD32F205/gd32_sdio_sdcard.c

@@ -1,2520 +0,0 @@
-/*!
-    \file    sdcard.c
-    \brief   SD card driver
-
-    \version 2015-07-15, V1.0.0, firmware for GD32F20x
-    \version 2017-06-05, V2.0.0, firmware for GD32F20x
-    \version 2018-10-31, V2.1.0, firmware for GD32F20x
-    \version 2020-09-30, V2.2.0, firmware for GD32F20x
-    \version 2021-07-30, V2.3.0, firmware for GD32F20x
-*/
-
-/*
-    Copyright (c) 2021, GigaDevice Semiconductor Inc.
-
-    Redistribution and use in source and binary forms, with or without modification,
-are permitted provided that the following conditions are met:
-
-    1. Redistributions of source code must retain the above copyright notice, this
-       list of conditions and the following disclaimer.
-    2. Redistributions in binary form must reproduce the above copyright notice,
-       this list of conditions and the following disclaimer in the documentation
-       and/or other materials provided with the distribution.
-    3. Neither the name of the copyright holder nor the names of its contributors
-       may be used to endorse or promote products derived from this software without
-       specific prior written permission.
-
-    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
-WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
-IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
-INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
-NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
-PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
-WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
-OF SUCH DAMAGE.
-*/
-
-#include "gd32_sdio_sdcard.h"
-#include "gd32f20x_sdio.h"
-#include <stddef.h>
-
-/* card status of R1 definitions */
-#define SD_R1_OUT_OF_RANGE                  BIT(31)                   /* command's argument was out of the allowed range */
-#define SD_R1_ADDRESS_ERROR                 BIT(30)                   /* misaligned address which did not match the block length */
-#define SD_R1_BLOCK_LEN_ERROR               BIT(29)                   /* transferred block length is not allowed */
-#define SD_R1_ERASE_SEQ_ERROR               BIT(28)                   /* an error in the sequence of erase commands occurred */
-#define SD_R1_ERASE_PARAM                   BIT(27)                   /* an invalid selection of write-blocks for erase occurred */
-#define SD_R1_WP_VIOLATION                  BIT(26)                   /* the host attempts to write to a protected block or to the temporary or permanent write protected card */
-#define SD_R1_CARD_IS_LOCKED                BIT(25)                   /* the card is locked by the host */
-#define SD_R1_LOCK_UNLOCK_FAILED            BIT(24)                   /* a sequence or password error has been detected in lock/unlock card command */
-#define SD_R1_COM_CRC_ERROR                 BIT(23)                   /* CRC check of the previous command failed */
-#define SD_R1_ILLEGAL_COMMAND               BIT(22)                   /* command not legal for the card state */
-#define SD_R1_CARD_ECC_FAILED               BIT(21)                   /* card internal ECC was applied but failed to correct the data */
-#define SD_R1_CC_ERROR                      BIT(20)                   /* internal card controller error */
-#define SD_R1_GENERAL_UNKNOWN_ERROR         BIT(19)                   /* a general or an unknown error occurred during the operation */
-#define SD_R1_CSD_OVERWRITE                 BIT(16)                   /* read only section of the CSD does not match or attempt to reverse the copy or permanent WP bits */
-#define SD_R1_WP_ERASE_SKIP                 BIT(15)                   /* partial address space was erased */
-#define SD_R1_CARD_ECC_DISABLED             BIT(14)                   /* command has been executed without using the internal ECC */
-#define SD_R1_ERASE_RESET                   BIT(13)                   /* an erase sequence was cleared before executing */
-#define SD_R1_READY_FOR_DATA                BIT(8)                    /* correspond to buffer empty signaling on the bus */
-#define SD_R1_APP_CMD                       BIT(5)                    /* card will expect ACMD */
-#define SD_R1_AKE_SEQ_ERROR                 BIT(3)                    /* error in the sequence of the authentication process */
-#define SD_R1_ERROR_BITS                    (uint32_t)0xFDF9E008      /* all the R1 error bits */
-
-/* card status of R6 definitions */
-#define SD_R6_COM_CRC_ERROR                 BIT(15)                   /* CRC check of the previous command failed */
-#define SD_R6_ILLEGAL_COMMAND               BIT(14)                   /* command not legal for the card state */
-#define SD_R6_GENERAL_UNKNOWN_ERROR         BIT(13)                   /* a general or an unknown error occurred during the operation */
-
-/* card state */
-#define SD_CARDSTATE_IDLE                   ((uint8_t)0x00)           /* card is in idle state */
-#define SD_CARDSTATE_READY                  ((uint8_t)0x01)           /* card is in ready state */
-#define SD_CARDSTATE_IDENTIFICAT            ((uint8_t)0x02)           /* card is in identificat state */
-#define SD_CARDSTATE_STANDBY                ((uint8_t)0x03)           /* card is in standby state */
-#define SD_CARDSTATE_TRANSFER               ((uint8_t)0x04)           /* card is in transfer state */
-#define SD_CARDSTATE_DATA                   ((uint8_t)0x05)           /* card is in data sending state */
-#define SD_CARDSTATE_RECEIVING              ((uint8_t)0x06)           /* card is in receiving state */
-#define SD_CARDSTATE_PROGRAMMING            ((uint8_t)0x07)           /* card is in programming state */
-#define SD_CARDSTATE_DISCONNECT             ((uint8_t)0x08)           /* card is in disconnect state */
-#define SD_CARDSTATE_LOCKED                 ((uint32_t)0x02000000)    /* card is in locked state */
-
-#define SD_CHECK_PATTERN                    ((uint32_t)0x000001AA)    /* check pattern for CMD8 */
-#define SD_VOLTAGE_WINDOW                   ((uint32_t)0x80100000)    /* host 3.3V request in ACMD41 */
-
-/* parameters for ACMD41(voltage validation) */
-#define SD_HIGH_CAPACITY                    ((uint32_t)0x40000000)    /* high capacity SD memory card */
-#define SD_STD_CAPACITY                     ((uint32_t)0x00000000)    /* standard capacity SD memory card */
-
-/* SD bus width, check SCR register */
-#define SD_BUS_WIDTH_4BIT                   ((uint32_t)0x00040000)    /* 4-bit width bus mode */
-#define SD_BUS_WIDTH_1BIT                   ((uint32_t)0x00010000)    /* 1-bit width bus mode */
-
-/* masks for SCR register */
-#define SD_MASK_0_7BITS                     ((uint32_t)0x000000FF)    /* mask [7:0] bits */
-#define SD_MASK_8_15BITS                    ((uint32_t)0x0000FF00)    /* mask [15:8] bits */
-#define SD_MASK_16_23BITS                   ((uint32_t)0x00FF0000)    /* mask [23:16] bits */
-#define SD_MASK_24_31BITS                   ((uint32_t)0xFF000000)    /* mask [31:24] bits */
-
-#define SDIO_FIFO_ADDR                      ((uint32_t)SDIO + 0x80U)  /* address of SDIO_FIFO */
-#define SD_FIFOHALF_WORDS                   ((uint32_t)0x00000008)    /* words of FIFO half full/empty */
-#define SD_FIFOHALF_BYTES                   ((uint32_t)0x00000020)    /* bytes of FIFO half full/empty */
-
-#define SD_DATATIMEOUT                      ((uint32_t)0xFFFFFFFF)    /* DSM data timeout */
-#define SD_MAX_VOLT_VALIDATION              ((uint32_t)0x0000FFFF)    /* the maximum times of voltage validation */
-#define SD_MAX_DATA_LENGTH                  ((uint32_t)0x01FFFFFF)    /* the maximum length of data */
-#define SD_ALLZERO                          ((uint32_t)0x00000000)    /* all zero */
-#define SD_RCA_SHIFT                        ((uint8_t)0x10)           /* RCA shift bits */
-#define SD_CLK_DIV_INIT                     ((uint16_t)0x0076)        /* SD clock division in initilization phase */
-#define SD_CLK_DIV_TRANS                    ((uint16_t)0x0002)        /* SD clock division in transmission phase */
-
-#define SDIO_MASK_INTC_FLAGS                ((uint32_t)0x00C007FF)    /* mask flags of SDIO_INTC */
-
-uint32_t sd_scr[2] = {0, 0};                                          /* content of SCR register */
-
-static sdio_card_type_enum cardtype = SDIO_STD_CAPACITY_SD_CARD_V1_1; /* SD card type */
-static uint32_t sd_csd[4] = {0, 0, 0, 0};                             /* content of CSD register */
-static uint32_t sd_cid[4] = {0, 0, 0, 0};                             /* content of CID register */
-static uint16_t sd_rca = 0;                                           /* RCA of SD card */
-static uint32_t transmode = SD_POLLING_MODE;
-static uint32_t totalnumber_bytes = 0, stopcondition = 0;
-static __IO sd_error_enum transerror = SD_OK;
-static __IO uint32_t transend = 0, number_bytes = 0;
-
-/* check if the command sent error occurs */
-static sd_error_enum cmdsent_error_check(void);
-/* check if error occurs for R1 response */
-static sd_error_enum r1_error_check(uint8_t cmdindex);
-/* check if error type for R1 response */
-static sd_error_enum r1_error_type_check(uint32_t resp);
-/* check if error occurs for R2 response */
-static sd_error_enum r2_error_check(void);
-/* check if error occurs for R3 response */
-static sd_error_enum r3_error_check(void);
-/* check if error occurs for R6 response */
-static sd_error_enum r6_error_check(uint8_t cmdindex, uint16_t *prca);
-/* check if error occurs for R7 response */
-static sd_error_enum r7_error_check(void);
-
-/* get the state which the card is in */
-static sd_error_enum sd_card_state_get(uint8_t *pcardstate);
-/* configure the bus width mode */
-static sd_error_enum sd_bus_width_config(uint32_t buswidth);
-/* get the SCR of corresponding card */
-static sd_error_enum sd_scr_get(uint16_t rca, uint32_t *pscr);
-/* get the data block size */
-static uint32_t sd_datablocksize_get(uint16_t bytesnumber);
-
-/* configure the DMA for SDIO transfer request */
-static void dma_transfer_config(uint32_t *srcbuf, uint32_t bufsize);
-/* configure the DMA for SDIO receive request */
-static void dma_receive_config(uint32_t *dstbuf, uint32_t bufsize);
-
-unsigned long millis(void);
-
-/*!
-    \brief      initialize the SD card and make it in standby state
-    \param[in]  none
-    \param[out] none
-    \retval     sd_error_enum
-*/
-sd_error_enum sd_init(void)
-{
-    sd_error_enum status = SD_OK;
-    /* configure the RCU and GPIO, deinitialize the SDIO */
-    sdio_deinit();
-
-    /* configure the clock and work voltage */
-    status = sd_power_on();
-    if(SD_OK != status) {
-        return status;
-    }
-
-    /* initialize the card and get CID and CSD of the card */
-    status = sd_card_init();
-    if(SD_OK != status) {
-        return status;
-    }
-
-    /* configure the SDIO peripheral */
-    sdio_clock_config(SDIO_SDIOCLKEDGE_RISING, SDIO_CLOCKBYPASS_DISABLE, SDIO_CLOCKPWRSAVE_DISABLE, SD_CLK_DIV_TRANS);
-    sdio_bus_mode_set(SDIO_BUSMODE_1BIT);
-    sdio_hardware_clock_disable();
-
-    return status;
-}
-
-/*!
-    \brief      initialize the card and get CID and CSD of the card
-    \param[in]  none
-    \param[out] none
-    \retval     sd_error_enum
-*/
-sd_error_enum sd_card_init(void)
-{
-    sd_error_enum status = SD_OK;
-    uint16_t temp_rca = 0x01;
-
-    if(SDIO_POWER_OFF == sdio_power_state_get()) {
-        status = SD_OPERATION_IMPROPER;
-        return status;
-    }
-
-    /* the card is not I/O only card */
-    if(SDIO_SECURE_DIGITAL_IO_CARD != cardtype) {
-        /* send CMD2(SD_CMD_ALL_SEND_CID) to get the CID numbers */
-        sdio_csm_disable();
-        sdio_command_response_config(SD_CMD_ALL_SEND_CID, (uint32_t)0x0, SDIO_RESPONSETYPE_LONG);
-        sdio_wait_type_set(SDIO_WAITTYPE_NO);
-        sdio_csm_enable();
-        /* check if some error occurs */
-        status = r2_error_check();
-        if(SD_OK != status) {
-            return status;
-        }
-
-        /* store the CID numbers */
-        sd_cid[0] = sdio_response_get(SDIO_RESPONSE0);
-        sd_cid[1] = sdio_response_get(SDIO_RESPONSE1);
-        sd_cid[2] = sdio_response_get(SDIO_RESPONSE2);
-        sd_cid[3] = sdio_response_get(SDIO_RESPONSE3);
-    }
-
-    /* the card is SD memory card or the I/O card has the memory portion */
-    if((SDIO_STD_CAPACITY_SD_CARD_V1_1 == cardtype) || (SDIO_STD_CAPACITY_SD_CARD_V2_0 == cardtype) ||
-            (SDIO_HIGH_CAPACITY_SD_CARD == cardtype) || (SDIO_SECURE_DIGITAL_IO_COMBO_CARD == cardtype)) {
-        /* send CMD3(SEND_RELATIVE_ADDR) to ask the card to publish a new relative address (RCA) */
-        sdio_csm_disable();
-        sdio_command_response_config(SD_CMD_SEND_RELATIVE_ADDR, (uint32_t)0x0, SDIO_RESPONSETYPE_SHORT);
-        sdio_wait_type_set(SDIO_WAITTYPE_NO);
-        sdio_csm_enable();
-        /* check if some error occurs */
-        status = r6_error_check(SD_CMD_SEND_RELATIVE_ADDR, &temp_rca);
-        if(SD_OK != status) {
-            return status;
-        }
-    }
-
-    if(SDIO_SECURE_DIGITAL_IO_CARD != cardtype) {
-        /* the card is not I/O only card */
-        sd_rca = temp_rca;
-
-        /* send CMD9(SEND_CSD) to get the addressed card's card-specific data (CSD) */
-        sdio_csm_disable();
-        sdio_command_response_config(SD_CMD_SEND_CSD, (uint32_t)(temp_rca << SD_RCA_SHIFT), SDIO_RESPONSETYPE_LONG);
-        sdio_wait_type_set(SDIO_WAITTYPE_NO);
-        sdio_csm_enable();
-        /* check if some error occurs */
-        status = r2_error_check();
-        if(SD_OK != status) {
-            return status;
-        }
-
-        /* store the card-specific data (CSD) */
-        sd_csd[0] = sdio_response_get(SDIO_RESPONSE0);
-        sd_csd[1] = sdio_response_get(SDIO_RESPONSE1);
-        sd_csd[2] = sdio_response_get(SDIO_RESPONSE2);
-        sd_csd[3] = sdio_response_get(SDIO_RESPONSE3);
-    }
-    return status;
-}
-
-/*!
-    \brief      configure the clock and the work voltage, and get the card type
-    \param[in]  none
-    \param[out] none
-    \retval     sd_error_enum
-*/
-sd_error_enum sd_power_on(void)
-{
-    sd_error_enum status = SD_OK;
-    uint32_t sdcardtype = SD_STD_CAPACITY, response = 0, count = 0;
-    uint8_t busyflag = 0;
-
-    /* configure the SDIO peripheral */
-    sdio_clock_config(SDIO_SDIOCLKEDGE_RISING, SDIO_CLOCKBYPASS_DISABLE, SDIO_CLOCKPWRSAVE_DISABLE, SD_CLK_DIV_INIT);
-    sdio_bus_mode_set(SDIO_BUSMODE_1BIT);
-    sdio_hardware_clock_disable();
-    sdio_power_state_set(SDIO_POWER_ON);
-    /* enable SDIO_CLK clock output */
-    sdio_clock_enable();
-
-    /* send CMD0(GO_IDLE_STATE) to reset the card */
-    sdio_csm_disable();
-    sdio_command_response_config(SD_CMD_GO_IDLE_STATE, (uint32_t)0x0, SDIO_RESPONSETYPE_NO);
-    sdio_wait_type_set(SDIO_WAITTYPE_NO);
-    /* enable the CSM */
-    sdio_csm_enable();
-
-    /* check if command sent error occurs */
-    status = cmdsent_error_check();
-    if(SD_OK != status) {
-        return status;
-    }
-
-    /* send CMD8(SEND_IF_COND) to get SD memory card interface condition */
-    sdio_csm_disable();
-    sdio_command_response_config(SD_CMD_SEND_IF_COND, SD_CHECK_PATTERN, SDIO_RESPONSETYPE_SHORT);
-    sdio_wait_type_set(SDIO_WAITTYPE_NO);
-    sdio_csm_enable();
-
-    if(SD_OK == r7_error_check()) {
-        /* SD Card 2.0 */
-        cardtype = SDIO_STD_CAPACITY_SD_CARD_V2_0;
-        sdcardtype = SD_HIGH_CAPACITY;
-    }
-
-    while((!busyflag) && (count < SD_MAX_VOLT_VALIDATION)) {
-        /* send CMD55(APP_CMD) to indicate next command is application specific command */
-        sdio_csm_disable();
-        sdio_command_response_config(SD_CMD_APP_CMD, (uint32_t)0x0, SDIO_RESPONSETYPE_SHORT);
-        sdio_wait_type_set(SDIO_WAITTYPE_NO);
-        sdio_csm_enable();
-
-        
-        /* check if some error occurs */
-        /* ignoring return value, SD_ILLEGAL_COMMAND, for v1.x spec SD cards */
-        status = r1_error_check(SD_CMD_APP_CMD);
-        if(SD_OK != status && SD_ILLEGAL_COMMAND != status) {
-            return status;
-        }
-        
-        /* send ACMD41(SD_SEND_OP_COND) to get host capacity support information (HCS) and OCR content */
-        sdio_csm_disable();
-        sdio_command_response_config(SD_APPCMD_SD_SEND_OP_COND, (SD_VOLTAGE_WINDOW | sdcardtype), SDIO_RESPONSETYPE_SHORT);
-        sdio_wait_type_set(SDIO_WAITTYPE_NO);
-        sdio_csm_enable();
-        /* check if some error occurs */
-
-        status = r3_error_check();
-        if(SD_OK != status) {
-            return status;
-        }
-        /* get the response and check card power up status bit(busy) */
-        response = sdio_response_get(SDIO_RESPONSE0);
-        busyflag = (uint8_t)((response >> 31) & (uint32_t)0x01);
-        ++count;
-    }
-    if(count >= SD_MAX_VOLT_VALIDATION) {
-        status = SD_VOLTRANGE_INVALID;
-        return status;
-    }
-    if(response &= SD_HIGH_CAPACITY) {
-        /* SDHC card */
-        cardtype = SDIO_HIGH_CAPACITY_SD_CARD;
-    }
-
-    return status;
-}
-
-/*!
-    \brief      close the power of SDIO
-    \param[in]  none
-    \param[out] none
-    \retval     sd_error_enum
-*/
-sd_error_enum sd_power_off(void)
-{
-    sd_error_enum status = SD_OK;
-    sdio_power_state_set(SDIO_POWER_OFF);
-    return status;
-}
-
-/*!
-    \brief      configure the bus mode
-    \param[in]  busmode: the bus mode
-      \arg        SDIO_BUSMODE_1BIT: 1-bit SDIO card bus mode
-      \arg        SDIO_BUSMODE_4BIT: 4-bit SDIO card bus mode
-      \arg        SDIO_BUSMODE_8BIT: 8-bit SDIO card bus mode (MMC only)
-    \param[out] none
-    \retval     sd_error_enum
-*/
-sd_error_enum sd_bus_mode_config(uint32_t busmode)
-{
-    sd_error_enum status = SD_OK;
-    if(SDIO_MULTIMEDIA_CARD == cardtype) {
-        /* MMC card doesn't support this function */
-        status = SD_FUNCTION_UNSUPPORTED;
-        return status;
-    } else if((SDIO_STD_CAPACITY_SD_CARD_V1_1 == cardtype) || (SDIO_STD_CAPACITY_SD_CARD_V2_0 == cardtype) ||
-              (SDIO_HIGH_CAPACITY_SD_CARD == cardtype)) {
-        if(SDIO_BUSMODE_8BIT == busmode) {
-            /* 8 bit bus mode doesn't support */
-            status = SD_FUNCTION_UNSUPPORTED;
-            return status;
-        } else if(SDIO_BUSMODE_4BIT == busmode) {
-            /* configure SD bus width and the SDIO */
-            status = sd_bus_width_config(SD_BUS_WIDTH_4BIT);
-            if(SD_OK == status) {
-                sdio_clock_config(SDIO_SDIOCLKEDGE_RISING, SDIO_CLOCKBYPASS_DISABLE,
-                                  SDIO_CLOCKPWRSAVE_DISABLE, SD_CLK_DIV_TRANS);
-                sdio_bus_mode_set(busmode);
-                sdio_hardware_clock_disable();
-            }
-        } else if(SDIO_BUSMODE_1BIT == busmode) {
-            /* configure SD bus width and the SDIO */
-            status = sd_bus_width_config(SD_BUS_WIDTH_1BIT);
-            if(SD_OK == status) {
-                sdio_clock_config(SDIO_SDIOCLKEDGE_RISING, SDIO_CLOCKBYPASS_DISABLE,
-                                  SDIO_CLOCKPWRSAVE_DISABLE, SD_CLK_DIV_TRANS);
-                sdio_bus_mode_set(busmode);
-                sdio_hardware_clock_disable();
-            }
-        } else {
-            status = SD_PARAMETER_INVALID;
-        }
-    }
-    return status;
-}
-
-/*!
-    \brief      configure the mode of transmission
-    \param[in]  txmode: transfer mode
-      \arg        SD_DMA_MODE: DMA mode
-      \arg        SD_POLLING_MODE: polling mode
-    \param[out] none
-    \retval     sd_error_enum
-*/
-sd_error_enum sd_transfer_mode_config(uint32_t txmode)
-{
-    sd_error_enum status = SD_OK;
-    /* set the transfer mode */
-    if((SD_DMA_MODE == txmode) || (SD_POLLING_MODE == txmode)) {
-        transmode = txmode;
-    } else {
-        status = SD_PARAMETER_INVALID;
-    }
-    return status;
-}
-
-/*!
-    \brief      read a block data into a buffer from the specified address of a card
-    \param[out] preadbuffer: a pointer that store a block read data
-    \param[in]  readaddr: the read data address
-    \param[in]  blocksize: the data block size
-    \retval     sd_error_enum
-*/
-sd_error_enum sd_block_read(uint32_t *preadbuffer, uint64_t readaddr, uint16_t blocksize, sdio_callback_t callback)
-{
-    /* initialize the variables */
-    sd_error_enum status = SD_OK;
-    uint32_t count = 0, align = 0, datablksize = SDIO_DATABLOCKSIZE_1BYTE, *ptempbuff = preadbuffer;
-
-    if(NULL == preadbuffer) {
-        status = SD_PARAMETER_INVALID;
-        return status;
-    }
-
-    transerror = SD_OK;
-    transend = 0;
-    totalnumber_bytes = 0;
-    /* clear all DSM configuration */
-    sdio_data_config(0, 0, SDIO_DATABLOCKSIZE_1BYTE);
-    sdio_data_transfer_config(SDIO_TRANSMODE_BLOCK, SDIO_TRANSDIRECTION_TOCARD);
-    sdio_dsm_disable();
-    sdio_dma_disable();
-
-    /* check whether the card is locked */
-    if(sdio_response_get(SDIO_RESPONSE0) & SD_CARDSTATE_LOCKED) {
-        status = SD_LOCK_UNLOCK_FAILED;
-        return status;
-    }
-
-    /* blocksize is fixed in 512B for SDHC card */
-    if(SDIO_HIGH_CAPACITY_SD_CARD == cardtype) {
-        blocksize = 512;
-        readaddr /= 512;
-    }
-
-    align = blocksize & (blocksize - 1);
-    if((blocksize > 0) && (blocksize <= 2048) && (0 == align)) {
-        datablksize = sd_datablocksize_get(blocksize);
-        /* send CMD16(SET_BLOCKLEN) to set the block length */
-        sdio_csm_disable();
-        sdio_command_response_config(SD_CMD_SET_BLOCKLEN, (uint32_t)blocksize, SDIO_RESPONSETYPE_SHORT);
-        sdio_wait_type_set(SDIO_WAITTYPE_NO);
-        sdio_csm_enable();
-
-        /* check if some error occurs */
-        status = r1_error_check(SD_CMD_SET_BLOCKLEN);
-        if(SD_OK != status) {
-            return status;
-        }
-    } else {
-        status = SD_PARAMETER_INVALID;
-        return status;
-    }
-
-    stopcondition = 0;
-    totalnumber_bytes = blocksize;
-
-    /* configure SDIO data transmission */
-    sdio_data_config(SD_DATATIMEOUT, totalnumber_bytes, datablksize);
-    sdio_data_transfer_config(SDIO_TRANSMODE_BLOCK, SDIO_TRANSDIRECTION_TOSDIO);
-    sdio_dsm_enable();
-
-    /* send CMD17(READ_SINGLE_BLOCK) to read a block */
-    sdio_csm_disable();
-    sdio_command_response_config(SD_CMD_READ_SINGLE_BLOCK, (uint32_t)readaddr, SDIO_RESPONSETYPE_SHORT);
-    sdio_wait_type_set(SDIO_WAITTYPE_NO);
-    sdio_csm_enable();
-    /* check if some error occurs */
-    status = r1_error_check(SD_CMD_READ_SINGLE_BLOCK);
-    if(SD_OK != status) {
-        return status;
-    }
-
-    if(SD_POLLING_MODE == transmode) {
-        /* polling mode */
-        while(!sdio_flag_get(SDIO_FLAG_DTCRCERR | SDIO_FLAG_DTTMOUT | SDIO_FLAG_RXORE | SDIO_FLAG_DTBLKEND | SDIO_FLAG_STBITE)) {
-            if(RESET != sdio_flag_get(SDIO_FLAG_RFH)) {
-                /* at least 8 words can be read in the FIFO */
-                for(count = 0; count < SD_FIFOHALF_WORDS; count++) {
-                    *(ptempbuff + count) = sdio_data_read();
-                }
-                ptempbuff += SD_FIFOHALF_WORDS;
-            }
-        }
-
-        /* whether some error occurs and return it */
-        if(RESET != sdio_flag_get(SDIO_FLAG_DTCRCERR)) {
-            status = SD_DATA_CRC_ERROR;
-            sdio_flag_clear(SDIO_FLAG_DTCRCERR);
-            return status;
-        } else if(RESET != sdio_flag_get(SDIO_FLAG_DTTMOUT)) {
-            status = SD_DATA_TIMEOUT;
-            sdio_flag_clear(SDIO_FLAG_DTTMOUT);
-            return status;
-        } else if(RESET != sdio_flag_get(SDIO_FLAG_RXORE)) {
-            status = SD_RX_OVERRUN_ERROR;
-            sdio_flag_clear(SDIO_FLAG_RXORE);
-            return status;
-        } else if(RESET != sdio_flag_get(SDIO_FLAG_STBITE)) {
-            status = SD_START_BIT_ERROR;
-            sdio_flag_clear(SDIO_FLAG_STBITE);
-            return status;
-        }
-        while(RESET != sdio_flag_get(SDIO_FLAG_RXDTVAL)) {
-            *ptempbuff = sdio_data_read();
-            ++ptempbuff;
-        }
-        /* clear the SDIO_INTC flags */
-        sdio_flag_clear(SDIO_MASK_INTC_FLAGS);
-    } else if(SD_DMA_MODE == transmode) {
-        /* DMA mode */
-        /* enable the SDIO corresponding interrupts and DMA function */
-        sdio_interrupt_enable(SDIO_INT_DTCRCERR | SDIO_INT_DTTMOUT | SDIO_INT_RXORE | SDIO_INT_DTEND | SDIO_INT_STBITE);
-        sdio_dma_enable();
-        dma_receive_config(preadbuffer, blocksize);
-        uint32_t start = millis();
-        while((RESET == dma_flag_get(DMA1, DMA_CH3, DMA_FLAG_FTF))) {
-            if((uint32_t)(millis() - start) > 1000) {
-                return SD_ERROR;
-            }
-            if (callback)
-            {
-                uint32_t complete = (blocksize - DMA_CHCNT(DMA1, DMA_CH3) * 4);
-                callback(complete);
-            }
-        }
-    } else {
-        status = SD_PARAMETER_INVALID;
-    }
-    return status;
-}
-
-/*!
-    \brief      read multiple blocks data into a buffer from the specified address of a card
-    \param[out] preadbuffer: a pointer that store multiple blocks read data
-    \param[in]  readaddr: the read data address
-    \param[in]  blocksize: the data block size
-    \param[in]  blocksnumber: number of blocks that will be read
-    \retval     sd_error_enum
-*/
-sd_error_enum sd_multiblocks_read(uint32_t *preadbuffer, uint64_t readaddr, uint16_t blocksize, uint32_t blocksnumber, sdio_callback_t callback)
-{
-    /* initialize the variables */
-    sd_error_enum status = SD_OK;
-    uint32_t count = 0, align = 0, datablksize = SDIO_DATABLOCKSIZE_1BYTE, *ptempbuff = preadbuffer;
-    
-    if(NULL == preadbuffer) {
-        status = SD_PARAMETER_INVALID;
-        return status;
-    }
-
-    transerror = SD_OK;
-    transend = 0;
-    totalnumber_bytes = 0;
-    /* clear all DSM configuration */
-    sdio_data_config(0, 0, SDIO_DATABLOCKSIZE_1BYTE);
-    sdio_data_transfer_config(SDIO_TRANSMODE_BLOCK, SDIO_TRANSDIRECTION_TOCARD);
-    sdio_dsm_disable();
-    sdio_dma_disable();
-
-    /* check whether the card is locked */
-    if(sdio_response_get(SDIO_RESPONSE0) & SD_CARDSTATE_LOCKED) {
-        status = SD_LOCK_UNLOCK_FAILED;
-        return status;
-    }
-
-    /* blocksize is fixed in 512B for SDHC card */
-    if(SDIO_HIGH_CAPACITY_SD_CARD == cardtype) {
-        blocksize = 512;
-        readaddr /= 512;
-    }
-
-    align = blocksize & (blocksize - 1);
-    if((blocksize > 0) && (blocksize <= 2048) && (0 == align)) {
-        datablksize = sd_datablocksize_get(blocksize);
-        /* send CMD16(SET_BLOCKLEN) to set the block length */
-        sdio_csm_disable();
-        sdio_command_response_config(SD_CMD_SET_BLOCKLEN, (uint32_t)blocksize, SDIO_RESPONSETYPE_SHORT);
-        sdio_wait_type_set(SDIO_WAITTYPE_NO);
-        sdio_csm_enable();
-
-        /* check if some error occurs */
-        status = r1_error_check(SD_CMD_SET_BLOCKLEN);
-        if(SD_OK != status) {
-            return status;
-        }
-    } else {
-        status = SD_PARAMETER_INVALID;
-        return status;
-    }
-
-    if(blocksnumber >= 1) {
-        if(blocksnumber * blocksize > SD_MAX_DATA_LENGTH) {
-            /* exceeds the maximum length */
-            status = SD_PARAMETER_INVALID;
-            return status;
-        }
-
-        stopcondition = 1;
-        totalnumber_bytes = blocksnumber * blocksize;
-
-        /* configure the SDIO data transmission */
-        sdio_data_config(SD_DATATIMEOUT, totalnumber_bytes, datablksize);
-        sdio_data_transfer_config(SDIO_TRANSMODE_BLOCK, SDIO_TRANSDIRECTION_TOSDIO);
-        sdio_dsm_enable();
-
-        /* send CMD18(READ_MULTIPLE_BLOCK) to read multiple blocks */
-        sdio_csm_disable();
-        sdio_command_response_config(SD_CMD_READ_MULTIPLE_BLOCK, readaddr, SDIO_RESPONSETYPE_SHORT);
-        sdio_wait_type_set(SDIO_WAITTYPE_NO);
-        sdio_csm_enable();
-        /* check if some error occurs */
-        status = r1_error_check(SD_CMD_READ_MULTIPLE_BLOCK);
-        if(SD_OK != status) {
-            return status;
-        }
-
-        if(SD_POLLING_MODE == transmode) {
-            /* polling mode */
-            while(!sdio_flag_get(SDIO_FLAG_DTCRCERR | SDIO_FLAG_DTTMOUT | SDIO_FLAG_RXORE | SDIO_FLAG_DTEND | SDIO_FLAG_STBITE)) {
-                if(RESET != sdio_flag_get(SDIO_FLAG_RFH)) {
-                    /* at least 8 words can be read in the FIFO */
-                    for(count = 0; count < SD_FIFOHALF_WORDS; count++) {
-                        *(ptempbuff + count) = sdio_data_read();
-                    }
-                    ptempbuff += SD_FIFOHALF_WORDS;
-                }
-            }
-
-            /* whether some error occurs and return it */
-            if(RESET != sdio_flag_get(SDIO_FLAG_DTCRCERR)) {
-                status = SD_DATA_CRC_ERROR;
-                sdio_flag_clear(SDIO_FLAG_DTCRCERR);
-                return status;
-            } else if(RESET != sdio_flag_get(SDIO_FLAG_DTTMOUT)) {
-                status = SD_DATA_TIMEOUT;
-                sdio_flag_clear(SDIO_FLAG_DTTMOUT);
-                return status;
-            } else if(RESET != sdio_flag_get(SDIO_FLAG_RXORE)) {
-                status = SD_RX_OVERRUN_ERROR;
-                sdio_flag_clear(SDIO_FLAG_RXORE);
-                return status;
-            } else if(RESET != sdio_flag_get(SDIO_FLAG_STBITE)) {
-                status = SD_START_BIT_ERROR;
-                sdio_flag_clear(SDIO_FLAG_STBITE);
-                return status;
-            }
-            while(RESET != sdio_flag_get(SDIO_FLAG_RXDTVAL)) {
-                *ptempbuff = sdio_data_read();
-                ++ptempbuff;
-            }
-
-            if(RESET != sdio_flag_get(SDIO_FLAG_DTEND)) {
-                if((SDIO_STD_CAPACITY_SD_CARD_V1_1 == cardtype) || (SDIO_STD_CAPACITY_SD_CARD_V2_0 == cardtype) ||
-                        (SDIO_HIGH_CAPACITY_SD_CARD == cardtype)) {
-                    /* send CMD12(STOP_TRANSMISSION) to stop transmission */
-                    sdio_csm_disable();
-                    sdio_command_response_config(SD_CMD_STOP_TRANSMISSION, (uint32_t)0x0, SDIO_RESPONSETYPE_SHORT);
-                    sdio_wait_type_set(SDIO_WAITTYPE_NO);
-                    sdio_csm_enable();
-                    /* check if some error occurs */
-                    status = r1_error_check(SD_CMD_STOP_TRANSMISSION);
-                    if(SD_OK != status) {
-                        return status;
-                    }
-                }
-            }
-            sdio_flag_clear(SDIO_MASK_INTC_FLAGS);
-        } else if(SD_DMA_MODE == transmode) {
-            /* DMA mode */
-            /* enable the SDIO corresponding interrupts and DMA function */
-            sdio_interrupt_enable(SDIO_INT_DTCRCERR | SDIO_INT_DTTMOUT | SDIO_INT_RXORE | SDIO_INT_DTEND | SDIO_INT_STBITE);
-            sdio_dma_enable();
-            dma_receive_config(preadbuffer, totalnumber_bytes);
-
-            uint32_t start = millis();
-            while((RESET == dma_flag_get(DMA1, DMA_CH3, DMA_FLAG_FTF))) {
-                if((uint32_t)(millis() - start) > 1000) {
-                    return SD_ERROR;
-                }
-                if (callback)
-                {
-                    uint32_t complete = (totalnumber_bytes - DMA_CHCNT(DMA1, DMA_CH3) * 4);
-                    callback(complete);
-                }
-            }
-            while((0 == transend) && (SD_OK == transerror)) {
-                if (callback)
-                {
-                    callback(totalnumber_bytes);
-                }
-            }
-            if(SD_OK != transerror) {
-                return transerror;
-            }
-        } else {
-            status = SD_PARAMETER_INVALID;
-        }
-    }
-    return status;
-}
-
-/*!
-    \brief      write a block data to the specified address of a card
-    \param[in]  pwritebuffer: a pointer that store a block data to be transferred
-    \param[in]  writeaddr: the read data address
-    \param[in]  blocksize: the data block size
-    \param[out] none
-    \retval     sd_error_enum
-*/
-sd_error_enum sd_block_write(uint32_t *pwritebuffer, uint64_t writeaddr, uint16_t blocksize, sdio_callback_t callback)
-{
-    /* initialize the variables */
-    sd_error_enum status = SD_OK;
-    uint8_t cardstate = 0;
-    uint32_t count = 0, align = 0, datablksize = SDIO_DATABLOCKSIZE_1BYTE, *ptempbuff = pwritebuffer;
-    uint32_t transbytes = 0, restwords = 0, response = 0;
-    
-    if(NULL == pwritebuffer) {
-        status = SD_PARAMETER_INVALID;
-        return status;
-    }
-
-    transerror = SD_OK;
-    transend = 0;
-    totalnumber_bytes = 0;
-    /* clear all DSM configuration */
-    sdio_data_config(0, 0, SDIO_DATABLOCKSIZE_1BYTE);
-    sdio_data_transfer_config(SDIO_TRANSMODE_BLOCK, SDIO_TRANSDIRECTION_TOCARD);
-    sdio_dsm_disable();
-    sdio_dma_disable();
-
-    /* check whether the card is locked */
-    if(sdio_response_get(SDIO_RESPONSE0) & SD_CARDSTATE_LOCKED) {
-        status = SD_LOCK_UNLOCK_FAILED;
-        return status;
-    }
-
-    /* blocksize is fixed in 512B for SDHC card */
-    if(SDIO_HIGH_CAPACITY_SD_CARD == cardtype) {
-        blocksize = 512;
-        writeaddr /= 512;
-    }
-
-    align = blocksize & (blocksize - 1);
-    if((blocksize > 0) && (blocksize <= 2048) && (0 == align)) {
-        datablksize = sd_datablocksize_get(blocksize);
-        /* send CMD16(SET_BLOCKLEN) to set the block length */
-        sdio_csm_disable();
-        sdio_command_response_config(SD_CMD_SET_BLOCKLEN, (uint32_t)blocksize, SDIO_RESPONSETYPE_SHORT);
-        sdio_wait_type_set(SDIO_WAITTYPE_NO);
-        sdio_csm_enable();
-
-        /* check if some error occurs */
-        status = r1_error_check(SD_CMD_SET_BLOCKLEN);
-        if(SD_OK != status) {
-            return status;
-        }
-    } else {
-        status = SD_PARAMETER_INVALID;
-        return status;
-    }
-
-    /* send CMD13(SEND_STATUS), addressed card sends its status registers */
-    sdio_csm_disable();
-    sdio_command_response_config(SD_CMD_SEND_STATUS, (uint32_t)sd_rca << SD_RCA_SHIFT, SDIO_RESPONSETYPE_SHORT);
-    sdio_wait_type_set(SDIO_WAITTYPE_NO);
-    sdio_csm_enable();
-    /* check if some error occurs */
-    status = r1_error_check(SD_CMD_SEND_STATUS);
-    if(SD_OK != status) {
-        return status;
-    }
-
-    response = sdio_response_get(SDIO_RESPONSE0);
-    
-    uint32_t start = millis();
-    while((0 == (response & SD_R1_READY_FOR_DATA))) {
-        /* continue to send CMD13 to polling the state of card until buffer empty or timeout */
-        if((uint32_t)(millis() - start) > 1000) {
-            return SD_ERROR;
-        }
-
-        if (callback)
-        {
-            callback(0);
-        }
-
-        /* send CMD13(SEND_STATUS), addressed card sends its status registers */
-        sdio_csm_disable();
-        sdio_command_response_config(SD_CMD_SEND_STATUS, (uint32_t)sd_rca << SD_RCA_SHIFT, SDIO_RESPONSETYPE_SHORT);
-        sdio_wait_type_set(SDIO_WAITTYPE_NO);
-        sdio_csm_enable();
-        /* check if some error occurs */
-        status = r1_error_check(SD_CMD_SEND_STATUS);
-        if(SD_OK != status) {
-            return status;
-        }
-        response = sdio_response_get(SDIO_RESPONSE0);
-    }
-
-    /* send CMD24(WRITE_BLOCK) to write a block */
-    sdio_csm_disable();
-    sdio_command_response_config(SD_CMD_WRITE_BLOCK, writeaddr, SDIO_RESPONSETYPE_SHORT);
-    sdio_wait_type_set(SDIO_WAITTYPE_NO);
-    sdio_csm_enable();
-    /* check if some error occurs */
-    status = r1_error_check(SD_CMD_WRITE_BLOCK);
-    if(SD_OK != status) {
-        return status;
-    }
-
-    stopcondition = 0;
-    totalnumber_bytes = blocksize;
-
-    /* configure the SDIO data transmission */
-    sdio_data_config(SD_DATATIMEOUT, totalnumber_bytes, datablksize);
-    sdio_data_transfer_config(SDIO_TRANSMODE_BLOCK, SDIO_TRANSDIRECTION_TOCARD);
-    sdio_dsm_enable();
-
-    if(SD_POLLING_MODE == transmode) {
-        /* polling mode */
-        while(!sdio_flag_get(SDIO_FLAG_DTCRCERR | SDIO_FLAG_DTTMOUT | SDIO_FLAG_TXURE | SDIO_FLAG_DTBLKEND | SDIO_FLAG_STBITE)) {
-            if(RESET != sdio_flag_get(SDIO_FLAG_TFH)) {
-                /* at least 8 words can be written into the FIFO */
-                if((totalnumber_bytes - transbytes) < SD_FIFOHALF_BYTES) {
-                    restwords = (totalnumber_bytes - transbytes) / 4 + (((totalnumber_bytes - transbytes) % 4 == 0) ? 0 : 1);
-                    for(count = 0; count < restwords; count++) {
-                        sdio_data_write(*ptempbuff);
-                        ++ptempbuff;
-                        transbytes += 4;
-                    }
-                } else {
-                    for(count = 0; count < SD_FIFOHALF_WORDS; count++) {
-                        sdio_data_write(*(ptempbuff + count));
-                    }
-                    /* 8 words(32 bytes) has been transferred */
-                    ptempbuff += SD_FIFOHALF_WORDS;
-                    transbytes += SD_FIFOHALF_BYTES;
-                }
-            }
-        }
-
-        /* whether some error occurs and return it */
-        if(RESET != sdio_flag_get(SDIO_FLAG_DTCRCERR)) {
-            status = SD_DATA_CRC_ERROR;
-            sdio_flag_clear(SDIO_FLAG_DTCRCERR);
-            return status;
-        } else if(RESET != sdio_flag_get(SDIO_FLAG_DTTMOUT)) {
-            status = SD_DATA_TIMEOUT;
-            sdio_flag_clear(SDIO_FLAG_DTTMOUT);
-            return status;
-        } else if(RESET != sdio_flag_get(SDIO_FLAG_TXURE)) {
-            status = SD_TX_UNDERRUN_ERROR;
-            sdio_flag_clear(SDIO_FLAG_TXURE);
-            return status;
-        } else if(RESET != sdio_flag_get(SDIO_FLAG_STBITE)) {
-            status = SD_START_BIT_ERROR;
-            sdio_flag_clear(SDIO_FLAG_STBITE);
-            return status;
-        }
-    } else if(SD_DMA_MODE == transmode) {
-        /* DMA mode */
-        /* enable the SDIO corresponding interrupts and DMA */
-        sdio_interrupt_enable(SDIO_INT_DTCRCERR | SDIO_INT_DTTMOUT | SDIO_INT_TXURE | SDIO_INT_DTEND | SDIO_INT_STBITE);
-        dma_transfer_config(pwritebuffer, blocksize);
-        sdio_dma_enable();
-
-        uint32_t start = millis();
-        while((RESET == dma_flag_get(DMA1, DMA_CH3, DMA_FLAG_FTF))) {
-            if((uint32_t)(millis() - start) > 1000) {
-                return SD_ERROR;
-            }
-            if (callback)
-            {
-                uint32_t complete = (blocksize - DMA_CHCNT(DMA1, DMA_CH3) * 4);
-                callback(complete);
-            }
-        }
-        while((0 == transend) && (SD_OK == transerror)) {
-            if (callback)
-            {
-                callback(blocksize);
-            }
-        }
-
-        if(SD_OK != transerror) {
-            return transerror;
-        }
-    } else {
-        status = SD_PARAMETER_INVALID;
-        return status;
-    }
-
-    /* clear the SDIO_INTC flags */
-    sdio_flag_clear(SDIO_MASK_INTC_FLAGS);
-    /* get the card state and wait the card is out of programming and receiving state */
-    status = sd_card_state_get(&cardstate);
-    while((SD_OK == status) && ((SD_CARDSTATE_PROGRAMMING == cardstate) || (SD_CARDSTATE_RECEIVING == cardstate))) {
-        if (callback)
-        {
-            callback(blocksize);
-        }
-        status = sd_card_state_get(&cardstate);
-    }
-    return status;
-}
-
-/*!
-    \brief      write multiple blocks data to the specified address of a card
-    \param[in]  pwritebuffer: a pointer that store multiple blocks data to be transferred
-    \param[in]  writeaddr: the read data address
-    \param[in]  blocksize: the data block size
-    \param[in]  blocksnumber: number of blocks that will be written
-    \param[out] none
-    \retval     sd_error_enum
-*/
-sd_error_enum sd_multiblocks_write(uint32_t *pwritebuffer, uint64_t writeaddr, uint16_t blocksize, uint32_t blocksnumber, sdio_callback_t callback)
-{
-    /* initialize the variables */
-    sd_error_enum status = SD_OK;
-    uint8_t cardstate = 0;
-    uint32_t count = 0, align = 0, datablksize = SDIO_DATABLOCKSIZE_1BYTE, *ptempbuff = pwritebuffer;
-    uint32_t transbytes = 0, restwords = 0;
-    
-    if(NULL == pwritebuffer) {
-        status = SD_PARAMETER_INVALID;
-        return status;
-    }
-
-    transerror = SD_OK;
-    transend = 0;
-    totalnumber_bytes = 0;
-    /* clear all DSM configuration */
-    sdio_data_config(0, 0, SDIO_DATABLOCKSIZE_1BYTE);
-    sdio_data_transfer_config(SDIO_TRANSMODE_BLOCK, SDIO_TRANSDIRECTION_TOCARD);
-    sdio_dsm_disable();
-    sdio_dma_disable();
-
-    /* check whether the card is locked */
-    if(sdio_response_get(SDIO_RESPONSE0) & SD_CARDSTATE_LOCKED) {
-        status = SD_LOCK_UNLOCK_FAILED;
-        return status;
-    }
-
-    /* blocksize is fixed in 512B for SDHC card */
-    if(SDIO_HIGH_CAPACITY_SD_CARD == cardtype) {
-        blocksize = 512;
-        writeaddr /= 512;
-    }
-
-    align = blocksize & (blocksize - 1);
-    if((blocksize > 0) && (blocksize <= 2048) && (0 == align)) {
-        datablksize = sd_datablocksize_get(blocksize);
-        /* send CMD16(SET_BLOCKLEN) to set the block length */
-        sdio_csm_disable();
-        sdio_command_response_config(SD_CMD_SET_BLOCKLEN, (uint32_t)blocksize, SDIO_RESPONSETYPE_SHORT);
-        sdio_wait_type_set(SDIO_WAITTYPE_NO);
-        sdio_csm_enable();
-
-        /* check if some error occurs */
-        status = r1_error_check(SD_CMD_SET_BLOCKLEN);
-        if(SD_OK != status) {
-            return status;
-        }
-    } else {
-        status = SD_PARAMETER_INVALID;
-        return status;
-    }
-
-    /* send CMD13(SEND_STATUS), addressed card sends its status registers */
-    sdio_csm_disable();
-    sdio_command_response_config(SD_CMD_SEND_STATUS, (uint32_t)sd_rca << SD_RCA_SHIFT, SDIO_RESPONSETYPE_SHORT);
-    sdio_wait_type_set(SDIO_WAITTYPE_NO);
-    sdio_csm_enable();
-    /* check if some error occurs */
-    status = r1_error_check(SD_CMD_SEND_STATUS);
-    if(SD_OK != status) {
-        return status;
-    }
-
-    if(blocksnumber >= 1) {
-        if(blocksnumber * blocksize > SD_MAX_DATA_LENGTH) {
-            status = SD_PARAMETER_INVALID;
-            return status;
-        }
-
-        if((SDIO_STD_CAPACITY_SD_CARD_V1_1 == cardtype) || (SDIO_STD_CAPACITY_SD_CARD_V2_0 == cardtype) ||
-                (SDIO_HIGH_CAPACITY_SD_CARD == cardtype)) {
-            /* send CMD55(APP_CMD) to indicate next command is application specific command */
-            sdio_csm_disable();
-            sdio_command_response_config(SD_CMD_APP_CMD, (uint32_t)sd_rca << SD_RCA_SHIFT, SDIO_RESPONSETYPE_SHORT);
-            sdio_wait_type_set(SDIO_WAITTYPE_NO);
-            sdio_csm_enable();
-            /* check if some error occurs */
-            status = r1_error_check(SD_CMD_APP_CMD);
-            if(SD_OK != status) {
-                return status;
-            }
-
-            /* send ACMD23(SET_WR_BLK_ERASE_COUNT) to set the number of write blocks to be preerased before writing */
-            sdio_csm_disable();
-            sdio_command_response_config(SD_APPCMD_SET_WR_BLK_ERASE_COUNT, blocksnumber, SDIO_RESPONSETYPE_SHORT);
-            sdio_wait_type_set(SDIO_WAITTYPE_NO);
-            sdio_csm_enable();
-            /* check if some error occurs */
-            status = r1_error_check(SD_APPCMD_SET_WR_BLK_ERASE_COUNT);
-            if(SD_OK != status) {
-                return status;
-            }
-        }
-        /* send CMD25(WRITE_MULTIPLE_BLOCK) to continuously write blocks of data */
-        sdio_csm_disable();
-        sdio_command_response_config(SD_CMD_WRITE_MULTIPLE_BLOCK, writeaddr, SDIO_RESPONSETYPE_SHORT);
-        sdio_wait_type_set(SDIO_WAITTYPE_NO);
-        sdio_csm_enable();
-        /* check if some error occurs */
-        status = r1_error_check(SD_CMD_WRITE_MULTIPLE_BLOCK);
-        if(SD_OK != status) {
-            return status;
-        }
-
-        stopcondition = 1;
-        totalnumber_bytes = blocksnumber * blocksize;
-
-        /* configure the SDIO data transmission */
-        sdio_data_config(SD_DATATIMEOUT, totalnumber_bytes, datablksize);
-        sdio_data_transfer_config(SDIO_TRANSMODE_BLOCK, SDIO_TRANSDIRECTION_TOCARD);
-        sdio_dsm_enable();
-
-        if(SD_POLLING_MODE == transmode) {
-            /* polling mode */
-            while(!sdio_flag_get(SDIO_FLAG_DTCRCERR | SDIO_FLAG_DTTMOUT | SDIO_FLAG_TXURE | SDIO_FLAG_DTEND | SDIO_FLAG_STBITE)) {
-                if(RESET != sdio_flag_get(SDIO_FLAG_TFH)) {
-                    /* at least 8 words can be written into the FIFO */
-                    if(!((totalnumber_bytes - transbytes) < SD_FIFOHALF_BYTES)) {
-                        for(count = 0; count < SD_FIFOHALF_WORDS; count++) {
-                            sdio_data_write(*(ptempbuff + count));
-                        }
-                        /* 8 words(32 bytes) has been transferred */
-                        ptempbuff += SD_FIFOHALF_WORDS;
-                        transbytes += SD_FIFOHALF_BYTES;
-                    } else {
-                        restwords = (totalnumber_bytes - transbytes) / 4 + (((totalnumber_bytes - transbytes) % 4 == 0) ? 0 : 1);
-                        for(count = 0; count < restwords; count++) {
-                            sdio_data_write(*ptempbuff);
-                            ++ptempbuff;
-                            transbytes += 4;
-                        }
-                    }
-                }
-            }
-
-            /* whether some error occurs and return it */
-            if(RESET != sdio_flag_get(SDIO_FLAG_DTCRCERR)) {
-                status = SD_DATA_CRC_ERROR;
-                sdio_flag_clear(SDIO_FLAG_DTCRCERR);
-                return status;
-            } else if(RESET != sdio_flag_get(SDIO_FLAG_DTTMOUT)) {
-                status = SD_DATA_TIMEOUT;
-                sdio_flag_clear(SDIO_FLAG_DTTMOUT);
-                return status;
-            } else if(RESET != sdio_flag_get(SDIO_FLAG_TXURE)) {
-                status = SD_TX_UNDERRUN_ERROR;
-                sdio_flag_clear(SDIO_FLAG_TXURE);
-                return status;
-            } else if(RESET != sdio_flag_get(SDIO_FLAG_STBITE)) {
-                status = SD_START_BIT_ERROR;
-                sdio_flag_clear(SDIO_FLAG_STBITE);
-                return status;
-            }
-
-            if(RESET != sdio_flag_get(SDIO_FLAG_DTEND)) {
-                if((SDIO_STD_CAPACITY_SD_CARD_V1_1 == cardtype) || (SDIO_STD_CAPACITY_SD_CARD_V2_0 == cardtype) ||
-                        (SDIO_HIGH_CAPACITY_SD_CARD == cardtype)) {
-                    /* send CMD12(STOP_TRANSMISSION) to stop transmission */
-                    sdio_csm_disable();
-                    sdio_command_response_config(SD_CMD_STOP_TRANSMISSION, (uint32_t)0x0, SDIO_RESPONSETYPE_SHORT);
-                    sdio_wait_type_set(SDIO_WAITTYPE_NO);
-                    sdio_csm_enable();
-                    /* check if some error occurs */
-                    status = r1_error_check(SD_CMD_STOP_TRANSMISSION);
-                    if(SD_OK != status) {
-                        return status;
-                    }
-                }
-            }
-            sdio_flag_clear(SDIO_MASK_INTC_FLAGS);
-        } else if(SD_DMA_MODE == transmode) {
-            /* DMA mode */
-            /* enable SDIO corresponding interrupts and DMA */
-            sdio_interrupt_enable(SDIO_INT_DTCRCERR | SDIO_INT_DTTMOUT | SDIO_INT_TXURE | SDIO_INT_DTEND | SDIO_INT_STBITE);
-            sdio_dma_enable();
-            dma_transfer_config(pwritebuffer, totalnumber_bytes);
-
-            uint32_t start = millis();
-            while((RESET == dma_flag_get(DMA1, DMA_CH3, DMA_FLAG_FTF))) {
-                if((uint32_t)(millis() - start) > 1000) {
-                    return SD_ERROR;
-                }
-                if (callback)
-                {
-                    uint32_t complete = (totalnumber_bytes - DMA_CHCNT(DMA1, DMA_CH3) * 4);
-                    callback(complete);
-                }
-            }
-            while((0 == transend) && (SD_OK == transerror)) {
-                if (callback)
-                {
-                    callback(totalnumber_bytes);
-                }
-            }
-            if(SD_OK != transerror) {
-                return transerror;
-            }
-        } else {
-            status = SD_PARAMETER_INVALID;
-            return status;
-        }
-    }
-
-    /* clear the SDIO_INTC flags */
-    sdio_flag_clear(SDIO_MASK_INTC_FLAGS);
-    /* get the card state and wait the card is out of programming and receiving state */
-    status = sd_card_state_get(&cardstate);
-    while((SD_OK == status) && ((SD_CARDSTATE_PROGRAMMING == cardstate) || (SD_CARDSTATE_RECEIVING == cardstate))) {
-        if (callback)
-        {
-            callback(totalnumber_bytes);
-        }
-        status = sd_card_state_get(&cardstate);
-    }
-    return status;
-}
-
-/*!
-    \brief      erase a continuous area of a card
-    \param[in]  startaddr: the start address
-    \param[in]  endaddr: the end address
-    \param[out] none
-    \retval     sd_error_enum
-*/
-sd_error_enum sd_erase(uint64_t startaddr, uint64_t endaddr)
-{
-    /* initialize the variables */
-    sd_error_enum status = SD_OK;
-    uint32_t count = 0, clkdiv = 0;
-    __IO uint32_t delay = 0;
-    uint8_t cardstate = 0, tempbyte = 0;
-    uint16_t tempccc = 0;
-
-    /* get the card command classes from CSD */
-    tempbyte = (uint8_t)((sd_csd[1] & SD_MASK_24_31BITS) >> 24);
-    tempccc = (uint16_t)((uint16_t)tempbyte << 4);
-    tempbyte = (uint8_t)((sd_csd[1] & SD_MASK_16_23BITS) >> 16);
-    tempccc |= (uint16_t)((uint16_t)(tempbyte & 0xF0) >> 4);
-    if(0 == (tempccc & SD_CCC_ERASE)) {
-        /* don't support the erase command */
-        status = SD_FUNCTION_UNSUPPORTED;
-        return status;
-    }
-    clkdiv = (SDIO_CLKCTL & SDIO_CLKCTL_DIV);
-    clkdiv += ((SDIO_CLKCTL & SDIO_CLKCTL_DIV8) >> 31) * 256;
-    clkdiv += 2;
-    delay = 120000 / clkdiv;
-
-    /* check whether the card is locked */
-    if(sdio_response_get(SDIO_RESPONSE0) & SD_CARDSTATE_LOCKED) {
-        status = SD_LOCK_UNLOCK_FAILED;
-        return(status);
-    }
-
-    /* blocksize is fixed in 512B for SDHC card */
-    if(SDIO_HIGH_CAPACITY_SD_CARD == cardtype) {
-        startaddr /= 512;
-        endaddr /= 512;
-    }
-
-    if((SDIO_STD_CAPACITY_SD_CARD_V1_1 == cardtype) || (SDIO_STD_CAPACITY_SD_CARD_V2_0 == cardtype) ||
-            (SDIO_HIGH_CAPACITY_SD_CARD == cardtype)) {
-        /* send CMD32(ERASE_WR_BLK_START) to set the address of the first write block to be erased */
-        sdio_csm_disable();
-        sdio_command_response_config(SD_CMD_ERASE_WR_BLK_START, startaddr, SDIO_RESPONSETYPE_SHORT);
-        sdio_wait_type_set(SDIO_WAITTYPE_NO);
-        sdio_csm_enable();
-        /* check if some error occurs */
-        status = r1_error_check(SD_CMD_ERASE_WR_BLK_START);
-        if(SD_OK != status) {
-            return status;
-        }
-
-        /* send CMD33(ERASE_WR_BLK_END) to set the address of the last write block of the continuous range to be erased */
-        sdio_csm_disable();
-        sdio_command_response_config(SD_CMD_ERASE_WR_BLK_END, endaddr, SDIO_RESPONSETYPE_SHORT);
-        sdio_wait_type_set(SDIO_WAITTYPE_NO);
-        sdio_csm_enable();
-        /* check if some error occurs */
-        status = r1_error_check(SD_CMD_ERASE_WR_BLK_END);
-        if(SD_OK != status) {
-            return status;
-        }
-    }
-
-    /* send CMD38(ERASE) to set the address of the first write block to be erased */
-    sdio_csm_disable();
-    sdio_command_response_config(SD_CMD_ERASE, (uint32_t)0x0, SDIO_RESPONSETYPE_SHORT);
-    sdio_wait_type_set(SDIO_WAITTYPE_NO);
-    sdio_csm_enable();
-    /* check if some error occurs */
-    status = r1_error_check(SD_CMD_ERASE);
-    if(SD_OK != status) {
-        return status;
-    }
-    /* loop until the counter is reach to the calculated time */
-    for(count = 0; count < delay; count++) {
-    }
-    /* get the card state and wait the card is out of programming and receiving state */
-    status = sd_card_state_get(&cardstate);
-    while((SD_OK == status) && ((SD_CARDSTATE_PROGRAMMING == cardstate) || (SD_CARDSTATE_RECEIVING == cardstate))) {
-        status = sd_card_state_get(&cardstate);
-    }
-    return status;
-}
-
-/*!
-    \brief      process all the interrupts which the corresponding flags are set
-    \param[in]  none
-    \param[out] none
-    \retval     sd_error_enum
-*/
-sd_error_enum sd_interrupts_process(void)
-{
-    transerror = SD_OK;
-    if(RESET != sdio_interrupt_flag_get(SDIO_INT_FLAG_DTEND)) {
-        /* send CMD12 to stop data transfer in multiple blocks operation */
-        if(1 == stopcondition) {
-            transerror = sd_transfer_stop();
-        } else {
-            transerror = SD_OK;
-        }
-        sdio_interrupt_flag_clear(SDIO_INT_DTEND);
-        /* disable all the interrupts */
-        sdio_interrupt_disable(SDIO_INT_DTCRCERR | SDIO_INT_DTTMOUT | SDIO_INT_DTEND | SDIO_INT_STBITE |
-                               SDIO_INT_TFH | SDIO_INT_RFH | SDIO_INT_TXURE | SDIO_INT_RXORE);
-        transend = 1;
-        number_bytes = 0;
-        return transerror;
-    }
-
-    if(RESET != sdio_interrupt_flag_get(SDIO_INT_FLAG_DTCRCERR)) {
-        sdio_interrupt_flag_clear(SDIO_INT_DTCRCERR);
-        /* disable all the interrupts */
-        sdio_interrupt_disable(SDIO_INT_DTCRCERR | SDIO_INT_DTTMOUT | SDIO_INT_DTEND | SDIO_INT_STBITE |
-                               SDIO_INT_TFH | SDIO_INT_RFH | SDIO_INT_TXURE | SDIO_INT_RXORE);
-        number_bytes = 0;
-        transerror = SD_DATA_CRC_ERROR;
-        return transerror;
-    }
-
-    if(RESET != sdio_interrupt_flag_get(SDIO_INT_FLAG_DTTMOUT)) {
-        sdio_interrupt_flag_clear(SDIO_INT_DTTMOUT);
-        /* disable all the interrupts */
-        sdio_interrupt_disable(SDIO_INT_DTCRCERR | SDIO_INT_DTTMOUT | SDIO_INT_DTEND | SDIO_INT_STBITE |
-                               SDIO_INT_TFH | SDIO_INT_RFH | SDIO_INT_TXURE | SDIO_INT_RXORE);
-        number_bytes = 0;
-        transerror = SD_DATA_TIMEOUT;
-        return transerror;
-    }
-
-    if(RESET != sdio_interrupt_flag_get(SDIO_INT_FLAG_STBITE)) {
-        sdio_interrupt_flag_clear(SDIO_INT_STBITE);
-        /* disable all the interrupts */
-        sdio_interrupt_disable(SDIO_INT_DTCRCERR | SDIO_INT_DTTMOUT | SDIO_INT_DTEND | SDIO_INT_STBITE |
-                               SDIO_INT_TFH | SDIO_INT_RFH | SDIO_INT_TXURE | SDIO_INT_RXORE);
-        number_bytes = 0;
-        transerror = SD_START_BIT_ERROR;
-        return transerror;
-    }
-
-    if(RESET != sdio_interrupt_flag_get(SDIO_INT_FLAG_TXURE)) {
-        sdio_interrupt_flag_clear(SDIO_INT_TXURE);
-        /* disable all the interrupts */
-        sdio_interrupt_disable(SDIO_INT_DTCRCERR | SDIO_INT_DTTMOUT | SDIO_INT_DTEND | SDIO_INT_STBITE |
-                               SDIO_INT_TFH | SDIO_INT_RFH | SDIO_INT_TXURE | SDIO_INT_RXORE);
-        number_bytes = 0;
-        transerror = SD_TX_UNDERRUN_ERROR;
-        return transerror;
-    }
-
-    if(RESET != sdio_interrupt_flag_get(SDIO_INT_FLAG_RXORE)) {
-        sdio_interrupt_flag_clear(SDIO_INT_RXORE);
-        /* disable all the interrupts */
-        sdio_interrupt_disable(SDIO_INT_DTCRCERR | SDIO_INT_DTTMOUT | SDIO_INT_DTEND | SDIO_INT_STBITE |
-                               SDIO_INT_TFH | SDIO_INT_RFH | SDIO_INT_TXURE | SDIO_INT_RXORE);
-        number_bytes = 0;
-        transerror = SD_RX_OVERRUN_ERROR;
-        return transerror;
-    }
-    return transerror;
-}
-
-/*!
-    \brief      select or deselect a card
-    \param[in]  cardrca: the RCA of a card
-    \param[out] none
-    \retval     sd_error_enum
-*/
-sd_error_enum sd_card_select_deselect(uint16_t cardrca)
-{
-    sd_error_enum status = SD_OK;
-    /* send CMD7(SELECT/DESELECT_CARD) to select or deselect the card */
-    sdio_csm_disable();
-    sdio_command_response_config(SD_CMD_SELECT_DESELECT_CARD, (uint32_t)(cardrca << SD_RCA_SHIFT), SDIO_RESPONSETYPE_SHORT);
-    sdio_wait_type_set(SDIO_WAITTYPE_NO);
-    sdio_csm_enable();
-
-    status = r1_error_check(SD_CMD_SELECT_DESELECT_CARD);
-    return status;
-}
-
-/*!
-    \brief      get the card status
-    \param[in]  none
-    \param[out] pcardstatus: a pointer that store card status
-    \retval     sd_error_enum
-*/
-sd_error_enum sd_cardstatus_get(uint32_t *pcardstatus)
-{
-    sd_error_enum status = SD_OK;
-    if(NULL == pcardstatus) {
-        status = SD_PARAMETER_INVALID;
-        return status;
-    }
-
-    /* send CMD13(SEND_STATUS), addressed card sends its status register */
-    sdio_csm_disable();
-    sdio_command_response_config(SD_CMD_SEND_STATUS, (uint32_t)sd_rca << SD_RCA_SHIFT, SDIO_RESPONSETYPE_SHORT);
-    sdio_wait_type_set(SDIO_WAITTYPE_NO);
-    sdio_csm_enable();
-    /* check if some error occurs */
-    status = r1_error_check(SD_CMD_SEND_STATUS);
-    if(SD_OK != status) {
-        return status;
-    }
-
-    *pcardstatus = sdio_response_get(SDIO_RESPONSE0);
-    return status;
-}
-
-/*!
-    \brief      get the SD card status
-    \param[in]  none
-    \param[out] psdstatus: a pointer that store SD card status
-    \retval     sd_error_enum
-*/
-sd_error_enum sd_sdstatus_get(uint32_t *psdstatus)
-{
-    sd_error_enum status = SD_OK;
-    uint32_t count = 0;
-
-    /* check whether the card is locked */
-    if(sdio_response_get(SDIO_RESPONSE0) & SD_CARDSTATE_LOCKED) {
-        status = SD_LOCK_UNLOCK_FAILED;
-        return(status);
-    }
-
-    /* send CMD16(SET_BLOCKLEN) to set the block length */
-    sdio_csm_disable();
-    sdio_command_response_config(SD_CMD_SET_BLOCKLEN, (uint32_t)64, SDIO_RESPONSETYPE_SHORT);
-    sdio_wait_type_set(SDIO_WAITTYPE_NO);
-    sdio_csm_enable();
-    /* check if some error occurs */
-    status = r1_error_check(SD_CMD_SET_BLOCKLEN);
-    if(SD_OK != status) {
-        return status;
-    }
-
-    /* send CMD55(APP_CMD) to indicate next command is application specific command */
-    sdio_csm_disable();
-    sdio_command_response_config(SD_CMD_APP_CMD, (uint32_t)sd_rca << SD_RCA_SHIFT, SDIO_RESPONSETYPE_SHORT);
-    sdio_wait_type_set(SDIO_WAITTYPE_NO);
-    sdio_csm_enable();
-    /* check if some error occurs */
-    status = r1_error_check(SD_CMD_APP_CMD);
-    if(SD_OK != status) {
-        return status;
-    }
-
-    /* configure the SDIO data transmission */
-    sdio_data_config(SD_DATATIMEOUT, (uint32_t)64, SDIO_DATABLOCKSIZE_64BYTES);
-    sdio_data_transfer_config(SDIO_TRANSMODE_BLOCK, SDIO_TRANSDIRECTION_TOSDIO);
-    sdio_dsm_enable();
-
-    /* send ACMD13(SD_STATUS) to get the SD status */
-    sdio_csm_disable();
-    sdio_command_response_config(SD_APPCMD_SD_STATUS, (uint32_t)0x0, SDIO_RESPONSETYPE_SHORT);
-    sdio_wait_type_set(SDIO_WAITTYPE_NO);
-    sdio_csm_enable();
-    /* check if some error occurs */
-    status = r1_error_check(SD_APPCMD_SD_STATUS);
-    if(SD_OK != status) {
-        return status;
-    }
-
-    while(!sdio_flag_get(SDIO_FLAG_DTCRCERR | SDIO_FLAG_DTTMOUT | SDIO_FLAG_RXORE | SDIO_FLAG_DTBLKEND | SDIO_FLAG_STBITE)) {
-        if(RESET != sdio_flag_get(SDIO_FLAG_RFH)) {
-            for(count = 0; count < SD_FIFOHALF_WORDS; count++) {
-                *(psdstatus + count) = sdio_data_read();
-            }
-            psdstatus += SD_FIFOHALF_WORDS;
-        }
-    }
-
-    /* whether some error occurs and return it */
-    if(RESET != sdio_flag_get(SDIO_FLAG_DTCRCERR)) {
-        status = SD_DATA_CRC_ERROR;
-        sdio_flag_clear(SDIO_FLAG_DTCRCERR);
-        return status;
-    } else if(RESET != sdio_flag_get(SDIO_FLAG_DTTMOUT)) {
-        status = SD_DATA_TIMEOUT;
-        sdio_flag_clear(SDIO_FLAG_DTTMOUT);
-        return status;
-    } else if(RESET != sdio_flag_get(SDIO_FLAG_RXORE)) {
-        status = SD_RX_OVERRUN_ERROR;
-        sdio_flag_clear(SDIO_FLAG_RXORE);
-        return status;
-    } else if(RESET != sdio_flag_get(SDIO_FLAG_STBITE)) {
-        status = SD_START_BIT_ERROR;
-        sdio_flag_clear(SDIO_FLAG_STBITE);
-        return status;
-    }
-    while(RESET != sdio_flag_get(SDIO_FLAG_RXDTVAL)) {
-        *psdstatus = sdio_data_read();
-        ++psdstatus;
-    }
-
-    /* clear the SDIO_INTC flags */
-    sdio_flag_clear(SDIO_MASK_INTC_FLAGS);
-    psdstatus -= 16;
-    for(count = 0; count < 16; count++) {
-        psdstatus[count] = ((psdstatus[count] & SD_MASK_0_7BITS) << 24) | ((psdstatus[count] & SD_MASK_8_15BITS) << 8) |
-                           ((psdstatus[count] & SD_MASK_16_23BITS) >> 8) | ((psdstatus[count] & SD_MASK_24_31BITS) >> 24);
-    }
-    return status;
-}
-
-/*!
-    \brief      stop an ongoing data transfer
-    \param[in]  none
-    \param[out] none
-    \retval     sd_error_enum
-*/
-sd_error_enum sd_transfer_stop(void)
-{
-    sd_error_enum status = SD_OK;
-    /* send CMD12(STOP_TRANSMISSION) to stop transmission */
-    sdio_csm_disable();
-    sdio_command_response_config(SD_CMD_STOP_TRANSMISSION, (uint32_t)0x0, SDIO_RESPONSETYPE_SHORT);
-    sdio_wait_type_set(SDIO_WAITTYPE_NO);
-    sdio_csm_enable();
-    /* check if some error occurs */
-    status = r1_error_check(SD_CMD_STOP_TRANSMISSION);
-    return status;
-}
-
-/*!
-    \brief      lock or unlock a card
-    \param[in]  lockstate: the lock state
-      \arg        SD_LOCK: lock the SD card
-      \arg        SD_UNLOCK: unlock the SD card
-    \param[out] none
-    \retval     sd_error_enum
-*/
-sd_error_enum sd_lock_unlock(uint8_t lockstate)
-{
-    sd_error_enum status = SD_OK;
-    uint8_t cardstate = 0, tempbyte = 0;
-    uint32_t pwd1 = 0, pwd2 = 0, response = 0;
-    __IO uint32_t timeout = 0;
-    uint16_t tempccc = 0;
-
-    /* get the card command classes from CSD */
-    tempbyte = (uint8_t)((sd_csd[1] & SD_MASK_24_31BITS) >> 24);
-    tempccc = (uint16_t)((uint16_t)tempbyte << 4);
-    tempbyte = (uint8_t)((sd_csd[1] & SD_MASK_16_23BITS) >> 16);
-    tempccc |= (uint16_t)((uint16_t)(tempbyte & 0xF0) >> 4);
-
-    if(0 == (tempccc & SD_CCC_LOCK_CARD)) {
-        /* don't support the lock command */
-        status = SD_FUNCTION_UNSUPPORTED;
-        return status;
-    }
-    /* password pattern */
-    pwd1 = (0x01020600 | lockstate);
-    pwd2 = 0x03040506;
-
-    /* clear all DSM configuration */
-    sdio_data_config(0, 0, SDIO_DATABLOCKSIZE_1BYTE);
-    sdio_data_transfer_config(SDIO_TRANSMODE_BLOCK, SDIO_TRANSDIRECTION_TOCARD);
-    sdio_dsm_disable();
-    sdio_dma_disable();
-
-    /* send CMD16(SET_BLOCKLEN) to set the block length */
-    sdio_csm_disable();
-    sdio_command_response_config(SD_CMD_SET_BLOCKLEN, (uint32_t)8, SDIO_RESPONSETYPE_SHORT);
-    sdio_wait_type_set(SDIO_WAITTYPE_NO);
-    sdio_csm_enable();
-    /* check if some error occurs */
-    status = r1_error_check(SD_CMD_SET_BLOCKLEN);
-    if(SD_OK != status) {
-        return status;
-    }
-
-    /* send CMD13(SEND_STATUS), addressed card sends its status register */
-    sdio_csm_disable();
-    sdio_command_response_config(SD_CMD_SEND_STATUS, (uint32_t)sd_rca << SD_RCA_SHIFT, SDIO_RESPONSETYPE_SHORT);
-    sdio_wait_type_set(SDIO_WAITTYPE_NO);
-    sdio_csm_enable();
-    /* check if some error occurs */
-    status = r1_error_check(SD_CMD_SEND_STATUS);
-    if(SD_OK != status) {
-        return status;
-    }
-
-    response = sdio_response_get(SDIO_RESPONSE0);
-    timeout = 100000;
-    while((0 == (response & SD_R1_READY_FOR_DATA)) && (timeout > 0)) {
-        /* continue to send CMD13 to polling the state of card until buffer empty or timeout */
-        --timeout;
-        /* send CMD13(SEND_STATUS), addressed card sends its status registers */
-        sdio_csm_disable();
-        sdio_command_response_config(SD_CMD_SEND_STATUS, (uint32_t)sd_rca << SD_RCA_SHIFT, SDIO_RESPONSETYPE_SHORT);
-        sdio_wait_type_set(SDIO_WAITTYPE_NO);
-        sdio_csm_enable();
-        /* check if some error occurs */
-        status = r1_error_check(SD_CMD_SEND_STATUS);
-        if(SD_OK != status) {
-            return status;
-        }
-        response = sdio_response_get(SDIO_RESPONSE0);
-    }
-    if(0 == timeout) {
-        return SD_ERROR;
-    }
-
-    /* send CMD42(LOCK_UNLOCK) to set/reset the password or lock/unlock the card */
-    sdio_csm_disable();
-    sdio_command_response_config(SD_CMD_LOCK_UNLOCK, (uint32_t)0x0, SDIO_RESPONSETYPE_SHORT);
-    sdio_wait_type_set(SDIO_WAITTYPE_NO);
-    sdio_csm_enable();
-    /* check if some error occurs */
-    status = r1_error_check(SD_CMD_LOCK_UNLOCK);
-    if(SD_OK != status) {
-        return status;
-    }
-
-    response = sdio_response_get(SDIO_RESPONSE0);
-
-    /* configure the SDIO data transmission */
-    sdio_data_config(SD_DATATIMEOUT, (uint32_t)8, SDIO_DATABLOCKSIZE_8BYTES);
-    sdio_data_transfer_config(SDIO_TRANSMODE_BLOCK, SDIO_TRANSDIRECTION_TOCARD);
-    sdio_dsm_enable();
-
-    /* write password pattern */
-    sdio_data_write(pwd1);
-    sdio_data_write(pwd2);
-
-    /* whether some error occurs and return it */
-    if(RESET != sdio_flag_get(SDIO_FLAG_DTCRCERR)) {
-        status = SD_DATA_CRC_ERROR;
-        sdio_flag_clear(SDIO_FLAG_DTCRCERR);
-        return status;
-    } else if(RESET != sdio_flag_get(SDIO_FLAG_DTTMOUT)) {
-        status = SD_DATA_TIMEOUT;
-        sdio_flag_clear(SDIO_FLAG_DTTMOUT);
-        return status;
-    } else if(RESET != sdio_flag_get(SDIO_FLAG_TXURE)) {
-        status = SD_TX_UNDERRUN_ERROR;
-        sdio_flag_clear(SDIO_FLAG_TXURE);
-        return status;
-    } else if(RESET != sdio_flag_get(SDIO_FLAG_STBITE)) {
-        status = SD_START_BIT_ERROR;
-        sdio_flag_clear(SDIO_FLAG_STBITE);
-        return status;
-    }
-
-    /* clear the SDIO_INTC flags */
-    sdio_flag_clear(SDIO_MASK_INTC_FLAGS);
-    /* get the card state and wait the card is out of programming and receiving state */
-    status = sd_card_state_get(&cardstate);
-    while((SD_OK == status) && ((SD_CARDSTATE_PROGRAMMING == cardstate) || (SD_CARDSTATE_RECEIVING == cardstate))) {
-        status = sd_card_state_get(&cardstate);
-    }
-    return status;
-}
-
-/*!
-    \brief      get the data transfer state
-    \param[in]  none
-    \param[out] none
-    \retval     sd_error_enum
-*/
-sd_transfer_state_enum sd_transfer_state_get(void)
-{
-    sd_transfer_state_enum transtate = SD_NO_TRANSFER;
-    if(RESET != sdio_flag_get(SDIO_FLAG_TXRUN | SDIO_FLAG_RXRUN)) {
-        transtate = SD_TRANSFER_IN_PROGRESS;
-    }
-    return transtate;
-}
-
-/*!
-    \brief      get SD card capacity
-    \param[in]  none
-    \param[out] none
-    \retval     capacity of the card(KB)
-*/
-uint32_t sd_card_capacity_get(void)
-{
-    uint8_t tempbyte = 0, devicesize_mult = 0, readblklen = 0;
-    uint32_t capacity = 0, devicesize = 0;
-    if((SDIO_STD_CAPACITY_SD_CARD_V1_1 == cardtype) || (SDIO_STD_CAPACITY_SD_CARD_V2_0 == cardtype)) {
-        /* calculate the c_size(device size) */
-        tempbyte = (uint8_t)((sd_csd[1] & SD_MASK_8_15BITS) >> 8);
-        devicesize = (uint32_t)((uint32_t)(tempbyte & 0x03) << 10);
-        tempbyte = (uint8_t)(sd_csd[1] & SD_MASK_0_7BITS);
-        devicesize |= (uint32_t)((uint32_t)tempbyte << 2);
-        tempbyte = (uint8_t)((sd_csd[2] & SD_MASK_24_31BITS) >> 24);
-        devicesize |= (uint32_t)((uint32_t)(tempbyte & 0xC0) >> 6);
-
-        /* calculate the c_size_mult(device size multiplier) */
-        tempbyte = (uint8_t)((sd_csd[2] & SD_MASK_16_23BITS) >> 16);
-        devicesize_mult = (tempbyte & 0x03) << 1;
-        tempbyte = (uint8_t)((sd_csd[2] & SD_MASK_8_15BITS) >> 8);
-        devicesize_mult |= (tempbyte & 0x80) >> 7;
-
-        /* calculate the read_bl_len */
-        tempbyte = (uint8_t)((sd_csd[1] & SD_MASK_16_23BITS) >> 16);
-        readblklen = tempbyte & 0x0F;
-
-        /* capacity = BLOCKNR*BLOCK_LEN, BLOCKNR = (C_SIZE+1)*MULT, MULT = 2^(C_SIZE_MULT+2), BLOCK_LEN = 2^READ_BL_LEN */
-        capacity = (devicesize + 1) * (1 << (devicesize_mult + 2));
-        capacity *= (1 << readblklen);
-
-        /* change the unit of capacity to KByte */
-        capacity /= 1024;
-    } else if(SDIO_HIGH_CAPACITY_SD_CARD == cardtype) {
-        /* calculate the c_size */
-        tempbyte = (uint8_t)(sd_csd[1] & SD_MASK_0_7BITS);
-        devicesize = (uint32_t)((uint32_t)(tempbyte & 0x3F) << 16);
-        tempbyte = (uint8_t)((sd_csd[2] & SD_MASK_24_31BITS) >> 24);
-        devicesize |= (uint32_t)((uint32_t)tempbyte << 8);
-        tempbyte = (uint8_t)((sd_csd[2] & SD_MASK_16_23BITS) >> 16);
-        devicesize |= (uint32_t)tempbyte;
-
-        /* capacity = (c_size+1)*512KByte */
-        capacity = (devicesize + 1) * 512;
-    }
-    return capacity;
-}
-
-sd_error_enum sd_card_information_get_short(sdio_card_type_enum *card_type, uint16_t *card_rca)
-{
-    *card_type = cardtype;
-    *card_rca = sd_rca;
-    return SD_OK;
-}
-
-/*!
-    \brief      get the detailed information of the SD card based on received CID and CSD
-    \param[in]  none
-    \param[out] pcardinfo: a pointer that store the detailed card information
-    \retval     sd_error_enum
-*/
-sd_error_enum sd_card_information_get(sd_card_info_struct *pcardinfo)
-{
-    sd_error_enum status = SD_OK;
-    uint8_t tempbyte = 0;
-
-    if(NULL == pcardinfo) {
-        status = SD_PARAMETER_INVALID;
-        return status;
-    }
-
-    /* store the card type and RCA */
-    pcardinfo->card_type = cardtype;
-    pcardinfo->card_rca = sd_rca;
-
-    /* CID byte 0 */
-    tempbyte = (uint8_t)((sd_cid[0] & SD_MASK_24_31BITS) >> 24);
-    pcardinfo->card_cid.mid = tempbyte;
-
-    /* CID byte 1 */
-    tempbyte = (uint8_t)((sd_cid[0] & SD_MASK_16_23BITS) >> 16);
-    pcardinfo->card_cid.oid = (uint16_t)((uint16_t)tempbyte << 8);
-
-    /* CID byte 2 */
-    tempbyte = (uint8_t)((sd_cid[0] & SD_MASK_8_15BITS) >> 8);
-    pcardinfo->card_cid.oid |= (uint16_t)tempbyte;
-
-    /* CID byte 3 */
-    tempbyte = (uint8_t)(sd_cid[0] & SD_MASK_0_7BITS);
-    pcardinfo->card_cid.pnm0 = (uint32_t)((uint32_t)tempbyte << 24);
-
-    /* CID byte 4 */
-    tempbyte = (uint8_t)((sd_cid[1] & SD_MASK_24_31BITS) >> 24);
-    pcardinfo->card_cid.pnm0 |= (uint32_t)((uint32_t)tempbyte << 16);
-
-    /* CID byte 5 */
-    tempbyte = (uint8_t)((sd_cid[1] & SD_MASK_16_23BITS) >> 16);
-    pcardinfo->card_cid.pnm0 |= (uint32_t)((uint32_t)tempbyte << 8);
-
-    /* CID byte 6 */
-    tempbyte = (uint8_t)((sd_cid[1] & SD_MASK_8_15BITS) >> 8);
-    pcardinfo->card_cid.pnm0 |= (uint32_t)(tempbyte);
-
-    /* CID byte 7 */
-    tempbyte = (uint8_t)(sd_cid[1] & SD_MASK_0_7BITS);
-    pcardinfo->card_cid.pnm1 = tempbyte;
-
-    /* CID byte 8 */
-    tempbyte = (uint8_t)((sd_cid[2] & SD_MASK_24_31BITS) >> 24);
-    pcardinfo->card_cid.prv = tempbyte;
-
-    /* CID byte 9 */
-    tempbyte = (uint8_t)((sd_cid[2] & SD_MASK_16_23BITS) >> 16);
-    pcardinfo->card_cid.psn = (uint32_t)((uint32_t)tempbyte << 24);
-
-    /* CID byte 10 */
-    tempbyte = (uint8_t)((sd_cid[2] & SD_MASK_8_15BITS) >> 8);
-    pcardinfo->card_cid.psn |= (uint32_t)((uint32_t)tempbyte << 16);
-
-    /* CID byte 11 */
-    tempbyte = (uint8_t)(sd_cid[2] & SD_MASK_0_7BITS);
-    pcardinfo->card_cid.psn |= (uint32_t)tempbyte;
-
-    /* CID byte 12 */
-    tempbyte = (uint8_t)((sd_cid[3] & SD_MASK_24_31BITS) >> 24);
-    pcardinfo->card_cid.psn |= (uint32_t)tempbyte;
-
-    /* CID byte 13 */
-    tempbyte = (uint8_t)((sd_cid[3] & SD_MASK_16_23BITS) >> 16);
-    pcardinfo->card_cid.mdt = (uint16_t)((uint16_t)(tempbyte & 0x0F) << 8);
-
-    /* CID byte 14 */
-    tempbyte = (uint8_t)((sd_cid[3] & SD_MASK_8_15BITS) >> 8);
-    pcardinfo->card_cid.mdt |= (uint16_t)tempbyte;
-
-    /* CID byte 15 */
-    tempbyte = (uint8_t)(sd_cid[3] & SD_MASK_0_7BITS);
-    pcardinfo->card_cid.cid_crc = (tempbyte & 0xFE) >> 1;
-
-    /* CSD byte 0 */
-    tempbyte = (uint8_t)((sd_csd[0] & SD_MASK_24_31BITS) >> 24);
-    pcardinfo->card_csd.csd_struct = (tempbyte & 0xC0) >> 6;
-
-    /* CSD byte 1 */
-    tempbyte = (uint8_t)((sd_csd[0] & SD_MASK_16_23BITS) >> 16);
-    pcardinfo->card_csd.taac = tempbyte;
-
-    /* CSD byte 2 */
-    tempbyte = (uint8_t)((sd_csd[0] & SD_MASK_8_15BITS) >> 8);
-    pcardinfo->card_csd.nsac = tempbyte;
-
-    /* CSD byte 3 */
-    tempbyte = (uint8_t)(sd_csd[0] & SD_MASK_0_7BITS);
-    pcardinfo->card_csd.tran_speed = tempbyte;
-
-    /* CSD byte 4 */
-    tempbyte = (uint8_t)((sd_csd[1] & SD_MASK_24_31BITS) >> 24);
-    pcardinfo->card_csd.ccc = (uint16_t)((uint16_t)tempbyte << 4);
-
-    /* CSD byte 5 */
-    tempbyte = (uint8_t)((sd_csd[1] & SD_MASK_16_23BITS) >> 16);
-    pcardinfo->card_csd.ccc |= (uint16_t)((uint16_t)(tempbyte & 0xF0) >> 4);
-    pcardinfo->card_csd.read_bl_len = tempbyte & 0x0F;
-
-    /* CSD byte 6 */
-    tempbyte = (uint8_t)((sd_csd[1] & SD_MASK_8_15BITS) >> 8);
-    pcardinfo->card_csd.read_bl_partial = (tempbyte & 0x80) >> 7;
-    pcardinfo->card_csd.write_blk_misalign = (tempbyte & 0x40) >> 6;
-    pcardinfo->card_csd.read_blk_misalign = (tempbyte & 0x20) >> 5;
-    pcardinfo->card_csd.dsp_imp = (tempbyte & 0x10) >> 4;
-
-    if((SDIO_STD_CAPACITY_SD_CARD_V1_1 == cardtype) || (SDIO_STD_CAPACITY_SD_CARD_V2_0 == cardtype)) {
-        /* card is SDSC card, CSD version 1.0 */
-        pcardinfo->card_csd.c_size = (uint32_t)((uint32_t)(tempbyte & 0x03) << 10);
-
-        /* CSD byte 7 */
-        tempbyte = (uint8_t)(sd_csd[1] & SD_MASK_0_7BITS);
-        pcardinfo->card_csd.c_size |= (uint32_t)((uint32_t)tempbyte << 2);
-
-        /* CSD byte 8 */
-        tempbyte = (uint8_t)((sd_csd[2] & SD_MASK_24_31BITS) >> 24);
-        pcardinfo->card_csd.c_size |= (uint32_t)((uint32_t)(tempbyte & 0xC0) >> 6);
-        pcardinfo->card_csd.vdd_r_curr_min = (tempbyte & 0x38) >> 3;
-        pcardinfo->card_csd.vdd_r_curr_max = tempbyte & 0x07;
-
-        /* CSD byte 9 */
-        tempbyte = (uint8_t)((sd_csd[2] & SD_MASK_16_23BITS) >> 16);
-        pcardinfo->card_csd.vdd_w_curr_min = (tempbyte & 0xE0) >> 5;
-        pcardinfo->card_csd.vdd_w_curr_max = (tempbyte & 0x1C) >> 2;
-        pcardinfo->card_csd.c_size_mult = (tempbyte & 0x03) << 1;
-
-        /* CSD byte 10 */
-        tempbyte = (uint8_t)((sd_csd[2] & SD_MASK_8_15BITS) >> 8);
-        pcardinfo->card_csd.c_size_mult |= (tempbyte & 0x80) >> 7;
-
-        /* calculate the card block size and capacity */
-        pcardinfo->card_blocksize = 1 << (pcardinfo->card_csd.read_bl_len);
-        pcardinfo->card_capacity = pcardinfo->card_csd.c_size + 1;
-        pcardinfo->card_capacity *= (1 << (pcardinfo->card_csd.c_size_mult + 2));
-        pcardinfo->card_capacity *= pcardinfo->card_blocksize;
-    } else if(SDIO_HIGH_CAPACITY_SD_CARD == cardtype) {
-        /* card is SDHC card, CSD version 2.0 */
-        /* CSD byte 7 */
-        tempbyte = (uint8_t)(sd_csd[1] & SD_MASK_0_7BITS);
-        pcardinfo->card_csd.c_size = (uint32_t)((uint32_t)(tempbyte & 0x3F) << 16);
-
-        /* CSD byte 8 */
-        tempbyte = (uint8_t)((sd_csd[2] & SD_MASK_24_31BITS) >> 24);
-        pcardinfo->card_csd.c_size |= (uint32_t)((uint32_t)tempbyte << 8);
-
-        /* CSD byte 9 */
-        tempbyte = (uint8_t)((sd_csd[2] & SD_MASK_16_23BITS) >> 16);
-        pcardinfo->card_csd.c_size |= (uint32_t)tempbyte;
-
-        /* calculate the card block size and capacity */
-        pcardinfo->card_blocksize = 512;
-        pcardinfo->card_capacity = (pcardinfo->card_csd.c_size + 1) * 512 * 1024;
-    }
-
-    pcardinfo->card_csd.erase_blk_en = (tempbyte & 0x40) >> 6;
-    pcardinfo->card_csd.sector_size = (tempbyte & 0x3F) << 1;
-
-    /* CSD byte 11 */
-    tempbyte = (uint8_t)(sd_csd[2] & SD_MASK_0_7BITS);
-    pcardinfo->card_csd.sector_size |= (tempbyte & 0x80) >> 7;
-    pcardinfo->card_csd.wp_grp_size = (tempbyte & 0x7F);
-
-    /* CSD byte 12 */
-    tempbyte = (uint8_t)((sd_csd[3] & SD_MASK_24_31BITS) >> 24);
-    pcardinfo->card_csd.wp_grp_enable = (tempbyte & 0x80) >> 7;
-    pcardinfo->card_csd.r2w_factor = (tempbyte & 0x1C) >> 2;
-    pcardinfo->card_csd.write_bl_len = (tempbyte & 0x03) << 2;
-
-    /* CSD byte 13 */
-    tempbyte = (uint8_t)((sd_csd[3] & SD_MASK_16_23BITS) >> 16);
-    pcardinfo->card_csd.write_bl_len |= (tempbyte & 0xC0) >> 6;
-    pcardinfo->card_csd.write_bl_partial = (tempbyte & 0x20) >> 5;
-
-    /* CSD byte 14 */
-    tempbyte = (uint8_t)((sd_csd[3] & SD_MASK_8_15BITS) >> 8);
-    pcardinfo->card_csd.file_format_grp = (tempbyte & 0x80) >> 7;
-    pcardinfo->card_csd.copy_flag = (tempbyte & 0x40) >> 6;
-    pcardinfo->card_csd.perm_write_protect = (tempbyte & 0x20) >> 5;
-    pcardinfo->card_csd.tmp_write_protect = (tempbyte & 0x10) >> 4;
-    pcardinfo->card_csd.file_format = (tempbyte & 0x0C) >> 2;
-
-    /* CSD byte 15 */
-    tempbyte = (uint8_t)(sd_csd[3] & SD_MASK_0_7BITS);
-    pcardinfo->card_csd.csd_crc = (tempbyte & 0xFE) >> 1;
-
-    return status;
-}
-
-void sd_cid_get(uint8_t *cid)
-{
-    // SdFat expects the data in big endian format.
-    for (int i = 0; i < 16; i++)
-    {
-        cid[i] = (sd_cid[i / 4] >> (24 - (i % 4) * 8)) & 0xFF;
-    }
-}
-
-void sd_csd_get(uint8_t *csd)
-{
-    for (int i = 0; i < 16; i++)
-    {
-        csd[i] = (sd_csd[i / 4] >> (24 - (i % 4) * 8)) & 0xFF;
-    }
-}
-
-/*!
-    \brief      check if the command sent error occurs
-    \param[in]  none
-    \param[out] none
-    \retval     sd_error_enum
-*/
-static sd_error_enum cmdsent_error_check(void)
-{
-    sd_error_enum status = SD_OK;
-    __IO uint32_t timeout = 100000;
-    /* check command sent flag */
-    while((RESET == sdio_flag_get(SDIO_FLAG_CMDSEND)) && (timeout > 0)) {
-        --timeout;
-    }
-    /* command response is timeout */
-    if(0 == timeout) {
-        status = SD_CMD_RESP_TIMEOUT;
-        return status;
-    }
-    /* if the command is sent, clear the SDIO_INTC flags */
-    sdio_flag_clear(SDIO_MASK_INTC_FLAGS);
-    return status;
-}
-
-/*!
-    \brief      check if error type for R1 response
-    \param[in]  resp: content of response
-    \param[out] none
-    \retval     sd_error_enum
-*/
-static sd_error_enum r1_error_type_check(uint32_t resp)
-{
-    sd_error_enum status = SD_ERROR;
-    /* check which error occurs */
-    if(resp & SD_R1_OUT_OF_RANGE) {
-        status = SD_OUT_OF_RANGE;
-    } else if(resp & SD_R1_ADDRESS_ERROR) {
-        status = SD_ADDRESS_ERROR;
-    } else if(resp & SD_R1_BLOCK_LEN_ERROR) {
-        status = SD_BLOCK_LEN_ERROR;
-    } else if(resp & SD_R1_ERASE_SEQ_ERROR) {
-        status = SD_ERASE_SEQ_ERROR;
-    } else if(resp & SD_R1_ERASE_PARAM) {
-        status = SD_ERASE_PARAM;
-    } else if(resp & SD_R1_WP_VIOLATION) {
-        status = SD_WP_VIOLATION;
-    } else if(resp & SD_R1_LOCK_UNLOCK_FAILED) {
-        status = SD_LOCK_UNLOCK_FAILED;
-    } else if(resp & SD_R1_COM_CRC_ERROR) {
-        status = SD_COM_CRC_ERROR;
-    } else if(resp & SD_R1_ILLEGAL_COMMAND) {
-        status = SD_ILLEGAL_COMMAND;
-    } else if(resp & SD_R1_CARD_ECC_FAILED) {
-        status = SD_CARD_ECC_FAILED;
-    } else if(resp & SD_R1_CC_ERROR) {
-        status = SD_CC_ERROR;
-    } else if(resp & SD_R1_GENERAL_UNKNOWN_ERROR) {
-        status = SD_GENERAL_UNKNOWN_ERROR;
-    } else if(resp & SD_R1_CSD_OVERWRITE) {
-        status = SD_CSD_OVERWRITE;
-    } else if(resp & SD_R1_WP_ERASE_SKIP) {
-        status = SD_WP_ERASE_SKIP;
-    } else if(resp & SD_R1_CARD_ECC_DISABLED) {
-        status = SD_CARD_ECC_DISABLED;
-    } else if(resp & SD_R1_ERASE_RESET) {
-        status = SD_ERASE_RESET;
-    } else if(resp & SD_R1_AKE_SEQ_ERROR) {
-        status = SD_AKE_SEQ_ERROR;
-    }
-    return status;
-}
-
-/*!
-    \brief      check if error occurs for R1 response
-    \param[in]  cmdindex: the index of command
-    \param[out] none
-    \retval     sd_error_enum
-*/
-static sd_error_enum r1_error_check(uint8_t cmdindex)
-{
-    sd_error_enum status = SD_OK;
-    uint32_t reg_status = 0, resp_r1 = 0;
-    __IO uint32_t timeout = 100000;
-
-    /* store the content of SDIO_STAT */
-    reg_status = SDIO_STAT;
-    while(!(reg_status & (SDIO_FLAG_CCRCERR | SDIO_FLAG_CMDTMOUT | SDIO_FLAG_CMDRECV)) && (timeout > 0)) {
-        reg_status = SDIO_STAT;
-        --timeout;
-    }
-    /* check whether an error or timeout occurs or command response received */
-    if(reg_status & SDIO_FLAG_CCRCERR) {
-        status = SD_CMD_CRC_ERROR;
-        sdio_flag_clear(SDIO_FLAG_CCRCERR);
-        return status;
-    } else if((reg_status & SDIO_FLAG_CMDTMOUT) || (0 == timeout)) {
-        status = SD_CMD_RESP_TIMEOUT;
-        sdio_flag_clear(SDIO_FLAG_CMDTMOUT);
-        return status;
-    }
-
-    /* check whether the last response command index is the desired one */
-    if(sdio_command_index_get() != cmdindex) {
-        status = SD_ILLEGAL_COMMAND;
-        return status;
-    }
-    /* clear all the SDIO_INTC flags */
-    sdio_flag_clear(SDIO_MASK_INTC_FLAGS);
-    /* get the SDIO response register 0 for checking */
-    resp_r1 = sdio_response_get(SDIO_RESPONSE0);
-    if(SD_ALLZERO == (resp_r1 & SD_R1_ERROR_BITS)) {
-        /* no error occurs, return SD_OK */
-        status = SD_OK;
-        return status;
-    }
-
-    /* if some error occurs, return the error type */
-    status = r1_error_type_check(resp_r1);
-    return status;
-}
-
-/*!
-    \brief      check if error occurs for R2 response
-    \param[in]  none
-    \param[out] none
-    \retval     sd_error_enum
-*/
-static sd_error_enum r2_error_check(void)
-{
-    sd_error_enum status = SD_OK;
-    uint32_t reg_status = 0;
-    __IO uint32_t timeout = 100000;
-
-    /* store the content of SDIO_STAT */
-    reg_status = SDIO_STAT;
-    while(!(reg_status & (SDIO_FLAG_CCRCERR | SDIO_FLAG_CMDTMOUT | SDIO_FLAG_CMDRECV)) && (timeout > 0)) {
-        reg_status = SDIO_STAT;
-        --timeout;
-    }
-    /* check whether an error or timeout occurs or command response received */
-    if(reg_status & SDIO_FLAG_CCRCERR) {
-        status = SD_CMD_CRC_ERROR;
-        sdio_flag_clear(SDIO_FLAG_CCRCERR);
-        return status;
-    } else if((reg_status & SDIO_FLAG_CMDTMOUT) || (0 == timeout)) {
-        status = SD_CMD_RESP_TIMEOUT;
-        sdio_flag_clear(SDIO_FLAG_CMDTMOUT);
-        return status;
-    }
-    /* clear all the SDIO_INTC flags */
-    sdio_flag_clear(SDIO_MASK_INTC_FLAGS);
-    return status;
-}
-
-/*!
-    \brief      check if error occurs for R3 response
-    \param[in]  none
-    \param[out] none
-    \retval     sd_error_enum
-*/
-static sd_error_enum r3_error_check(void)
-{
-    sd_error_enum status = SD_OK;
-    uint32_t reg_status = 0;
-    __IO uint32_t timeout = 100000;
-
-    /* store the content of SDIO_STAT */
-    reg_status = SDIO_STAT;
-    while(!(reg_status & (SDIO_FLAG_CCRCERR | SDIO_FLAG_CMDTMOUT | SDIO_FLAG_CMDRECV)) && (timeout > 0)) {
-        reg_status = SDIO_STAT;
-        --timeout;
-    }
-    if((reg_status & SDIO_FLAG_CMDTMOUT) || (0 == timeout)) {
-        status = SD_CMD_RESP_TIMEOUT;
-        sdio_flag_clear(SDIO_FLAG_CMDTMOUT);
-        return status;
-    }
-    /* clear all the SDIO_INTC flags */
-    sdio_flag_clear(SDIO_MASK_INTC_FLAGS);
-    return status;
-}
-
-/*!
-    \brief      check if error occurs for R6 response
-    \param[in]  cmdindex: the index of command
-    \param[out] prca: a pointer that store the RCA of card
-    \retval     sd_error_enum
-*/
-static sd_error_enum r6_error_check(uint8_t cmdindex, uint16_t *prca)
-{
-    sd_error_enum status = SD_OK;
-    uint32_t reg_status = 0, response = 0;
-    __IO uint32_t timeout = 100000;
-
-    /* store the content of SDIO_STAT */
-    reg_status = SDIO_STAT;
-    while(!(reg_status & (SDIO_FLAG_CCRCERR | SDIO_FLAG_CMDTMOUT | SDIO_FLAG_CMDRECV)) && (timeout > 0)) {
-        reg_status = SDIO_STAT;
-        --timeout;
-    }
-    /* check whether an error or timeout occurs or command response received */
-    if(reg_status & SDIO_FLAG_CCRCERR) {
-        status = SD_CMD_CRC_ERROR;
-        sdio_flag_clear(SDIO_FLAG_CCRCERR);
-        return status;
-    } else if((reg_status & SDIO_FLAG_CMDTMOUT) || (0 == timeout)) {
-        status = SD_CMD_RESP_TIMEOUT;
-        sdio_flag_clear(SDIO_FLAG_CMDTMOUT);
-        return status;
-    }
-
-    /* check whether the last response command index is the desired one */
-    if(sdio_command_index_get() != cmdindex) {
-        status = SD_ILLEGAL_COMMAND;
-        return status;
-    }
-    /* clear all the SDIO_INTC flags */
-    sdio_flag_clear(SDIO_MASK_INTC_FLAGS);
-    /* get the SDIO response register 0 for checking */
-    response = sdio_response_get(SDIO_RESPONSE0);
-
-    if(SD_ALLZERO == (response & (SD_R6_COM_CRC_ERROR | SD_R6_ILLEGAL_COMMAND | SD_R6_GENERAL_UNKNOWN_ERROR))) {
-        *prca = (uint16_t)(response >> 16);
-        return status;
-    }
-    /* if some error occurs, return the error type */
-    if(response & SD_R6_COM_CRC_ERROR) {
-        status = SD_COM_CRC_ERROR;
-    } else if(response & SD_R6_ILLEGAL_COMMAND) {
-        status = SD_ILLEGAL_COMMAND;
-    } else if(response & SD_R6_GENERAL_UNKNOWN_ERROR) {
-        status = SD_GENERAL_UNKNOWN_ERROR;
-    }
-    return status;
-}
-
-/*!
-    \brief      check if error occurs for R7 response
-    \param[in]  none
-    \param[out] none
-    \retval     sd_error_enum
-*/
-static sd_error_enum r7_error_check(void)
-{
-    sd_error_enum status = SD_ERROR;
-    uint32_t reg_status = 0;
-    __IO uint32_t timeout = 100000;
-
-    /* store the content of SDIO_STAT */
-    reg_status = SDIO_STAT;
-    while(!(reg_status & (SDIO_FLAG_CCRCERR | SDIO_FLAG_CMDTMOUT | SDIO_FLAG_CMDRECV)) && (timeout > 0)) {
-        reg_status = SDIO_STAT;
-        --timeout;
-    }
-
-    /* check the flags */
-    if((reg_status & SDIO_FLAG_CMDTMOUT) || (0 == timeout)) {
-        status = SD_CMD_RESP_TIMEOUT;
-        sdio_flag_clear(SDIO_FLAG_CMDTMOUT);
-        return status;
-    }
-    if(reg_status & SDIO_FLAG_CMDRECV) {
-        status = SD_OK;
-        sdio_flag_clear(SDIO_FLAG_CMDRECV);
-        return status;
-    }
-    return status;
-}
-
-/*!
-    \brief      get the state which the card is in
-    \param[in]  none
-    \param[out] pcardstate: a pointer that store the card state
-      \arg        SD_CARDSTATE_IDLE: card is in idle state
-      \arg        SD_CARDSTATE_READY: card is in ready state
-      \arg        SD_CARDSTATE_IDENTIFICAT: card is in identification state
-      \arg        SD_CARDSTATE_STANDBY: card is in standby state
-      \arg        SD_CARDSTATE_TRANSFER: card is in transfer state
-      \arg        SD_CARDSTATE_DATA: card is in data state
-      \arg        SD_CARDSTATE_RECEIVING: card is in receiving state
-      \arg        SD_CARDSTATE_PROGRAMMING: card is in programming state
-      \arg        SD_CARDSTATE_DISCONNECT: card is in disconnect state
-      \arg        SD_CARDSTATE_LOCKED: card is in locked state
-    \retval     sd_error_enum
-*/
-static sd_error_enum sd_card_state_get(uint8_t *pcardstate)
-{
-    sd_error_enum status = SD_OK;
-    __IO uint32_t reg_status = 0, response = 0;
-    __IO uint32_t timeout = 100000;
-
-    /* send CMD13(SEND_STATUS), addressed card sends its status register */
-    sdio_csm_disable();
-    sdio_command_response_config(SD_CMD_SEND_STATUS, (uint32_t)sd_rca << SD_RCA_SHIFT, SDIO_RESPONSETYPE_SHORT);
-    sdio_wait_type_set(SDIO_WAITTYPE_NO);
-    sdio_csm_enable();
-
-    /* store the content of SDIO_STAT */
-    reg_status = SDIO_STAT;
-    while(!(reg_status & (SDIO_FLAG_CCRCERR | SDIO_FLAG_CMDTMOUT | SDIO_FLAG_CMDRECV)) && (timeout > 0)) {
-        reg_status = SDIO_STAT;
-        --timeout;
-    }
-    /* check whether an error or timeout occurs or command response received */
-    if(reg_status & SDIO_FLAG_CCRCERR) {
-        status = SD_CMD_CRC_ERROR;
-        sdio_flag_clear(SDIO_FLAG_CCRCERR);
-        return status;
-    } else if((reg_status & SDIO_FLAG_CMDTMOUT) || (0 == timeout)) {
-        status = SD_CMD_RESP_TIMEOUT;
-        sdio_flag_clear(SDIO_FLAG_CMDTMOUT);
-        return status;
-    }
-
-    /* command response received, store the response command index */
-    reg_status = (uint32_t)sdio_command_index_get();
-    if(reg_status != (uint32_t)SD_CMD_SEND_STATUS) {
-        status = SD_ILLEGAL_COMMAND;
-        return status;
-    }
-    /* clear all the SDIO_INTC flags */
-    sdio_flag_clear(SDIO_MASK_INTC_FLAGS);
-    /* get the SDIO response register 0 for checking */
-    response = sdio_response_get(SDIO_RESPONSE0);
-    *pcardstate = (uint8_t)((response >> 9) & 0x0000000F);
-
-    if(SD_ALLZERO == (response & SD_R1_ERROR_BITS)) {
-        /* no error occurs, return SD_OK */
-        status = SD_OK;
-        return status;
-    }
-
-    /* if some error occurs, return the error type */
-    status = r1_error_type_check(response);
-    return status;
-}
-
-/*!
-    \brief      configure the bus width mode
-    \param[in]  buswidth: the bus width
-      \arg        SD_BUS_WIDTH_1BIT: 1-bit bus width
-      \arg        SD_BUS_WIDTH_4BIT: 4-bit bus width
-    \param[out] none
-    \retval     sd_error_enum
-*/
-static sd_error_enum sd_bus_width_config(uint32_t buswidth)
-{
-    sd_error_enum status = SD_OK;
-    /* check whether the card is locked */
-    if(sdio_response_get(SDIO_RESPONSE0) & SD_CARDSTATE_LOCKED) {
-        status = SD_LOCK_UNLOCK_FAILED;
-        return status;
-    }
-    /* get the SCR register */
-    status = sd_scr_get(sd_rca, sd_scr);
-    if(SD_OK != status) {
-        return status;
-    }
-
-    if(SD_BUS_WIDTH_1BIT == buswidth) {
-        if(SD_ALLZERO != (sd_scr[1] & buswidth)) {
-            /* send CMD55(APP_CMD) to indicate next command is application specific command */
-            sdio_csm_disable();
-            sdio_command_response_config(SD_CMD_APP_CMD, (uint32_t)sd_rca << SD_RCA_SHIFT, SDIO_RESPONSETYPE_SHORT);
-            sdio_wait_type_set(SDIO_WAITTYPE_NO);
-            sdio_csm_enable();
-            /* check if some error occurs */
-            status = r1_error_check(SD_CMD_APP_CMD);
-            if(SD_OK != status) {
-                return status;
-            }
-
-            /* send ACMD6(SET_BUS_WIDTH) to define the data bus width */
-            sdio_csm_disable();
-            sdio_command_response_config(SD_APPCMD_SET_BUS_WIDTH, (uint32_t)0x0, SDIO_RESPONSETYPE_SHORT);
-            sdio_wait_type_set(SDIO_WAITTYPE_NO);
-            sdio_csm_enable();
-            /* check if some error occurs */
-            status = r1_error_check(SD_APPCMD_SET_BUS_WIDTH);
-            if(SD_OK != status) {
-                return status;
-            }
-        } else {
-            status = SD_OPERATION_IMPROPER;
-        }
-        return status;
-    } else if(SD_BUS_WIDTH_4BIT == buswidth) {
-        if(SD_ALLZERO != (sd_scr[1] & buswidth)) {
-            /* send CMD55(APP_CMD) to indicate next command is application specific command */
-            sdio_csm_disable();
-            sdio_command_response_config(SD_CMD_APP_CMD, (uint32_t)sd_rca << SD_RCA_SHIFT, SDIO_RESPONSETYPE_SHORT);
-            sdio_wait_type_set(SDIO_WAITTYPE_NO);
-            sdio_csm_enable();
-            /* check if some error occurs */
-            status = r1_error_check(SD_CMD_APP_CMD);
-            if(SD_OK != status) {
-                return status;
-            }
-
-            /* send ACMD6(SET_BUS_WIDTH) to define the data bus width */
-            sdio_csm_disable();
-            sdio_command_response_config(SD_APPCMD_SET_BUS_WIDTH, (uint32_t)0x2, SDIO_RESPONSETYPE_SHORT);
-            sdio_wait_type_set(SDIO_WAITTYPE_NO);
-            sdio_csm_enable();
-            /* check if some error occurs */
-            status = r1_error_check(SD_APPCMD_SET_BUS_WIDTH);
-            if(SD_OK != status) {
-                return status;
-            }
-        } else {
-            status = SD_OPERATION_IMPROPER;
-        }
-        return status;
-    } else {
-        status = SD_PARAMETER_INVALID;
-        return status;
-    }
-}
-
-/*!
-    \brief      get the SCR of corresponding card
-    \param[in]  rca: RCA of a card
-    \param[out] pscr: a pointer that store the SCR content
-    \retval     sd_error_enum
-*/
-static sd_error_enum sd_scr_get(uint16_t rca, uint32_t *pscr)
-{
-    sd_error_enum status = SD_OK;
-    uint32_t temp_scr[2] = {0, 0}, idx_scr = 0;
-    /* send CMD16(SET_BLOCKLEN) to set block length */
-    sdio_csm_disable();
-    sdio_command_response_config(SD_CMD_SET_BLOCKLEN, (uint32_t)8, SDIO_RESPONSETYPE_SHORT);
-    sdio_wait_type_set(SDIO_WAITTYPE_NO);
-    sdio_csm_enable();
-    /* check if some error occurs */
-    status = r1_error_check(SD_CMD_SET_BLOCKLEN);
-    if(SD_OK != status) {
-        return status;
-    }
-
-    /* send CMD55(APP_CMD) to indicate next command is application specific command */
-    sdio_csm_disable();
-    sdio_command_response_config(SD_CMD_APP_CMD, (uint32_t)rca << SD_RCA_SHIFT, SDIO_RESPONSETYPE_SHORT);
-    sdio_wait_type_set(SDIO_WAITTYPE_NO);
-    sdio_csm_enable();
-    /* check if some error occurs */
-    status = r1_error_check(SD_CMD_APP_CMD);
-    if(SD_OK != status) {
-        return status;
-    }
-
-    /* configure SDIO data */
-    sdio_data_config(SD_DATATIMEOUT, (uint32_t)8, SDIO_DATABLOCKSIZE_8BYTES);
-    sdio_data_transfer_config(SDIO_TRANSMODE_BLOCK, SDIO_TRANSDIRECTION_TOSDIO);
-    sdio_dsm_enable();
-
-    /* send ACMD51(SEND_SCR) to read the SD configuration register */
-    sdio_csm_disable();
-    sdio_command_response_config(SD_APPCMD_SEND_SCR, (uint32_t)0x0, SDIO_RESPONSETYPE_SHORT);
-    sdio_wait_type_set(SDIO_WAITTYPE_NO);
-    sdio_csm_enable();
-    /* check if some error occurs */
-    status = r1_error_check(SD_APPCMD_SEND_SCR);
-    if(SD_OK != status) {
-        return status;
-    }
-
-    /* store the received SCR */
-    while(!sdio_flag_get(SDIO_FLAG_DTCRCERR | SDIO_FLAG_DTTMOUT | SDIO_FLAG_RXORE | SDIO_FLAG_DTBLKEND | SDIO_FLAG_STBITE)) {
-        if(RESET != sdio_flag_get(SDIO_FLAG_RXDTVAL)) {
-            *(temp_scr + idx_scr) = sdio_data_read();
-            ++idx_scr;
-        }
-    }
-
-    /* check whether some error occurs */
-    if(RESET != sdio_flag_get(SDIO_FLAG_DTCRCERR)) {
-        status = SD_DATA_CRC_ERROR;
-        sdio_flag_clear(SDIO_FLAG_DTCRCERR);
-        return status;
-    } else if(RESET != sdio_flag_get(SDIO_FLAG_DTTMOUT)) {
-        status = SD_DATA_TIMEOUT;
-        sdio_flag_clear(SDIO_FLAG_DTTMOUT);
-        return status;
-    } else if(RESET != sdio_flag_get(SDIO_FLAG_RXORE)) {
-        status = SD_RX_OVERRUN_ERROR;
-        sdio_flag_clear(SDIO_FLAG_RXORE);
-        return status;
-    } else if(RESET != sdio_flag_get(SDIO_FLAG_STBITE)) {
-        status = SD_START_BIT_ERROR;
-        sdio_flag_clear(SDIO_FLAG_STBITE);
-        return status;
-    }
-
-    /* clear all the SDIO_INTC flags */
-    sdio_flag_clear(SDIO_MASK_INTC_FLAGS);
-    /* readjust the temp SCR value */
-    *(pscr) = ((temp_scr[1] & SD_MASK_0_7BITS) << 24) | ((temp_scr[1] & SD_MASK_8_15BITS) << 8) |
-              ((temp_scr[1] & SD_MASK_16_23BITS) >> 8) | ((temp_scr[1] & SD_MASK_24_31BITS) >> 24);
-    *(pscr + 1) = ((temp_scr[0] & SD_MASK_0_7BITS) << 24) | ((temp_scr[0] & SD_MASK_8_15BITS) << 8) |
-                  ((temp_scr[0] & SD_MASK_16_23BITS) >> 8) | ((temp_scr[0] & SD_MASK_24_31BITS) >> 24);
-    return status;
-}
-
-/*!
-    \brief      get the data block size
-    \param[in]  bytesnumber: the number of bytes
-    \param[out] none
-    \retval     data block size
-      \arg        SDIO_DATABLOCKSIZE_1BYTE: block size = 1 byte
-      \arg        SDIO_DATABLOCKSIZE_2BYTES: block size = 2 bytes
-      \arg        SDIO_DATABLOCKSIZE_4BYTES: block size = 4 bytes
-      \arg        SDIO_DATABLOCKSIZE_8BYTES: block size = 8 bytes
-      \arg        SDIO_DATABLOCKSIZE_16BYTES: block size = 16 bytes
-      \arg        SDIO_DATABLOCKSIZE_32BYTES: block size = 32 bytes
-      \arg        SDIO_DATABLOCKSIZE_64BYTES: block size = 64 bytes
-      \arg        SDIO_DATABLOCKSIZE_128BYTES: block size = 128 bytes
-      \arg        SDIO_DATABLOCKSIZE_256BYTES: block size = 256 bytes
-      \arg        SDIO_DATABLOCKSIZE_512BYTES: block size = 512 bytes
-      \arg        SDIO_DATABLOCKSIZE_1024BYTES: block size = 1024 bytes
-      \arg        SDIO_DATABLOCKSIZE_2048BYTES: block size = 2048 bytes
-      \arg        SDIO_DATABLOCKSIZE_4096BYTES: block size = 4096 bytes
-      \arg        SDIO_DATABLOCKSIZE_8192BYTES: block size = 8192 bytes
-      \arg        SDIO_DATABLOCKSIZE_16384BYTES: block size = 16384 bytes
-*/
-static uint32_t sd_datablocksize_get(uint16_t bytesnumber)
-{
-    uint8_t exp_val = 0;
-    /* calculate the exponent of 2 */
-    while(1 != bytesnumber) {
-        bytesnumber >>= 1;
-        ++exp_val;
-    }
-    return DATACTL_BLKSZ(exp_val);
-}
-
-/*!
-    \brief      configure the DMA1 channel 3 for transferring data
-    \param[in]  srcbuf: a pointer point to a buffer which will be transferred
-    \param[in]  bufsize: the size of buffer(not used in flow controller is peripheral)
-    \param[out] none
-    \retval     none
-*/
-static void dma_transfer_config(uint32_t *srcbuf, uint32_t bufsize)
-{
-    dma_parameter_struct dma_struct;
-    /* clear all the interrupt flags */
-    dma_flag_clear(DMA1, DMA_CH3, DMA_FLAG_G);
-    dma_flag_clear(DMA1, DMA_CH3, DMA_FLAG_FTF);
-    dma_flag_clear(DMA1, DMA_CH3, DMA_FLAG_HTF);
-    dma_flag_clear(DMA1, DMA_CH3, DMA_FLAG_ERR);
-    dma_channel_disable(DMA1, DMA_CH3);
-    dma_deinit(DMA1, DMA_CH3);
-
-    /* configure the DMA1 channel3 */
-    dma_struct.periph_addr = (uint32_t)SDIO_FIFO_ADDR;
-    dma_struct.memory_addr = (uint32_t)srcbuf;
-    dma_struct.direction = DMA_MEMORY_TO_PERIPHERAL;
-    dma_struct.number = bufsize / 4;
-    dma_struct.periph_inc = DMA_PERIPH_INCREASE_DISABLE;
-    dma_struct.memory_inc = DMA_MEMORY_INCREASE_ENABLE;
-    dma_struct.periph_width = DMA_PERIPHERAL_WIDTH_32BIT;
-    dma_struct.memory_width = DMA_MEMORY_WIDTH_32BIT;
-    dma_struct.priority = DMA_PRIORITY_MEDIUM;
-    dma_init(DMA1, DMA_CH3, &dma_struct);
-
-    dma_circulation_disable(DMA1, DMA_CH3);
-    dma_channel_enable(DMA1, DMA_CH3);
-}
-
-/*!
-    \brief      configure the DMA1 channel 3 for receiving data
-    \param[in]  dstbuf: a pointer point to a buffer which will receive data
-    \param[in]  bufsize: the size of buffer(not used in flow controller is peripheral)
-    \param[out] none
-    \retval     none
-*/
-static void dma_receive_config(uint32_t *dstbuf, uint32_t bufsize)
-{
-    dma_parameter_struct dma_struct;
-    /* clear all the interrupt flags */
-    dma_flag_clear(DMA1, DMA_CH3, DMA_FLAG_G);
-    dma_flag_clear(DMA1, DMA_CH3, DMA_FLAG_FTF);
-    dma_flag_clear(DMA1, DMA_CH3, DMA_FLAG_HTF);
-    dma_flag_clear(DMA1, DMA_CH3, DMA_FLAG_ERR);
-    dma_channel_disable(DMA1, DMA_CH3);
-    dma_deinit(DMA1, DMA_CH3);
-
-    /* configure the DMA1 channel 3 */
-    dma_struct.periph_addr = (uint32_t)SDIO_FIFO_ADDR;
-    dma_struct.memory_addr = (uint32_t)dstbuf;
-    dma_struct.direction = DMA_PERIPHERAL_TO_MEMORY;
-    dma_struct.number = bufsize / 4;
-    dma_struct.periph_inc = DMA_PERIPH_INCREASE_DISABLE;
-    dma_struct.memory_inc = DMA_MEMORY_INCREASE_ENABLE;
-    dma_struct.periph_width = DMA_PERIPHERAL_WIDTH_32BIT;
-    dma_struct.memory_width = DMA_MEMORY_WIDTH_32BIT;
-    dma_struct.priority = DMA_PRIORITY_ULTRA_HIGH;
-    dma_init(DMA1, DMA_CH3, &dma_struct);
-
-    dma_circulation_disable(DMA1, DMA_CH3);
-    dma_channel_enable(DMA1, DMA_CH3);
-}

+ 0 - 271
lib/ZuluSCSI_platform_GD32F205/gd32_sdio_sdcard.h

@@ -1,271 +0,0 @@
-/*!
-    \file    sdcard.h
-    \brief   the header file of SD card driver
-
-    \version 2015-07-15, V1.0.0, firmware for GD32F20x
-    \version 2017-06-05, V2.0.0, firmware for GD32F20x
-    \version 2018-10-31, V2.1.0, firmware for GD32F20x
-    \version 2020-09-30, V2.2.0, firmware for GD32F20x
-    \version 2021-07-30, V2.3.0, firmware for GD32F20x
-*/
-
-/*
-    Copyright (c) 2021, GigaDevice Semiconductor Inc.
-
-    Redistribution and use in source and binary forms, with or without modification,
-are permitted provided that the following conditions are met:
-
-    1. Redistributions of source code must retain the above copyright notice, this
-       list of conditions and the following disclaimer.
-    2. Redistributions in binary form must reproduce the above copyright notice,
-       this list of conditions and the following disclaimer in the documentation
-       and/or other materials provided with the distribution.
-    3. Neither the name of the copyright holder nor the names of its contributors
-       may be used to endorse or promote products derived from this software without
-       specific prior written permission.
-
-    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
-WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
-IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
-INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
-NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
-PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
-WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
-OF SUCH DAMAGE.
-*/
-
-#ifndef SDCARD_H
-#define SDCARD_H
-
-#include "gd32f20x.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/* SD memory card bus commands index */
-#define SD_CMD_GO_IDLE_STATE                  ((uint8_t)0)   /* CMD0, GO_IDLE_STATE */
-#define SD_CMD_ALL_SEND_CID                   ((uint8_t)2)   /* CMD2, ALL_SEND_CID */
-#define SD_CMD_SEND_RELATIVE_ADDR             ((uint8_t)3)   /* CMD3, SEND_RELATIVE_ADDR */
-#define SD_CMD_SET_DSR                        ((uint8_t)4)   /* CMD4, SET_DSR */
-#define SD_CMD_SWITCH_FUNC                    ((uint8_t)6)   /* CMD6, SWITCH_FUNC */
-#define SD_CMD_SELECT_DESELECT_CARD           ((uint8_t)7)   /* CMD7, SELECT_DESELECT_CARD */
-#define SD_CMD_SEND_IF_COND                   ((uint8_t)8)   /* CMD8, SEND_IF_COND */
-#define SD_CMD_SEND_CSD                       ((uint8_t)9)   /* CMD9, SEND_CSD */
-#define SD_CMD_SEND_CID                       ((uint8_t)10)  /* CMD10, SEND_CID */
-#define SD_CMD_STOP_TRANSMISSION              ((uint8_t)12)  /* CMD12, STOP_TRANSMISSION */
-#define SD_CMD_SEND_STATUS                    ((uint8_t)13)  /* CMD13, SEND_STATUS */
-#define SD_CMD_GO_INACTIVE_STATE              ((uint8_t)15)  /* CMD15, GO_INACTIVE_STATE */
-#define SD_CMD_SET_BLOCKLEN                   ((uint8_t)16)  /* CMD16, SET_BLOCKLEN */
-#define SD_CMD_READ_SINGLE_BLOCK              ((uint8_t)17)  /* CMD17, READ_SINGLE_BLOCK */
-#define SD_CMD_READ_MULTIPLE_BLOCK            ((uint8_t)18)  /* CMD18, READ_MULTIPLE_BLOCK */
-#define SD_CMD_WRITE_BLOCK                    ((uint8_t)24)  /* CMD24, WRITE_BLOCK */
-#define SD_CMD_WRITE_MULTIPLE_BLOCK           ((uint8_t)25)  /* CMD25, WRITE_MULTIPLE_BLOCK */
-#define SD_CMD_PROG_CSD                       ((uint8_t)27)  /* CMD27, PROG_CSD */
-#define SD_CMD_SET_WRITE_PROT                 ((uint8_t)28)  /* CMD28, SET_WRITE_PROT */
-#define SD_CMD_CLR_WRITE_PROT                 ((uint8_t)29)  /* CMD29, CLR_WRITE_PROT */
-#define SD_CMD_SEND_WRITE_PROT                ((uint8_t)30)  /* CMD30, SEND_WRITE_PROT */
-#define SD_CMD_ERASE_WR_BLK_START             ((uint8_t)32)  /* CMD32, ERASE_WR_BLK_START */
-#define SD_CMD_ERASE_WR_BLK_END               ((uint8_t)33)  /* CMD33, ERASE_WR_BLK_END */
-#define SD_CMD_ERASE                          ((uint8_t)38)  /* CMD38, ERASE */
-#define SD_CMD_LOCK_UNLOCK                    ((uint8_t)42)  /* CMD42, LOCK_UNLOCK */
-#define SD_CMD_APP_CMD                        ((uint8_t)55)  /* CMD55, APP_CMD */
-#define SD_CMD_GEN_CMD                        ((uint8_t)56)  /* CMD56, GEN_CMD */
-
-/* SD memory card application specific commands index */
-#define SD_APPCMD_SET_BUS_WIDTH               ((uint8_t)6)   /* ACMD6, SET_BUS_WIDTH */
-#define SD_APPCMD_SD_STATUS                   ((uint8_t)13)  /* ACMD13, SD_STATUS */
-#define SD_APPCMD_SEND_NUM_WR_BLOCKS          ((uint8_t)22)  /* ACMD22, SEND_NUM_WR_BLOCKS */
-#define SD_APPCMD_SET_WR_BLK_ERASE_COUNT      ((uint8_t)23)  /* ACMD23, SET_WR_BLK_ERASE_COUNT */
-#define SD_APPCMD_SD_SEND_OP_COND             ((uint8_t)41)  /* ACMD41, SD_SEND_OP_COND */
-#define SD_APPCMD_SET_CLR_CARD_DETECT         ((uint8_t)42)  /* ACMD42, SET_CLR_CARD_DETECT */
-#define SD_APPCMD_SEND_SCR                    ((uint8_t)51)  /* ACMD51, SEND_SCR */
-
-/* card command class */
-#define SD_CCC_SWITCH                          BIT(10)       /* class 10 */
-#define SD_CCC_IO_MODE                         BIT(9)        /* class 9 */
-#define SD_CCC_APPLICATION_SPECIFIC            BIT(8)        /* class 8 */
-#define SD_CCC_LOCK_CARD                       BIT(7)        /* class 7 */
-#define SD_CCC_WRITE_PROTECTION                BIT(6)        /* class 6 */
-#define SD_CCC_ERASE                           BIT(5)        /* class 5 */
-#define SD_CCC_BLOCK_WRITE                     BIT(4)        /* class 4 */
-#define SD_CCC_BLOCK_READ                      BIT(2)        /* class 2 */
-#define SD_CCC_BASIC                           BIT(0)        /* class 0 */
-
-/* SD card data transmission mode */
-#define SD_DMA_MODE                           ((uint32_t)0x00000000) /* DMA mode */
-#define SD_POLLING_MODE                       ((uint32_t)0x00000001) /* polling mode */
-
-/* lock unlock status */
-#define SD_LOCK                               ((uint8_t)0x05)        /* lock the SD card */
-#define SD_UNLOCK                             ((uint8_t)0x02)        /* unlock the SD card */
-
-/* supported memory cards types */
-typedef enum {
-    SDIO_STD_CAPACITY_SD_CARD_V1_1 = 0,   /* standard capacity SD card version 1.1 */
-    SDIO_STD_CAPACITY_SD_CARD_V2_0,       /* standard capacity SD card version 2.0 */
-    SDIO_HIGH_CAPACITY_SD_CARD,           /* high capacity SD card */
-    SDIO_SECURE_DIGITAL_IO_CARD,          /* secure digital IO card */
-    SDIO_SECURE_DIGITAL_IO_COMBO_CARD,    /* secure digital IO combo card */
-    SDIO_MULTIMEDIA_CARD,                 /* multimedia card */
-    SDIO_HIGH_CAPACITY_MULTIMEDIA_CARD,   /* high capacity multimedia card */
-    SDIO_HIGH_SPEED_MULTIMEDIA_CARD       /* high speed multimedia card */
-} sdio_card_type_enum;
-
-/* card identification (CID) register */
-typedef struct {
-    __IO uint8_t mid;                     /* manufacturer ID */
-    __IO uint16_t oid;                    /* OEM/application ID */
-    __IO uint32_t pnm0;                   /* product name */
-    __IO uint8_t pnm1;                    /* product name */
-    __IO uint8_t prv;                     /* product revision */
-    __IO uint32_t psn;                    /* product serial number */
-    __IO uint16_t mdt;                    /* manufacturing date */
-    __IO uint8_t cid_crc;                 /* CID CRC7 checksum */
-} sd_cid_struct;
-
-/* CSD register (CSD version 1.0 and 2.0) */
-typedef struct {
-    __IO uint8_t csd_struct;              /* CSD struct */
-    __IO uint8_t taac;                    /* data read access-time */
-    __IO uint8_t nsac;                    /* data read access-time in CLK cycles */
-    __IO uint8_t tran_speed;              /* max. data transfer rate */
-    __IO uint16_t ccc;                    /* card command classes */
-    __IO uint8_t read_bl_len;             /* max. read data block length */
-    __IO uint8_t read_bl_partial;         /* partial blocks for read allowed */
-    __IO uint8_t write_blk_misalign;      /* write block misalignment */
-    __IO uint8_t read_blk_misalign;       /* read block misalignment */
-    __IO uint8_t dsp_imp;                 /* DSR implemented */
-    __IO uint32_t c_size;                 /* device size, 12 bits in CSD version 1.0, 22 bits in CSD version 2.0 */
-    __IO uint8_t vdd_r_curr_min;          /* max. read current @VDD min, CSD version 1.0 */
-    __IO uint8_t vdd_r_curr_max;          /* max. read current @VDD max, CSD version 1.0 */
-    __IO uint8_t vdd_w_curr_min;          /* max. write current @VDD min, CSD version 1.0 */
-    __IO uint8_t vdd_w_curr_max;          /* max. write current @VDD max, CSD version 1.0 */
-    __IO uint8_t c_size_mult;             /* device size multiplier, CSD version 1.0 */
-    __IO uint8_t erase_blk_en;            /* erase single block enable */
-    __IO uint8_t sector_size;             /* erase sector size */
-    __IO uint8_t wp_grp_size;             /* write protect group size */
-    __IO uint8_t wp_grp_enable;           /* write protect group enable */
-    __IO uint8_t r2w_factor;              /* write speed factor */
-    __IO uint8_t write_bl_len;            /* max. write data block length */
-    __IO uint8_t write_bl_partial;        /* partial blocks for write allowed */
-    __IO uint8_t file_format_grp;         /* file format group */
-    __IO uint8_t copy_flag;               /* copy flag (OTP) */
-    __IO uint8_t perm_write_protect;      /* permanent write protection */
-    __IO uint8_t tmp_write_protect;       /* temporary write protection */
-    __IO uint8_t file_format;             /* file format */
-    __IO uint8_t csd_crc;                 /* CSD CRC checksum */
-} sd_csd_struct;
-
-/* information of card */
-typedef struct {
-    sd_cid_struct card_cid;               /* CID register */
-    sd_csd_struct card_csd;               /* CSD register */
-    sdio_card_type_enum card_type;        /* card tpye */
-    uint32_t card_capacity;               /* card capacity */
-    uint32_t card_blocksize;              /* card block size */
-    uint16_t card_rca;                    /* card relative card address */
-} sd_card_info_struct;
-
-/* SD error flags */
-typedef enum {
-    SD_OUT_OF_RANGE = 0,                  /* command's argument was out of range */
-    SD_ADDRESS_ERROR,                     /* misaligned address which did not match the block length */
-    SD_BLOCK_LEN_ERROR,                   /* transferred block length is not allowed for the card or the number of transferred bytes does not match the block length */
-    SD_ERASE_SEQ_ERROR,                   /* an error in the sequence of erase command occurs */
-    SD_ERASE_PARAM,                       /* an invalid selection of write-blocks for erase occurred */
-    SD_WP_VIOLATION,                      /* attempt to program a write protect block or permanent write protected card */
-    SD_LOCK_UNLOCK_FAILED,                /* sequence or password error has been detected in lock/unlock card command */
-    SD_COM_CRC_ERROR,                     /* CRC check of the previous command failed */
-    SD_ILLEGAL_COMMAND,                   /* command not legal for the card state */
-    SD_CARD_ECC_FAILED,                   /* card internal ECC was applied but failed to correct the data */
-    SD_CC_ERROR,                          /* internal card controller error */
-    SD_GENERAL_UNKNOWN_ERROR,             /* general or unknown error occurred during the operation */
-    SD_CSD_OVERWRITE,                     /* read only section of the CSD does not match the card content or an attempt to reverse the copy or permanent WP bits was made */
-    SD_WP_ERASE_SKIP,                     /* only partial address space was erased or the temporary or permanent write protected card was erased */
-    SD_CARD_ECC_DISABLED,                 /* command has been executed without using internal ECC */
-    SD_ERASE_RESET,                       /* erase sequence was cleared before executing because an out of erase sequence command was received */
-    SD_AKE_SEQ_ERROR,                     /* error in the sequence of the authentication process */
-
-    SD_CMD_CRC_ERROR,                     /* command response received (CRC check failed) */
-    SD_DATA_CRC_ERROR,                    /* data block sent/received (CRC check failed) */
-    SD_CMD_RESP_TIMEOUT,                  /* command response timeout */
-    SD_DATA_TIMEOUT,                      /* data timeout */
-    SD_TX_UNDERRUN_ERROR,                 /* transmit FIFO underrun error occurs */
-    SD_RX_OVERRUN_ERROR,                  /* received FIFO overrun error occurs */
-    SD_START_BIT_ERROR,                   /* start bit error in the bus */
-
-    SD_VOLTRANGE_INVALID,                 /* the voltage range is invalid */
-    SD_PARAMETER_INVALID,                 /* the parameter is invalid */
-    SD_OPERATION_IMPROPER,                /* the operation is improper */
-    SD_FUNCTION_UNSUPPORTED,              /* the function is unsupported */
-    SD_ERROR,                             /* an error occurred */
-    SD_OK                                 /* no error occurred */
-} sd_error_enum;
-
-typedef enum {
-    SD_NO_TRANSFER = 0,                     /* no data transfer is acting */
-    SD_TRANSFER_IN_PROGRESS                 /* data transfer is in progress */
-} sd_transfer_state_enum;
-
-extern uint32_t sd_scr[2];                /* SD card SCR */
-
-/* function declarations */
-/* initialize the SD card and make it in standby state */
-sd_error_enum sd_init(void);
-/* initialize the card and get CID and CSD of the card */
-sd_error_enum sd_card_init(void);
-/* configure the clock and the work voltage, and get the card type */
-sd_error_enum sd_power_on(void);
-/* close the power of SDIO */
-sd_error_enum sd_power_off(void);
-
-/* configure the bus mode */
-sd_error_enum sd_bus_mode_config(uint32_t busmode);
-/* configure the mode of transmission */
-sd_error_enum sd_transfer_mode_config(uint32_t txmode);
-
-typedef void (*sdio_callback_t)(uint32_t bytes_done);
-/* read a block data into a buffer from the specified address of a card */
-sd_error_enum sd_block_read(uint32_t *preadbuffer, uint64_t readaddr, uint16_t blocksize, sdio_callback_t callback);
-/* read multiple blocks data into a buffer from the specified address of a card */
-sd_error_enum sd_multiblocks_read(uint32_t *preadbuffer, uint64_t readaddr, uint16_t blocksize, uint32_t blocksnumber, sdio_callback_t callback);
-/* write a block data to the specified address of a card */
-sd_error_enum sd_block_write(uint32_t *pwritebuffer, uint64_t writeaddr, uint16_t blocksize, sdio_callback_t callback);
-/* write multiple blocks data to the specified address of a card */
-sd_error_enum sd_multiblocks_write(uint32_t *pwritebuffer, uint64_t writeaddr, uint16_t blocksize, uint32_t blocksnumber, sdio_callback_t callback);
-/* erase a continuous area of a card */
-sd_error_enum sd_erase(uint64_t startaddr, uint64_t endaddr);
-/* process all the interrupts which the corresponding flags are set */
-sd_error_enum sd_interrupts_process(void);
-
-/* select or deselect a card */
-sd_error_enum sd_card_select_deselect(uint16_t cardrca);
-/* get the card status */
-sd_error_enum sd_cardstatus_get(uint32_t *pcardstatus);
-/* get the SD card status */
-sd_error_enum sd_sdstatus_get(uint32_t *psdstatus);
-/* stop an ongoing data transfer */
-sd_error_enum sd_transfer_stop(void);
-/* lock or unlock a card */
-sd_error_enum sd_lock_unlock(uint8_t lockstate);
-
-/* get the data transfer state */
-sd_transfer_state_enum sd_transfer_state_get(void);
-/* get SD card capacity(KB) */
-uint32_t sd_card_capacity_get(void);
-/* get the detailed information of the SD card based on received CID and CSD */
-sd_error_enum sd_card_information_get(sd_card_info_struct *pcardinfo);
-sd_error_enum sd_card_information_get_short(sdio_card_type_enum *card_type, uint16_t *card_rca);
-
-/* Get card information in raw format */
-void sd_cid_get(uint8_t *cid);
-void sd_csd_get(uint8_t *csd);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* SDCARD_H */

+ 0 - 209
lib/ZuluSCSI_platform_GD32F205/greenpak.cpp

@@ -1,209 +0,0 @@
-/** 
- * ZuluSCSI™ - Copyright (c) 2022-2025 Rabbit Hole Computing™
- * 
- * ZuluSCSI™ firmware is licensed under the GPL version 3 or any later version. 
- * 
- * https://www.gnu.org/licenses/gpl-3.0.html
- * ----
- * 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 <https://www.gnu.org/licenses/>.
-**/
-
-// I2C communication with GreenPAK.
-// This uses bitbanging for I2C so that internal GPIO pull-up can be used
-// and to avoid the bugs that are present in STM32F2 I2C peripheral,
-// it is uncertain if the same bugs apply to GD32F2.
-
-#include "ZuluSCSI_platform.h"
-#include "ZuluSCSI_log.h"
-#include "greenpak.h"
-#include "greenpak_fw.h"
-
-#ifndef GREENPAK_I2C_PORT
-
-bool greenpak_write(uint16_t regaddr, const uint8_t *data, int length) { return false; }
-bool greenpak_read(uint16_t regaddr, uint8_t *data, int length) { return false; }
-bool greenpak_load_firmware() { return false; }
-bool greenpak_is_ready() { return false; }
-
-#else
-
-bool g_greenpak_is_ready;
-
-// SCL is driven as push-pull, SDA is driven as IPU / OUT_OD
-#define I2C_SCL_HI() GPIO_BOP(GREENPAK_I2C_PORT) = GREENPAK_I2C_SCL
-#define I2C_SCL_LO() GPIO_BC(GREENPAK_I2C_PORT) = GREENPAK_I2C_SCL
-#define I2C_SDA_HI() gpio_init(GREENPAK_I2C_PORT, GPIO_MODE_IPU, 0, GREENPAK_I2C_SDA)
-#define I2C_SDA_LO() gpio_init(GREENPAK_I2C_PORT, GPIO_MODE_OUT_OD, GPIO_OSPEED_2MHZ, GREENPAK_I2C_SDA), GPIO_BC(GREENPAK_I2C_PORT) = GREENPAK_I2C_SDA
-#define I2C_SDA_READ() (GPIO_ISTAT(GREENPAK_I2C_PORT) & GREENPAK_I2C_SDA)
-#define I2C_DELAY() delay_ns(10000);
-
-static void greenpak_gpio_init()
-{
-    gpio_bit_set(GREENPAK_I2C_PORT, GREENPAK_I2C_SCL | GREENPAK_I2C_SDA);
-    gpio_init(GREENPAK_I2C_PORT, GPIO_MODE_IPU, 0, GREENPAK_I2C_SDA);
-    gpio_init(GREENPAK_I2C_PORT, GPIO_MODE_OUT_PP, GPIO_OSPEED_2MHZ, GREENPAK_I2C_SCL);
-
-    // Data bits used for communication
-    uint32_t greenpak_io = GREENPAK_PLD_IO1 | GREENPAK_PLD_IO2 | GREENPAK_PLD_IO3;
-    gpio_bit_reset(SCSI_OUT_PORT, greenpak_io);
-    gpio_init(SCSI_OUT_PORT, GPIO_MODE_OUT_PP, GPIO_OSPEED_50MHZ, greenpak_io);
-}
-
-static void i2c_writebit(bool bit)
-{
-    if (bit)
-        I2C_SDA_HI();
-    else
-        I2C_SDA_LO();
-
-    I2C_DELAY();
-    I2C_SCL_HI();
-    I2C_DELAY();
-    I2C_SCL_LO();
-}
-
-static bool i2c_readbit()
-{
-    I2C_SDA_HI(); // Pull-up
-    I2C_DELAY();
-    I2C_SCL_HI();
-    I2C_DELAY();
-    bool result = I2C_SDA_READ();
-    I2C_SCL_LO();
-    return result;
-}
-
-// Write byte to I2C bus, return ACK bit status
-static bool i2c_writebyte(uint8_t byte)
-{
-    for (int i = 0; i < 8; i++)
-    {
-        i2c_writebit(byte & (0x80 >> i));
-    }
-    return !i2c_readbit();
-}
-
-// Read byte from I2C bus
-static uint8_t i2c_readbyte(bool ack)
-{
-    uint8_t result = 0;
-    for (int i = 0; i < 8; i++)
-    {
-        result |= i2c_readbit() << (7 - i);
-    }
-
-    i2c_writebyte(!ack);
-    return result;
-}
-
-static bool i2c_start(uint8_t device_addr)
-{
-    // Initial signal state
-    I2C_SCL_HI();
-    I2C_SDA_HI();
-    I2C_DELAY();
-
-    // Start condition
-    I2C_SDA_LO();
-    I2C_DELAY();
-    
-    I2C_SCL_LO();
-    I2C_DELAY();
-
-    // Device address
-    return i2c_writebyte(device_addr);
-}
-
-static void i2c_stop()
-{
-    I2C_SDA_LO();
-    I2C_DELAY();
-    I2C_SCL_HI();
-    I2C_DELAY();
-    I2C_SDA_HI();
-    I2C_DELAY();
-}
-
-bool greenpak_write(uint16_t regaddr, const uint8_t *data, int length)
-{
-    bool status = true;
-    uint16_t blockaddr = regaddr >> 8;
-    status &= i2c_start(GREENPAK_I2C_ADDR | (blockaddr << 1));
-    status &= i2c_writebyte(regaddr & 0xFF);
-    
-    for (int i = 0; i < length; i++)
-    {
-        status &= i2c_writebyte(data[i]);
-    }
-
-    i2c_stop();
-    return status;
-}
-
-bool greenpak_read(uint16_t regaddr, uint8_t *data, int length)
-{
-    bool status = true;
-    uint16_t blockaddr = (regaddr >> 8) & 7;
-    status &= i2c_start(GREENPAK_I2C_ADDR | (blockaddr << 1));
-    status &= i2c_writebyte(regaddr & 0xFF);
-
-    status &= i2c_start(GREENPAK_I2C_ADDR | (blockaddr << 1) | 1);
-    
-    for (int i = 0; i < length; i++)
-    {
-        data[i] = i2c_readbyte(i < length - 1);
-    }
-
-    i2c_stop();
-    return status;
-}
-
-bool greenpak_load_firmware()
-{
-    uint8_t dummy;
-    greenpak_gpio_init();
-
-    if (!greenpak_read(0, &dummy, 1))
-    {
-        logmsg("Optional GreenPAK not detected");
-        return false;
-    }
-    else
-    {
-        logmsg("Optional GreenPAK detected, loading firmware");
-    }
-
-    if (!greenpak_write(0, g_greenpak_fw, sizeof(g_greenpak_fw)))
-    {
-        logmsg("GreenPAK firmware loading failed");
-        return false;
-    }
-    else
-    {
-        logmsg("GreenPAK firmware successfully loaded");
-        LED_ON();
-        delay(10);
-        LED_OFF();
-        delay(100);
-        g_greenpak_is_ready = true;
-        return true;
-    }
-}
-
-bool greenpak_is_ready()
-{
-    return g_greenpak_is_ready;
-}
-
-#endif

+ 0 - 34
lib/ZuluSCSI_platform_GD32F205/greenpak.h

@@ -1,34 +0,0 @@
-/** 
- * ZuluSCSI™ - Copyright (c) 2022-2025 Rabbit Hole Computing™
- * 
- * ZuluSCSI™ firmware is licensed under the GPL version 3 or any later version. 
- * 
- * https://www.gnu.org/licenses/gpl-3.0.html
- * ----
- * 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 <https://www.gnu.org/licenses/>.
-**/
-
-// External GreenPAK SLG46824 programmable logic can optionally be used to
-// accelerate SCSI communications. This module contains code to load firmware
-// to the GreenPAK through I2C.
-
-#pragma once
-
-#include <stdint.h>
-
-bool greenpak_write(uint16_t regaddr, const uint8_t *data, int length);
-bool greenpak_read(uint16_t regaddr, uint8_t *data, int length);
-
-bool greenpak_load_firmware();
-bool greenpak_is_ready();

+ 0 - 46
lib/ZuluSCSI_platform_GD32F205/greenpak_fw.h

@@ -1,46 +0,0 @@
-/** 
- * ZuluSCSI™ - Copyright (c) 2022-2025 Rabbit Hole Computing™
- * 
- * ZuluSCSI™ firmware is licensed under the GPL version 3 or any later version. 
- * 
- * https://www.gnu.org/licenses/gpl-3.0.html
- * ----
- * 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 <https://www.gnu.org/licenses/>.
-**/
-
-
-const uint8_t g_greenpak_fw[] = {
-  0xc4, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0xc2, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd0, 0x08,
-  0x13, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe7, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x30, 0x70, 0x00, 0x30, 0x20, 0x30, 0x30, 0x00, 0x00, 0x30, 0x30,
-  0x30, 0x00, 0x30, 0x30, 0x30, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x14, 0x22, 0x30, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0xd7, 0x14, 0x20, 0x00, 0x01, 0x00, 0x00,
-  0x00, 0x02, 0x01, 0x00, 0x00, 0x02, 0x00, 0x01, 0x00, 0x00, 0x02, 0x01,
-  0x00, 0x00, 0x02, 0x00, 0x01, 0x00, 0x00, 0x02, 0x01, 0x00, 0x00, 0x02,
-  0x00, 0x01, 0x00, 0x00, 0x02, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x01,
-  0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0xa5
-};

+ 0 - 106
lib/ZuluSCSI_platform_GD32F205/platform_hw_config.cpp

@@ -1,106 +0,0 @@
-/** 
- * ZuluSCSI™ - Copyright (c) 2023-2025 Rabbit Hole Computing™
- * 
- * ZuluSCSI™ firmware is licensed under the GPL version 3 or any later version. 
- * 
- * https://www.gnu.org/licenses/gpl-3.0.html
- * ----
- * 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 <https://www.gnu.org/licenses/>.
-**/
-#include "ZuluSCSI_platform.h"
-
-#ifdef ZULUSCSI_HARDWARE_CONFIG
-#include "platform_hw_config.h"
-#include <ZuluSCSI_config.h>
-#include <ZuluSCSI_log.h>
-#include <ZuluSCSI_settings.h>
-
-HardwareConfig g_hw_config;
-
-bool hw_config_is_active()
-{
-    return g_hw_config.is_active();
-}
-
-void hw_config_init_gpios()
-{
-    g_hw_config.init_gpios();
-}
-
-void hw_config_init_state(bool is_active)
-{
-    g_hw_config.init_state(is_active);
-}
-
-void HardwareConfig::init_gpios()
-{
-    // SCSI ID dip switch
-    gpio_init(DIPSW_SCSI_ID_BIT_PORT, GPIO_MODE_IPD, 0, DIPSW_SCSI_ID_BIT_PINS);
-    
-    // Device select BCD rotary dip switch
-    gpio_init(DIPROT_DEVICE_SEL_BIT_PORT, GPIO_MODE_IPD, 0, DIPROT_DEVICE_SEL_BIT_PINS);
-
-    LED_EJECT_OFF();
-    gpio_init(LED_EJECT_PORT, GPIO_MODE_OUT_PP, GPIO_OSPEED_2MHZ, LED_EJECT_PIN);
-}
-
-void HardwareConfig::init_state(bool is_active)
-{
-    m_is_active = is_active;
-    if (m_is_active)
-    {
-        m_scsi_id = (gpio_input_port_get(DIPSW_SCSI_ID_BIT_PORT) & DIPSW_SCSI_ID_BIT_PINS) >> DIPSW_SCSI_ID_BIT_SHIFT;
-        m_device_preset = DEV_PRESET_NONE;
-
-        uint8_t rotary_select = (gpio_input_port_get(DIPROT_DEVICE_SEL_BIT_PORT) & DIPROT_DEVICE_SEL_BIT_PINS) >> DIPROT_DEVICE_SEL_BIT_SHIFT;
-        switch (rotary_select)
-        {
-        case 0:
-            m_device_type = S2S_CFG_FIXED;
-        break;
-        case 1:
-            m_device_type = S2S_CFG_OPTICAL;
-        break;
-        case 2:
-            m_device_type = S2S_CFG_FLOPPY_14MB;
-        break;
-        case 3:
-            m_device_type = S2S_CFG_REMOVABLE;
-        break;
-        case 4:
-            m_device_type = S2S_CFG_MO;
-        break;
-        case 5:
-            m_device_preset = DEV_PRESET_ST32430N;
-            m_device_type = S2S_CFG_FIXED;
-        break;
-        case 6:
-            m_device_type = S2S_CFG_SEQUENTIAL;
-        break;
-        default:
-            m_device_type = S2S_CFG_FIXED;
-        }
-
-        if (m_device_type == S2S_CFG_OPTICAL)
-        {
-            m_blocksize = DEFAULT_BLOCKSIZE_OPTICAL;
-        }
-        else
-        {
-            m_blocksize = RAW_FALLBACK_BLOCKSIZE;
-        }
-    }
-}
-
-#endif // ZULUSCSI_HARDWARE_CONFIG

+ 0 - 77
lib/ZuluSCSI_platform_GD32F205/platform_hw_config.h

@@ -1,77 +0,0 @@
-/** 
- * ZuluSCSI™ - Copyright (c) 2023-2025 Rabbit Hole Computing™
- * 
- * ZuluSCSI™ firmware is licensed under the GPL version 3 or any later version. 
- * 
- * https://www.gnu.org/licenses/gpl-3.0.html
- * ----
- * 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 <https://www.gnu.org/licenses/>.
-**/
-
-/**
- * Configuration of the ZuluSCSI set by hardware rotary and standard DIP switches
- * Settings include SCSI ID, device type, and if hardware config is active 
-*/
-
-#pragma once
-#ifdef ZULUSCSI_HARDWARE_CONFIG
-#include <scsi2sd.h>
-#include <ZuluSCSI_settings.h>
-
-// C wrappers
-#ifdef __cplusplus
-extern "C"
-{
-#endif
-    S2S_CFG_TYPE hw_config_selected_device();
-    bool hw_config_is_active();
-    void hw_config_init_gpios();
-    void hw_config_init_state(bool is_active);
-    
-#ifdef __cplusplus
-}
-#endif
-
-#ifdef __cplusplus
-class HardwareConfig
-{
-public:
-    // Initialize GPIOs
-    void init_gpios();
-
-    // Initialize device state settings
-    void init_state(bool is_active);
-
-    // get the device type
-    // @returns the device type
-    const S2S_CFG_TYPE& device_type() const {return m_device_type;}
-    const uint8_t& scsi_id()          const {return m_scsi_id;}
-    const bool& is_active()           const {return m_is_active;}
-    const int blocksize()             const {return m_blocksize;}
-    const scsi_device_preset_t device_preset() const {return m_device_preset;}
-
-protected:
-    S2S_CFG_TYPE m_device_type;
-    uint8_t m_scsi_id;
-    bool m_is_active;
-    int m_blocksize;
-    scsi_device_preset_t m_device_preset;
-};
-
-
-// global hardware configuration
-extern HardwareConfig g_hw_config;
-
-#endif // __cplusplus
-#endif // ZULUSCSI_HARDWARE_CONFIG

+ 0 - 37
lib/ZuluSCSI_platform_GD32F205/scsi2sd_time.h

@@ -1,37 +0,0 @@
-/** 
- * SCSI2SD V6 - Copyright (C) 2014 Michael McMaster <michael@codesrc.com>
- * ZuluSCSI™ - Copyright (c) 2022-2025 Rabbit Hole Computing™
- * 
- * This file is licensed under the GPL version 3 or any later version.  
- * It is derived from time.h in SCSI2SD V6.
- *  
- * https://www.gnu.org/licenses/gpl-3.0.html
- * ----
- * 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 <https://www.gnu.org/licenses/>.
-**/
-
-// Timing functions for SCSI2SD.
-// This file is derived from time.h in SCSI2SD-V6.
-
-#pragma once
-
-#include <stdint.h>
-#include "ZuluSCSI_platform.h"
-
-#define s2s_getTime_ms() millis()
-#define s2s_elapsedTime_ms(since) ((uint32_t)(millis() - (since)))
-#define s2s_delay_ms(x) delay_ns(x * 1000000)
-#define s2s_delay_us(x) delay_ns(x * 1000)
-#define s2s_delay_ns(x) delay_ns(x)
-

+ 0 - 26
lib/ZuluSCSI_platform_GD32F205/scsi2sd_timings.c

@@ -1,26 +0,0 @@
-/**
- * ZuluSCSI™ - Copyright (c) 2024-2025 Rabbit Hole Computing™
- *
- * ZuluSCSI™ firmware is licensed under the GPL version 3 or any later version.
- *
- * https://www.gnu.org/licenses/gpl-3.0.html
- * ----
- * 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 <https://www.gnu.org/licenses/>.
-**/
-#include "timings.h"
-uint8_t g_max_sync_20_period = 25;
-uint8_t g_max_sync_10_period = 25;
-uint8_t g_max_sync_5_period  = 50;
-uint8_t g_force_sync = 0;
-uint8_t g_force_offset = 15;

+ 0 - 648
lib/ZuluSCSI_platform_GD32F205/scsiPhy.cpp

@@ -1,648 +0,0 @@
-/** 
- * SCSI2SD V6 - Copyright (C) 2013 Michael McMaster <michael@codesrc.com>
- * ZuluSCSI™ - Copyright (c) 2022-2025 Rabbit Hole Computing™
- * 
- * This file is licensed under the GPL version 3 or any later version.  
- * It is derived from scsiPhy.c in SCSI2SD V6.
- * 
- * https://www.gnu.org/licenses/gpl-3.0.html
- * ----
- * 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 <https://www.gnu.org/licenses/>.
-**/
-
-// Implements the low level interface to SCSI bus
-// Partially derived from scsiPhy.c from SCSI2SD-V6
-
-#include "scsiPhy.h"
-#include "ZuluSCSI_platform.h"
-#include "scsi_accel_asm.h"
-#include "scsi_accel_dma.h"
-#include "scsi_accel_greenpak.h"
-#include "scsi_accel_sync.h"
-#include "ZuluSCSI_log.h"
-#include "ZuluSCSI_log_trace.h"
-#include "ZuluSCSI_config.h"
-#include "ZuluSCSI_settings.h"
-#include <minIni.h>
-
-#include <scsi2sd.h>
-extern "C" {
-#include <scsi.h>
-#include <scsi2sd_time.h>
-}
-
-// Acceleration mode in use
-static enum {
-    PHY_MODE_BEST_AVAILABLE = 0,
-    PHY_MODE_PIO = 1,
-    PHY_MODE_DMA_TIMER = 2,
-    PHY_MODE_GREENPAK_PIO = 3,
-    PHY_MODE_GREENPAK_DMA = 4
-} g_scsi_phy_mode;
-static const char *g_scsi_phy_mode_names[] = {
-    "Unknown", "PIO", "DMA_TIMER", "GREENPAK_PIO", "GREENPAK_DMA"
-};
-
-// State of polling write request
-static struct {
-    const uint8_t *data;
-    uint32_t count;
-    bool use_sync_mode;
-} g_scsi_writereq;
-
-static void init_irqs();
-
-/***********************/
-/* SCSI status signals */
-/***********************/
-
-extern "C" bool scsiStatusATN()
-{
-    return SCSI_IN(ATN);
-}
-
-extern "C" bool scsiStatusBSY()
-{
-    return SCSI_IN(BSY);
-}
-
-/************************/
-/* SCSI selection logic */
-/************************/
-
-volatile uint8_t g_scsi_sts_selection;
-volatile uint8_t g_scsi_ctrl_bsy;
-
-static void scsi_bsy_deassert_interrupt()
-{
-    if (!SCSI_IN(BSY) && ((g_moved_select_in && SCSI_IN(ODE_SEL)) || (!g_moved_select_in && SCSI_IN(SEL))))
-    {
-        uint8_t sel_bits = SCSI_IN_DATA();
-        int sel_id = -1;
-        for (int i = 0; i < S2S_MAX_TARGETS; i++)
-        {
-            if (scsiDev.targets[i].targetId <= 7 && scsiDev.targets[i].cfg)
-            {
-                if (sel_bits & (1 << scsiDev.targets[i].targetId))
-                {
-                    sel_id = scsiDev.targets[i].targetId;
-                    break;
-                }
-            }
-        }
-
-        if (sel_id >= 0)
-        {
-            uint8_t atn_flag = SCSI_IN(ATN) ? SCSI_STS_SELECTION_ATN : 0;
-            g_scsi_sts_selection = SCSI_STS_SELECTION_SUCCEEDED | atn_flag | sel_id;
-        }
-
-        // selFlag is required for Philips P2000C which releases it after 600ns
-        // without waiting for BSY.
-        // Also required for some early Mac Plus roms
-        scsiDev.selFlag = *SCSI_STS_SELECTED;
-    }
-}
-
-extern "C" bool scsiStatusSEL()
-{
-    if (g_scsi_ctrl_bsy)
-    {
-        // We don't have direct register access to BSY bit like SCSI2SD scsi.c expects.
-        // Instead update the state here.
-        // Releasing happens with bus release.
-        g_scsi_ctrl_bsy = 0;
-        SCSI_OUT(BSY, 1);
-    }
-
-    if (g_moved_select_in)
-    {
-        return SCSI_IN(ODE_SEL);
-    }
-    return SCSI_IN(SEL);
-     
-}
-
-/************************/
-/* SCSI bus reset logic */
-/************************/
-
-static void scsi_rst_assert_interrupt()
-{
-    bool rst1 = SCSI_IN(RST);
-    delay_ns(500);
-    bool rst2 = SCSI_IN(RST);
-
-    if (rst1 && rst2)
-    {
-        dbgmsg("BUS RESET");
-        scsiDev.resetFlag = 1;
-    }
-}
-
-static void selectPhyMode()
-{
-    int oldmode = g_scsi_phy_mode;
-
-    // Read overriding setting from configuration file
-    int wanted_mode = g_scsi_settings.getSystem()->phyMode;
-
-    // Default: software GPIO bitbang, available on all revisions
-    g_scsi_phy_mode = PHY_MODE_PIO;
-    
-    // Timer based DMA bitbang, available on V1.1, 2.8 MB/s
-#ifdef SCSI_ACCEL_DMA_AVAILABLE
-    if (wanted_mode == PHY_MODE_BEST_AVAILABLE || wanted_mode == PHY_MODE_DMA_TIMER)
-    {
-        g_scsi_phy_mode = PHY_MODE_DMA_TIMER;
-    }
-#endif
-
-    // GreenPAK with software write, available on V1.1 with extra chip, 3.5 MB/s
-    if (wanted_mode == PHY_MODE_BEST_AVAILABLE || wanted_mode == PHY_MODE_GREENPAK_PIO)
-    {
-        if (greenpak_is_ready())
-        {
-            g_scsi_phy_mode = PHY_MODE_GREENPAK_PIO;
-        }
-    }
-
-    // GreenPAK with DMA write, available on V1.1 with extra chip
-#ifdef SCSI_ACCEL_DMA_AVAILABLE
-    if (wanted_mode == PHY_MODE_BEST_AVAILABLE || wanted_mode == PHY_MODE_GREENPAK_DMA)
-    {
-        if (greenpak_is_ready())
-        {
-            g_scsi_phy_mode = PHY_MODE_GREENPAK_DMA;
-        }
-    }
-#endif
-
-    if (g_scsi_phy_mode != oldmode)
-    {
-        logmsg("SCSI PHY operating mode: ", g_scsi_phy_mode_names[g_scsi_phy_mode]);
-    }
-}
-
-extern "C" void scsiPhyReset(void)
-{
-    SCSI_RELEASE_OUTPUTS();
-    scsi_accel_dma_stopWrite();
-
-    g_scsi_sts_selection = 0;
-    g_scsi_ctrl_bsy = 0;
-    g_scsi_writereq.count = 0;
-    init_irqs();
-
-#ifdef SCSI_SYNC_MODE_AVAILABLE
-    scsi_accel_sync_init();
-#endif
-
-    selectPhyMode();
-
-    if (g_scsi_phy_mode == PHY_MODE_DMA_TIMER)
-    {
-        scsi_accel_timer_dma_init();
-    }
-    else if (g_scsi_phy_mode == PHY_MODE_GREENPAK_DMA)
-    {
-        scsi_accel_greenpak_dma_init();
-    }
-}
-
-/************************/
-/* SCSI bus phase logic */
-/************************/
-
-static SCSI_PHASE g_scsi_phase;
-
-extern "C" void scsiEnterPhase(int phase)
-{
-    int delay = scsiEnterPhaseImmediate(phase);
-    if (delay > 0)
-    {
-        s2s_delay_ns(delay);
-    }
-}
-
-// Change state and return nanosecond delay to wait
-extern "C" uint32_t scsiEnterPhaseImmediate(int phase)
-{
-    if (phase != g_scsi_phase)
-    {
-        // ANSI INCITS 362-2002 SPI-3 10.7.1:
-        // Phase changes are not allowed while REQ or ACK is asserted.
-        while (likely(!scsiDev.resetFlag) && SCSI_IN(ACK)) {}
-
-        if (scsiDev.compatMode < COMPAT_SCSI2 && (phase == DATA_IN || phase == DATA_OUT))
-        {
-            // Akai S1000/S3000 seems to need extra delay before changing to data phase
-            // after a command. The code in ZuluSCSI_disk.cpp tries to do this while waiting
-            // for SD card, to avoid any extra latency.
-            s2s_delay_ns(400000);
-        }
-
-        int oldphase = g_scsi_phase;
-        g_scsi_phase = (SCSI_PHASE)phase;
-        scsiLogPhaseChange(phase);
-        
-        if (phase < 0)
-        {
-            // Other communication on bus or reset state
-            SCSI_RELEASE_OUTPUTS();
-            return 0;
-        }
-        else
-        {
-            SCSI_OUT(MSG, phase & __scsiphase_msg);
-            SCSI_OUT(CD,  phase & __scsiphase_cd);
-            SCSI_OUT(IO,  phase & __scsiphase_io);
-        
-            int delayNs = 400; // Bus settle delay
-            if ((oldphase & __scsiphase_io) != (phase & __scsiphase_io))
-            {
-                delayNs += 400; // Data release delay
-            }
-
-            if (scsiDev.compatMode < COMPAT_SCSI2)
-            {
-                // EMU EMAX needs 100uS ! 10uS is not enough.
-                delayNs += 100000;
-            }
-
-            return delayNs;
-        }
-    }
-    else
-    {
-        return 0;
-    }
-}
-
-// Release all signals
-void scsiEnterBusFree(void)
-{
-    g_scsi_phase = BUS_FREE;
-    g_scsi_sts_selection = 0;
-    g_scsi_ctrl_bsy = 0;
-    scsiDev.cdbLen = 0;
-    
-    SCSI_RELEASE_OUTPUTS();
-}
-
-/********************/
-/* Transmit to host */
-/********************/
-
-#define SCSI_WAIT_ACTIVE(pin) \
-  if (!SCSI_IN(pin)) { \
-    if (!SCSI_IN(pin)) { \
-      while(!SCSI_IN(pin) && !scsiDev.resetFlag); \
-    } \
-  }
-
-#define SCSI_WAIT_INACTIVE(pin) \
-  if (SCSI_IN(pin)) { \
-    if (SCSI_IN(pin)) { \
-      while(SCSI_IN(pin) && !scsiDev.resetFlag); \
-    } \
-  }
-
-static inline void scsiWriteOneByte(uint8_t value)
-{
-    SCSI_OUT_DATA(value);
-    delay_100ns(); // DB setup time before REQ
-    SCSI_OUT(REQ, 1);
-    SCSI_WAIT_ACTIVE(ACK);
-    SCSI_RELEASE_DATA_REQ(); // Release data and REQ
-    SCSI_WAIT_INACTIVE(ACK);
-}
-
-extern "C" void scsiWriteByte(uint8_t value)
-{
-    scsiLogDataIn(&value, 1);
-    scsiWriteOneByte(value);
-}
-
-extern "C" void scsiWrite(const uint8_t* data, uint32_t count)
-{
-    scsiStartWrite(data, count);
-    scsiFinishWrite();
-}
-
-extern "C" void scsiStartWrite(const uint8_t* data, uint32_t count)
-{
-    scsiLogDataIn(data, count);
-
-    g_scsi_writereq.use_sync_mode = (g_scsi_phase == DATA_IN && scsiDev.target->syncOffset > 0);
-
-    if (g_scsi_phy_mode == PHY_MODE_PIO
-        || g_scsi_phy_mode == PHY_MODE_GREENPAK_PIO
-        || g_scsi_writereq.use_sync_mode)
-    {
-        // Software based bit-banging.
-        // Write requests are queued and then executed in isWriteFinished() callback.
-        // This allows better parallelism with SD card transfers.
-        
-        if (g_scsi_writereq.count)
-        {
-            if (data == g_scsi_writereq.data + g_scsi_writereq.count)
-            {
-                // Combine with previous one
-                g_scsi_writereq.count += count;
-                return;
-            }
-            else
-            {
-                // Actually execute previous request
-                scsiFinishWrite();
-            }
-        }
-
-        g_scsi_writereq.data = data;
-        g_scsi_writereq.count = count;
-    }
-    else if (g_scsi_phy_mode == PHY_MODE_DMA_TIMER || g_scsi_phy_mode == PHY_MODE_GREENPAK_DMA)
-    {
-        // Accelerated writes using DMA and timers
-        scsi_accel_dma_startWrite(data, count, &scsiDev.resetFlag);
-    }
-    else
-    {
-        logmsg("Unknown SCSI PHY mode: ", (int)g_scsi_phy_mode);
-    }
-}
-
-static void processPollingWrite(uint32_t count)
-{
-    if (count > g_scsi_writereq.count)
-        count = g_scsi_writereq.count;
-    
-    const uint8_t *data = g_scsi_writereq.data;
-    uint32_t count_words = count / 4;
-
-    if (g_scsi_writereq.use_sync_mode)
-    {
-        // Synchronous mode transfer
-        scsi_accel_sync_send(data, count, &scsiDev.resetFlag);
-    }
-    else if (count_words * 4 == count)
-    {
-        if (g_scsi_phy_mode == PHY_MODE_GREENPAK_PIO)
-        {
-            // GreenPAK PIO accelerated asynchronous transfer
-            scsi_accel_greenpak_send((const uint32_t*)data, count_words, &scsiDev.resetFlag);
-        }
-        else
-        {
-            // Assembler optimized asynchronous transfer
-            scsi_accel_asm_send((const uint32_t*)data, count_words, &scsiDev.resetFlag);
-        }
-    }
-    else
-    {
-        // Use simple loop for unaligned transfers
-        for (uint32_t i = 0; i < count; i++)
-        {
-            if (scsiDev.resetFlag) break;
-            scsiWriteOneByte(data[i]);
-        }
-    }
-
-    g_scsi_writereq.count -= count;
-    if (g_scsi_writereq.count)
-    {
-        g_scsi_writereq.data += count;
-    }
-    else
-    {
-        g_scsi_writereq.data = NULL;
-    }
-}
-
-static bool isPollingWriteFinished(const uint8_t *data)
-{
-    if (g_scsi_writereq.count)
-    {
-        if (data == NULL)
-        {
-            return false;
-        }
-        else if (data >= g_scsi_writereq.data &&
-            data < g_scsi_writereq.data + g_scsi_writereq.count)
-        {
-            return false;
-        }
-    }
-    return true;
-}
-
-extern "C" bool scsiIsWriteFinished(const uint8_t *data)
-{
-    // Check if there is still a polling transfer in progress
-    if (!isPollingWriteFinished(data))
-    {
-        if (check_sd_read_done())
-        {
-            // Current SD card transfer is finished so return early
-            // to start a new transfer before doing SCSI data transfer.
-            // This is faster because the SD transfer can run on background,
-            // but PIO mode SCSI transfer cannot.
-            return false;
-        }
-
-        // Process the transfer piece-by-piece while waiting
-        // for SD card to react.
-        int max_count = g_scsi_writereq.count / 8;
-        
-        // Always transfer whole sectors without pause to avoid problems with some SCSI hosts.
-        int bytesPerSector = 512;
-        if (scsiDev.target)
-        {
-            bytesPerSector = scsiDev.target->liveCfg.bytesPerSector;
-        }
-        if (max_count % bytesPerSector != 0) max_count -= (max_count % bytesPerSector);
-        if (max_count < bytesPerSector) max_count = bytesPerSector;
-        
-        // Avoid SysTick interrupt pauses during the transfer
-        SysTick_Handle_PreEmptively();
-
-        processPollingWrite(max_count);
-        return isPollingWriteFinished(data);
-    }
-    
-    if (g_scsi_phy_mode == PHY_MODE_DMA_TIMER || g_scsi_phy_mode == PHY_MODE_GREENPAK_DMA)
-    {
-        return scsi_accel_dma_isWriteFinished(data);
-    }
-    else
-    {
-        return true;
-    }
-}
-
-extern "C" void scsiFinishWrite()
-{
-    if (g_scsi_writereq.count)
-    {
-        // Finish previously started polling write request.
-        processPollingWrite(g_scsi_writereq.count);
-    }
-
-    if (g_scsi_phy_mode == PHY_MODE_DMA_TIMER || g_scsi_phy_mode == PHY_MODE_GREENPAK_DMA)
-    {
-        scsi_accel_dma_finishWrite(&scsiDev.resetFlag);
-    }
-}
-
-/*********************/
-/* Receive from host */
-/*********************/
-
-static inline uint8_t scsiReadOneByte(void)
-{
-    SCSI_OUT(REQ, 1);
-    SCSI_WAIT_ACTIVE(ACK);
-    delay_100ns();
-    uint8_t r = SCSI_IN_DATA();
-    SCSI_OUT(REQ, 0);
-    SCSI_WAIT_INACTIVE(ACK);
-
-    return r;
-}
-
-extern "C" uint8_t scsiReadByte(void)
-{
-    uint8_t r = scsiReadOneByte();
-    scsiLogDataOut(&r, 1);
-    return r;
-}
-
-extern "C" void scsiRead(uint8_t* data, uint32_t count, int* parityError)
-{
-    *parityError = 0;
-
-    uint32_t count_words = count / 4;
-    bool use_greenpak = (g_scsi_phy_mode == PHY_MODE_GREENPAK_DMA || g_scsi_phy_mode == PHY_MODE_GREENPAK_PIO);
-
-    SysTick_Handle_PreEmptively();
-
-    if (g_scsi_phase == DATA_OUT && scsiDev.target->syncOffset > 0)
-    {
-        // Synchronous data transfer
-        scsi_accel_sync_recv(data, count, parityError, &scsiDev.resetFlag);
-    }
-    else if (count_words * 4 == count && count_words >= 2 && use_greenpak)
-    {
-        // GreenPAK accelerated receive can handle a multiple of 4 bytes with minimum of 8 bytes.
-        scsi_accel_greenpak_recv((uint32_t*)data, count_words, &scsiDev.resetFlag);
-    }
-    else if (count_words * 4 == count && count_words >= 1)
-    {
-        // Optimized ASM subroutine can handle multiple of 4 bytes with minimum of 4 bytes.
-        scsi_accel_asm_recv((uint32_t*)data, count_words, &scsiDev.resetFlag);
-    }
-    else
-    {
-        // Use a simple loop for short and unaligned transfers
-        for (uint32_t i = 0; i < count; i++)
-        {
-            if (scsiDev.resetFlag) break;
-
-            data[i] = scsiReadOneByte();
-        }
-    }
-
-    scsiLogDataOut(data, count);
-}
-
-/**********************/
-/* Interrupt handlers */
-/**********************/
-
-extern "C"
-void SCSI_RST_IRQ (void)
-{
-    if (exti_interrupt_flag_get(SCSI_RST_EXTI))
-    {
-        exti_interrupt_flag_clear(SCSI_RST_EXTI);
-        scsi_rst_assert_interrupt();
-    }
-
-    if (exti_interrupt_flag_get(SCSI_BSY_EXTI))
-    {
-        exti_interrupt_flag_clear(SCSI_BSY_EXTI);
-        scsi_bsy_deassert_interrupt();
-    }
-
-    if ((g_moved_select_in && exti_interrupt_flag_get(SCSI_ODE_SEL_EXTI)) ||
-        (!g_moved_select_in && exti_interrupt_flag_get(SCSI_SEL_EXTI))
-       )
-    {
-        // Check BSY line status when SEL goes active.
-        // This is needed to handle SCSI-1 hosts that use the single initiator mode.
-        // The host will just assert the SEL directly, without asserting BSY first.
-        exti_interrupt_flag_clear(g_moved_select_in ? SCSI_ODE_SEL_EXTI : SCSI_SEL_EXTI);
-        scsi_bsy_deassert_interrupt();
-    }
-}
-
-#if SCSI_RST_IRQn != SCSI_BSY_IRQn
-extern "C"
-void SCSI_BSY_IRQ (void)
-{
-    SCSI_RST_IRQ();
-}
-#endif
-
-#if (SCSI_SEL_IRQn != SCSI_RST_IRQn) && (SCSI_SEL_IRQn != SCSI_BSY_IRQn)
-extern "C"
-void SCSI_SEL_IRQ (void)
-{
-    SCSI_RST_IRQ();
-}
-#endif
-
-static void init_irqs()
-{
-    // Falling edge of RST pin
-    gpio_exti_source_select(SCSI_RST_EXTI_SOURCE_PORT, SCSI_RST_EXTI_SOURCE_PIN);
-    exti_init(SCSI_RST_EXTI, EXTI_INTERRUPT, EXTI_TRIG_FALLING);
-    NVIC_SetPriority(SCSI_RST_IRQn, 1);
-    NVIC_EnableIRQ(SCSI_RST_IRQn);
-
-    // Rising edge of BSY pin
-    gpio_exti_source_select(SCSI_BSY_EXTI_SOURCE_PORT, SCSI_BSY_EXTI_SOURCE_PIN);
-    exti_init(SCSI_BSY_EXTI, EXTI_INTERRUPT, EXTI_TRIG_RISING);
-    NVIC_SetPriority(SCSI_BSY_IRQn, 1);
-    NVIC_EnableIRQ(SCSI_BSY_IRQn);
-
-    // Falling edge of SEL pin
-    if (g_moved_select_in)
-    {
-        gpio_exti_source_select(SCSI_ODE_SEL_EXTI_SOURCE_PORT, SCSI_ODE_SEL_EXTI_SOURCE_PIN);
-        exti_init(SCSI_ODE_SEL_EXTI, EXTI_INTERRUPT, EXTI_TRIG_FALLING);
-        NVIC_SetPriority(SCSI_ODE_SEL_IRQn, 1);
-        NVIC_EnableIRQ(SCSI_ODE_SEL_IRQn);
-    }
-    else 
-    {
-        gpio_exti_source_select(SCSI_SEL_EXTI_SOURCE_PORT, SCSI_SEL_EXTI_SOURCE_PIN);
-        exti_init(SCSI_SEL_EXTI, EXTI_INTERRUPT, EXTI_TRIG_FALLING);
-        NVIC_SetPriority(SCSI_SEL_IRQn, 1);
-        NVIC_EnableIRQ(SCSI_SEL_IRQn);
-    }
-}
-
-

+ 0 - 90
lib/ZuluSCSI_platform_GD32F205/scsiPhy.h

@@ -1,90 +0,0 @@
-/** 
- * SCSI2SD V6 - Copyright (C) 2013 Michael McMaster <michael@codesrc.com>
- * ZuluSCSI™ - Copyright (c) 2022-2025 Rabbit Hole Computing™
- * 
- * This file is licensed under the GPL version 3 or any later version.  
- * It is derived from scsiPhy.h in SCSI2SD V6.
- * 
- * https://www.gnu.org/licenses/gpl-3.0.html
- * ----
- * 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 <https://www.gnu.org/licenses/>.
-**/
-
-// Interface to SCSI physical interface.
-// This file is derived from scsiPhy.h in SCSI2SD-V6.
-
-#pragma once
-
-#include <stdint.h>
-#include <stdbool.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-// Read SCSI status signals
-bool scsiStatusATN();
-bool scsiStatusBSY();
-bool scsiStatusSEL();
-
-// Parity not yet implemented
-#define scsiParityError() 0
-
-// Get SCSI selection status.
-// This is latched by interrupt when BSY is deasserted while SEL is asserted.
-// Lowest 3 bits are the selected target id.
-// Highest bits are status information.
-#define SCSI_STS_SELECTION_SUCCEEDED 0x40
-#define SCSI_STS_SELECTION_ATN 0x80
-extern volatile uint8_t g_scsi_sts_selection;
-#define SCSI_STS_SELECTED (&g_scsi_sts_selection)
-extern volatile uint8_t g_scsi_ctrl_bsy;
-#define SCSI_CTRL_BSY (&g_scsi_ctrl_bsy)
-
-// Called when SCSI RST signal has been asserted, should release bus.
-void scsiPhyReset(void);
-
-// Change MSG / CD / IO signal states and wait for necessary transition time.
-// Phase argument is one of SCSI_PHASE enum values.
-void scsiEnterPhase(int phase);
-
-// Change state and return nanosecond delay to wait
-uint32_t scsiEnterPhaseImmediate(int phase);
-
-// Release all signals
-void scsiEnterBusFree(void);
-
-// Blocking data transfer
-void scsiWrite(const uint8_t* data, uint32_t count);
-void scsiRead(uint8_t* data, uint32_t count, int* parityError);
-void scsiWriteByte(uint8_t value);
-uint8_t scsiReadByte(void);
-
-// Non-blocking data transfer.
-// Depending on platform support the start() function may block.
-// The start function can be called multiple times, it may internally
-// either combine transfers or block until previous transfer completes.
-void scsiStartWrite(const uint8_t* data, uint32_t count);
-void scsiFinishWrite();
-
-// Query whether the data at pointer has already been read, i.e. buffer can be reused.
-// If data is NULL, checks if all writes have completed.
-bool scsiIsWriteFinished(const uint8_t *data);
-
-
-#define s2s_getScsiRateKBs() 0
-
-#ifdef __cplusplus
-}
-#endif

+ 0 - 173
lib/ZuluSCSI_platform_GD32F205/scsi_accel_asm.cpp

@@ -1,173 +0,0 @@
-/** 
- * ZuluSCSI™ - Copyright (c) 2022-2025 Rabbit Hole Computing™
- * 
- * ZuluSCSI™ firmware is licensed under the GPL version 3 or any later version. 
- * 
- * https://www.gnu.org/licenses/gpl-3.0.html
- * ----
- * 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 <https://www.gnu.org/licenses/>.
-**/
-
-#include "scsi_accel_asm.h"
-#include "ZuluSCSI_platform.h"
-
-// Optimized ASM blocks for the SCSI communication subroutine
-
-// Take 8 bits from d and format them for writing
-// d is name of data operand, b is bit offset, x is unique label
-#define ASM_LOAD_DATA(d, b, x) \
-"    load_data1_" x "_%=: \n" \
-"        ubfx    %[tmp1], %[" d "], #" b ", #8 \n" \
-"        ldr     %[tmp1], [%[byte_lookup], %[tmp1], lsl #2] \n"
-
-// Write data to SCSI port and set REQ high
-#define ASM_SEND_DATA(x) \
-"    send_data" x "_%=: \n" \
-"        str     %[tmp1], [%[out_port_bop]] \n"
-
-// Read data from SCSI port, set REQ high, store data to d at bit offset b
-#define ASM_RECV_DATA(d, b, x) \
-"    recv_data" x "_%=: \n" \
-"        ldr     %[tmp1], [%[in_port_istat]] \n" \
-"        mov     %[tmp2], %[req_high_bop] \n" \
-"        str     %[tmp2], [%[out_port_bop]] \n" \
-"        ubfx    %[tmp1], %[tmp1], %[data_in_shift], #8 \n" \
-"        bfi     %[" d "], %[tmp1], #" b ", #8 \n"
-
-// Wait for ACK to be high, set REQ low, wait ACK low
-#define ASM_HANDSHAKE(x) \
-"        ldr     %[tmp2], [%[ack_pin_bb]] \n" \
-"        str     %[tmp2], [%[req_pin_bb]] \n" \
-"        cbnz    %[tmp2], req_is_low_now" x "_%= \n" \
-"        ldr     %[tmp2], [%[ack_pin_bb]] \n" \
-"        str     %[tmp2], [%[req_pin_bb]] \n" \
-"        cbnz    %[tmp2], req_is_low_now" x "_%= \n" \
-"        ldr     %[tmp2], [%[ack_pin_bb]] \n" \
-"        str     %[tmp2], [%[req_pin_bb]] \n" \
-"        cbnz    %[tmp2], req_is_low_now" x "_%= \n" \
-"    wait_ack_inactive" x "_%=: \n" \
-"        ldr     %[tmp2], [%[ack_pin_bb]] \n" \
-"        str     %[tmp2], [%[req_pin_bb]] \n" \
-"        cbnz    %[tmp2], req_is_low_now" x "_%= \n" \
-"        ldr     %[tmp2], [%[reset_flag]] \n" \
-"        cbnz    %[tmp2], req_is_low_now" x "_%= \n" \
-"        b.n     wait_ack_inactive" x "_%= \n" \
-"    req_is_low_now" x "_%=: \n" \
-"        ldr     %[tmp2], [%[ack_pin_bb]] \n" \
-"        cbz     %[tmp2], over_ack_active" x "_%= \n" \
-"        ldr     %[tmp2], [%[ack_pin_bb]] \n" \
-"        cbz     %[tmp2], over_ack_active" x "_%= \n" \
-"        ldr     %[tmp2], [%[ack_pin_bb]] \n" \
-"        cbz     %[tmp2], over_ack_active" x "_%= \n" \
-"        ldr     %[tmp2], [%[ack_pin_bb]] \n" \
-"        cbz     %[tmp2], over_ack_active" x "_%= \n" \
-"    wait_ack_active" x "_%=: \n" \
-"        ldr     %[tmp2], [%[ack_pin_bb]] \n" \
-"        cbz     %[tmp2], over_ack_active" x "_%= \n" \
-"        ldr     %[tmp2], [%[reset_flag]] \n" \
-"        cbnz    %[tmp2], over_ack_active" x "_%= \n" \
-"        b.n     wait_ack_active" x "_%= \n" \
-"    over_ack_active" x "_%=: \n" \
-
-// Send bytes to SCSI bus using the asynchronous handshake mechanism
-// Takes 4 bytes at a time for sending from buf.
-void scsi_accel_asm_send(const uint32_t *buf, uint32_t num_words, volatile int *resetFlag)
-{
-    volatile uint32_t *out_port_bop = (volatile uint32_t*)&GPIO_BOP(SCSI_OUT_PORT);
-    const uint32_t *byte_lookup = g_scsi_out_byte_to_bop;
-    uint32_t ack_pin_bb = PERIPH_BB_BASE + (((uint32_t)&GPIO_ISTAT(SCSI_ACK_PORT)) - APB1_BUS_BASE) * 32 + SCSI_IN_ACK_IDX * 4;
-    uint32_t req_pin_bb = PERIPH_BB_BASE + (((uint32_t)out_port_bop) - APB1_BUS_BASE) * 32 + (SCSI_OUT_REQ_IDX + 16) * 4;
-    register uint32_t tmp1 = 0;
-    register uint32_t tmp2 = 0;
-    register uint32_t data = 0;
-
-    asm volatile (
-    "   ldr      %[data], [%[buf]], #4 \n" \
-        ASM_LOAD_DATA("data", "0", "first")
-
-    "inner_loop_%=: \n" \
-        ASM_SEND_DATA("0")
-        ASM_LOAD_DATA("data", "8", "8")
-        ASM_HANDSHAKE("0")
-        
-        ASM_SEND_DATA("8")
-        ASM_LOAD_DATA("data", "16", "16")
-        ASM_HANDSHAKE("8")
-
-        ASM_SEND_DATA("16")
-        ASM_LOAD_DATA("data", "24", "24")
-        ASM_HANDSHAKE("16")
-
-        ASM_SEND_DATA("24")
-    "   ldr      %[data], [%[buf]], #4 \n" \
-        ASM_LOAD_DATA("data", "0", "0")
-        ASM_HANDSHAKE("24")
-
-    "   subs     %[num_words], %[num_words], #1 \n" \
-    "   bne     inner_loop_%= \n"
-    : /* Output */ [tmp1] "+l" (tmp1), [tmp2] "+l" (tmp2), [data] "+r" (data),
-                   [buf] "+r" (buf), [num_words] "+r" (num_words)
-    : /* Input */ [ack_pin_bb] "r" (ack_pin_bb),
-                  [req_pin_bb] "r" (req_pin_bb),
-                  [out_port_bop] "r"(out_port_bop),
-                  [byte_lookup] "r" (byte_lookup),
-                  [reset_flag] "r" (resetFlag)
-    : /* Clobber */ );
-
-    SCSI_RELEASE_DATA_REQ();
-}
-
-// Read bytes from SCSI bus using asynchronous handshake mechanism
-// Takes 4 bytes at a time.
-void scsi_accel_asm_recv(uint32_t *buf, uint32_t num_words, volatile int *resetFlag)
-{
-    volatile uint32_t *out_port_bop = (volatile uint32_t*)&GPIO_BOP(SCSI_OUT_PORT);
-    volatile uint32_t *in_port_istat = (volatile uint32_t*)&GPIO_ISTAT(SCSI_IN_PORT);
-    uint32_t ack_pin_bb = PERIPH_BB_BASE + (((uint32_t)&GPIO_ISTAT(SCSI_ACK_PORT)) - APB1_BUS_BASE) * 32 + SCSI_IN_ACK_IDX * 4;
-    uint32_t req_pin_bb = PERIPH_BB_BASE + (((uint32_t)out_port_bop) - APB1_BUS_BASE) * 32 + (SCSI_OUT_REQ_IDX + 16) * 4;
-    register uint32_t tmp1 = 0;
-    register uint32_t tmp2 = 0;
-    register uint32_t data = 0;
-
-    asm volatile (
-    "inner_loop_%=: \n" \
-        ASM_HANDSHAKE("0")
-        ASM_RECV_DATA("data", "0", "0")
-        
-        ASM_HANDSHAKE("8")
-        ASM_RECV_DATA("data", "8", "8")
-        
-        ASM_HANDSHAKE("16")
-        ASM_RECV_DATA("data", "16", "16")
-        
-        ASM_HANDSHAKE("24")
-        ASM_RECV_DATA("data", "24", "24")
-
-    "   mvn      %[data], %[data] \n" \
-    "   str      %[data], [%[buf]], #4 \n" \
-    "   subs     %[num_words], %[num_words], #1 \n" \
-    "   bne     inner_loop_%= \n"
-    : /* Output */ [tmp1] "+l" (tmp1), [tmp2] "+l" (tmp2), [data] "+r" (data),
-                   [buf] "+r" (buf), [num_words] "+r" (num_words)
-    : /* Input */ [ack_pin_bb] "r" (ack_pin_bb),
-                  [req_pin_bb] "r" (req_pin_bb),
-                  [out_port_bop] "r"(out_port_bop),
-                  [in_port_istat] "r" (in_port_istat),
-                  [reset_flag] "r" (resetFlag),
-                  [data_in_shift] "I" (SCSI_IN_SHIFT),
-                  [req_high_bop] "I" (SCSI_OUT_REQ)
-    : /* Clobber */ );
-
-    SCSI_RELEASE_DATA_REQ();
-}

+ 0 - 29
lib/ZuluSCSI_platform_GD32F205/scsi_accel_asm.h

@@ -1,29 +0,0 @@
-/** 
- * ZuluSCSI™ - Copyright (c) 2022-2025 Rabbit Hole Computing™
- * 
- * ZuluSCSI™ firmware is licensed under the GPL version 3 or any later version. 
- * 
- * https://www.gnu.org/licenses/gpl-3.0.html
- * ----
- * 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 <https://www.gnu.org/licenses/>.
-**/
-
-// SCSI subroutines using hand-optimized assembler
-
-#pragma once
-
-#include <stdint.h>
-
-void scsi_accel_asm_send(const uint32_t *buf, uint32_t num_words, volatile int *resetFlag);
-void scsi_accel_asm_recv(uint32_t *buf, uint32_t num_words, volatile int *resetFlag);

Algunos archivos no se mostraron porque demasiados archivos cambiaron en este cambio