nimphea/per/sdmmc

Search:
Group by:
Source   Edit  

SD Card (SDIO/SDMMC) support for libDaisy Nim wrapper

This module provides SD card access via SDMMC peripheral with FatFS filesystem. It enables reading and writing files on SD cards connected to the Daisy Seed.

Basic Usage:

import nimphea
import nimphea/per/sdmmc

var hw = newDaisySeed()
var sd = newSdmmcHandler()
var fatfs = newFatFSInterface()

proc main() =
  hw.init()
  
  # Configure SDMMC
  var sdConfig = newSdmmcConfig()
  sdConfig.speed = SD_FAST
  sdConfig.width = SD_BITS_4
  
  # Initialize SD card
  if sd.init(sdConfig) != SD_OK:
    return
  
  # Mount filesystem
  if fatfs.init(MEDIA_SD) != FATFS_OK:
    return
  
  # Now you can use FatFS functions
  var file: FIL
  if f_open(addr file, "test.txt", FA_READ) == FR_OK:
    # Read file...
    discard f_close(addr file)
  
  while true:
    hw.delayMs(100)

Pin Configuration (Fixed):

  • PC12: SDMMC1 Clock
  • PD2: SDMMC1 Command
  • PC8: SDMMC1 D0 (always required)
  • PC9: SDMMC1 D1 (4-bit mode only)
  • PC10: SDMMC1 D2 (4-bit mode only)
  • PC11: SDMMC1 D3 (4-bit mode only)

Types

BYTE = uint8
Source   Edit  
DIR {.importc: "DIR", bycopy.} = object
Source   Edit  
FATFS {.importc: "FATFS", bycopy.} = object
Source   Edit  
FatFSConfig {.importcpp: "daisy::FatFSInterface::Config", bycopy.} = object
  media* {.importc: "media".}: uint8
Source   Edit  
FatFSInterface {.importcpp: "daisy::FatFSInterface".} = object
Source   Edit  
FatFSMedia {.importcpp: "daisy::FatFSInterface::Config::Media", size: 1.} = enum
  MEDIA_SD = 1, MEDIA_USB = 2
Source   Edit  
FatFSResult {.importcpp: "daisy::FatFSInterface::Result", size: 4.} = enum
  FATFS_OK = 0, FATFS_ERR_TOO_MANY_VOLUMES, FATFS_ERR_NO_MEDIA_SELECTED,
  FATFS_ERR_GENERIC
Source   Edit  
FIL {.importc: "FIL", bycopy.} = object
Source   Edit  
FILINFO {.importc: "FILINFO", bycopy.} = object
  fsize* {.importc: "fsize".}: uint32 ## File size
  fdate* {.importc: "fdate".}: uint16 ## Modified date
  ftime* {.importc: "ftime".}: uint16 ## Modified time
  fattrib* {.importc: "fattrib".}: uint8 ## File attributes
  fname* {.importc: "fname".}: array[256, char] ## File name
Source   Edit  
FRESULT {.importc: "FRESULT", size: 4.} = enum
  FR_OK = 0,                ## Succeeded
  FR_DISK_ERR,              ## A hard error occurred in the low level disk I/O layer
  FR_INT_ERR,               ## Assertion failed
  FR_NOT_READY,             ## The physical drive cannot work
  FR_NO_FILE,               ## Could not find the file
  FR_NO_PATH,               ## Could not find the path
  FR_INVALID_NAME,          ## The path name format is invalid
  FR_DENIED,                ## Access denied due to prohibited access or directory full
  FR_EXIST,                 ## Access denied due to prohibited access
  FR_INVALID_OBJECT,        ## The file/directory object is invalid
  FR_WRITE_PROTECTED,       ## The physical drive is write protected
  FR_INVALID_DRIVE,         ## The logical drive number is invalid
  FR_NOT_ENABLED,           ## The volume has no work area
  FR_NO_FILESYSTEM,         ## There is no valid FAT volume
  FR_MKFS_ABORTED,          ## The f_mkfs() aborted due to any problem
  FR_TIMEOUT,               ## Could not get a grant to access the volume within defined period
  FR_LOCKED,                ## The operation is rejected according to the file sharing policy
  FR_NOT_ENOUGH_CORE,       ## LFN working buffer could not be allocated
  FR_TOO_MANY_OPEN_FILES,   ## Number of open files > FF_FS_LOCK
  FR_INVALID_PARAMETER       ## Given parameter is invalid
Source   Edit  
FSIZE_t = uint32
Source   Edit  
SdmmcBusWidth {.importcpp: "daisy::SdmmcHandler::BusWidth", size: 4.} = enum
  SD_BITS_1 = 0,            ## 1-bit mode (only D0 used)
  SD_BITS_4                  ## 4-bit mode (D0-D3 used, faster)
Source   Edit  
SdmmcConfig {.importcpp: "daisy::SdmmcHandler::Config", bycopy.} = object
  speed* {.importc: "speed".}: SdmmcSpeed
  width* {.importc: "width".}: SdmmcBusWidth
  clock_powersave* {.importc: "clock_powersave".}: bool
Source   Edit  
SdmmcHandler {.importcpp: "daisy::SdmmcHandler".} = object
Source   Edit  
SdmmcResult {.importcpp: "daisy::SdmmcHandler::Result", size: 4.} = enum
  SD_OK = 0, SD_ERROR
Source   Edit  
SdmmcSpeed {.importcpp: "daisy::SdmmcHandler::Speed", size: 4.} = enum
  SD_SLOW = 0,              ## 400kHz - initialization speed
  SD_MEDIUM_SLOW,           ## 12.5MHz - half of standard
  SD_STANDARD,              ## 25MHz - default speed
  SD_FAST,                  ## 50MHz - high speed
  SD_VERY_FAST               ## 100MHz - overclocked (SDR50)
Source   Edit  
UINT = cuint
Source   Edit  

Consts

AM_ARC = 0x20'u8
Archive Source   Edit  
AM_DIR = 0x10'u8
Directory Source   Edit  
AM_HID = 0x02'u8
Hidden Source   Edit  
AM_RDO = 0x01'u8
Read only Source   Edit  
AM_SYS = 0x04'u8
System Source   Edit  
FA_CREATE_ALWAYS = 0x08'u8
Create new file, overwrite existing Source   Edit  
FA_CREATE_NEW = 0x04'u8
Create new file Source   Edit  
FA_OPEN_ALWAYS = 0x10'u8
Open existing or create new Source   Edit  
FA_OPEN_APPEND = 0x30'u8
Open existing and seek to end Source   Edit  
FA_OPEN_EXISTING = 0x00'u8
Open existing file Source   Edit  
FA_READ = 0x01'u8
Read access Source   Edit  
FA_WRITE = 0x02'u8
Write access Source   Edit  

Procs

proc appendFile(path: cstring; data: openArray[uint8]): FRESULT {....raises: [],
    tags: [], forbids: [].}
Append data to file (creates if doesn't exist) Source   Edit  
proc createDirectory(path: cstring): FRESULT {....raises: [], tags: [], forbids: [].}
Create a directory Source   Edit  
proc DeInit(this: var FatFSInterface): FatFSResult {.importcpp: "#.DeInit()",
    header: "daisy_seed.h", header: "daisy_seed.h", importcpp, ...raises: [],
    tags: [], forbids: [].}
Source   Edit  
proc deInit(fatfs: var FatFSInterface): FatFSResult {....raises: [], tags: [],
    forbids: [].}
Deinitialize FatFS interface Source   Edit  
proc deleteFile(path: cstring): FRESULT {....raises: [], tags: [], forbids: [].}
Delete a file Source   Edit  
proc f_chmod(path: cstring; attr: BYTE; mask: BYTE): FRESULT {.
    importc: "f_chmod", header: "ff.h", ...raises: [], tags: [], forbids: [].}
Source   Edit  
proc f_close(fp: ptr FIL): FRESULT {.importc: "f_close", header: "ff.h",
                                     ...raises: [], tags: [], forbids: [].}
Source   Edit  
proc f_closedir(dp: ptr DIR): FRESULT {.importc: "f_closedir", header: "ff.h",
                                        ...raises: [], tags: [], forbids: [].}
Source   Edit  
proc f_eof(fp: ptr FIL): cint {.importc: "f_eof", header: "ff.h", ...raises: [],
                                tags: [], forbids: [].}
Source   Edit  
proc f_lseek(fp: ptr FIL; ofs: FSIZE_t): FRESULT {.importc: "f_lseek",
    header: "ff.h", ...raises: [], tags: [], forbids: [].}
Source   Edit  
proc f_mkdir(path: cstring): FRESULT {.importc: "f_mkdir", header: "ff.h",
                                       ...raises: [], tags: [], forbids: [].}
Source   Edit  
proc f_mount(fs: ptr FATFS; path: cstring; opt: BYTE): FRESULT {.
    importc: "f_mount", header: "ff.h", ...raises: [], tags: [], forbids: [].}
Source   Edit  
proc f_open(fp: ptr FIL; path: cstring; mode: uint8): FRESULT {.
    importc: "f_open", header: "ff.h", ...raises: [], tags: [], forbids: [].}
Source   Edit  
proc f_opendir(dp: ptr DIR; path: cstring): FRESULT {.importc: "f_opendir",
    header: "ff.h", ...raises: [], tags: [], forbids: [].}
Source   Edit  
proc f_read(fp: ptr FIL; buff: pointer; btr: UINT; br: ptr UINT): FRESULT {.
    importc: "f_read", header: "ff.h", ...raises: [], tags: [], forbids: [].}
Source   Edit  
proc f_readdir(dp: ptr DIR; fno: ptr FILINFO): FRESULT {.importc: "f_readdir",
    header: "ff.h", ...raises: [], tags: [], forbids: [].}
Source   Edit  
proc f_rename(oldname: cstring; newname: cstring): FRESULT {.
    importc: "f_rename", header: "ff.h", ...raises: [], tags: [], forbids: [].}
Source   Edit  
proc f_size(fp: ptr FIL): FSIZE_t {.importc: "f_size", header: "ff.h",
                                    ...raises: [], tags: [], forbids: [].}
Source   Edit  
proc f_stat(path: cstring; fno: ptr FILINFO): FRESULT {.importc: "f_stat",
    header: "ff.h", ...raises: [], tags: [], forbids: [].}
Source   Edit  
proc f_sync(fp: ptr FIL): FRESULT {.importc: "f_sync", header: "ff.h",
                                    ...raises: [], tags: [], forbids: [].}
Source   Edit  
proc f_tell(fp: ptr FIL): FSIZE_t {.importc: "f_tell", header: "ff.h",
                                    ...raises: [], tags: [], forbids: [].}
Source   Edit  
proc f_unmount(path: cstring): FRESULT {.importc: "f_unmount", header: "ff.h",
    ...raises: [], tags: [], forbids: [].}
Source   Edit  
proc f_write(fp: ptr FIL; buff: pointer; btw: UINT; bw: ptr UINT): FRESULT {.
    importc: "f_write", header: "ff.h", ...raises: [], tags: [], forbids: [].}
Source   Edit  
proc fileExists(path: cstring): bool {....raises: [], tags: [], forbids: [].}
Check if file exists Source   Edit  
proc GetConfig(this: FatFSInterface): FatFSConfig {.importcpp: "#.GetConfig()",
    header: "daisy_seed.h", header: "daisy_seed.h", importcpp, ...raises: [],
    tags: [], forbids: [].}
Source   Edit  
proc getConfig(fatfs: FatFSInterface): FatFSConfig {....raises: [], tags: [],
    forbids: [].}
Get FatFS configuration Source   Edit  
proc getFileSize(path: cstring): int {....raises: [], tags: [], forbids: [].}
Get file size in bytes, returns -1 on error Source   Edit  
proc getSDPath(fatfs: FatFSInterface): cstring {....raises: [], tags: [],
    forbids: [].}
Get SD card mount path Source   Edit  
proc GetSDPath(this: FatFSInterface): cstring {.importcpp: "#.GetSDPath()",
    header: "daisy_seed.h", header: "daisy_seed.h", importcpp, ...raises: [],
    tags: [], forbids: [].}
Source   Edit  
proc getUSBPath(fatfs: FatFSInterface): cstring {....raises: [], tags: [],
    forbids: [].}
Get USB mount path Source   Edit  
proc GetUSBPath(this: FatFSInterface): cstring {.importcpp: "#.GetUSBPath()",
    header: "daisy_seed.h", header: "daisy_seed.h", importcpp, ...raises: [],
    tags: [], forbids: [].}
Source   Edit  
proc Init(this: var FatFSInterface; cfg: FatFSConfig): FatFSResult {.
    importcpp: "#.Init(@)", header: "daisy_seed.h", ...raises: [], tags: [],
    forbids: [].}
Source   Edit  
proc Init(this: var FatFSInterface; media: uint8): FatFSResult {.
    importcpp: "#.Init(@)", header: "daisy_seed.h", ...raises: [], tags: [],
    forbids: [].}
Source   Edit  
proc Init(this: var SdmmcHandler; cfg: SdmmcConfig): SdmmcResult {.
    importcpp: "#.Init(@)", header: "daisy_seed.h", ...raises: [], tags: [],
    forbids: [].}
Source   Edit  
proc init(fatfs: var FatFSInterface; cfg: FatFSConfig): FatFSResult {.
    ...raises: [], tags: [], forbids: [].}
Initialize FatFS interface with configuration Source   Edit  
proc init(fatfs: var FatFSInterface; media: FatFSMedia): FatFSResult {.
    ...raises: [], tags: [], forbids: [].}
Initialize FatFS interface with media type (convenience) Source   Edit  
proc init(sdmmc: var SdmmcHandler; cfg: SdmmcConfig): SdmmcResult {....raises: [],
    tags: [], forbids: [].}
Initialize SDMMC handler with configuration Source   Edit  
proc initialized(fatfs: FatFSInterface): bool {....raises: [], tags: [],
    forbids: [].}
Check if FatFS is initialized Source   Edit  
proc Initialized(this: FatFSInterface): bool {.importcpp: "#.Initialized()",
    header: "daisy_seed.h", header: "daisy_seed.h", importcpp, ...raises: [],
    tags: [], forbids: [].}
Source   Edit  
proc listDirectory(path: cstring; filenames: var openArray[array[256, char]];
                   maxFiles: int): tuple[result: FRESULT, count: int] {.
    ...raises: [], tags: [], forbids: [].}
List files in directory into provided buffer filenames: buffer for storing filenames (each up to 256 chars) maxFiles: maximum number of files to read (should be <= filenames.len) Returns: result code and number of files found Source   Edit  
proc newFatFSConfig(): FatFSConfig {....raises: [], tags: [], forbids: [].}
Creates a new FatFS configuration Source   Edit  
proc newFatFSInterface(): FatFSInterface {.importcpp: "daisy::FatFSInterface()",
    constructor, header: "daisy_seed.h", ...raises: [], tags: [], forbids: [].}
Source   Edit  
proc newSdmmcConfig(): SdmmcConfig {....raises: [], tags: [], forbids: [].}
Creates a new SDMMC configuration with default values Source   Edit  
proc newSdmmcHandler(): SdmmcHandler {.importcpp: "daisy::SdmmcHandler()",
                                       constructor, header: "daisy_seed.h",
                                       ...raises: [], tags: [], forbids: [].}
Source   Edit  
proc readFile(path: cstring; buffer: var openArray[uint8]; bytesRead: var int): FRESULT {.
    ...raises: [], tags: [], forbids: [].}
Read file into provided buffer (safe for embedded) Returns number of bytes actually read in bytesRead parameter Source   Edit  
proc renameFile(oldPath: cstring; newPath: cstring): FRESULT {....raises: [],
    tags: [], forbids: [].}
Rename or move a file Source   Edit  
proc writeFile(path: cstring; data: openArray[uint8]): FRESULT {....raises: [],
    tags: [], forbids: [].}
Write data to file (creates or overwrites) Source   Edit