DEVICE NAME := "SD Card 4-bit interface"

  PINS
    // SD Card
    DATA        := 1, 9, 8, 7;
    CMD         := 2;
    CLK         := 5;
    nCD         := 10;
    WP          := 12;
    VDD_ENABLE  := 20;    // Power enable (modify pin as required)
  END;

  DISABLE DEVICE
    VDD_ENABLE := 0;
    WP    := Z;
    CMD   := Z;
  END;

  TEST COVERAGE
    nCD := OPEN HI LO;
    CLK := OPEN HI LO;
    CMD := OPEN HI LO;
    VDD_ENABLE := OPEN HI LO;
    DATA := OPEN HI LO;
  END;

  // Additional files
  FILES
    "FaultFinder.xje";
    "SD_MMC.xje";
  END;

END;

//------------------------------------------------------------
// SD Card Interface
//
// Copyright (c) 2004-2011 XJTAG Limited. All rights reserved.
// Licensed under XJTAG's XJEase Code Licence
// (http://xjtag.com/xjease_code_licence/)
//
// Disclaimer: XJTAG makes no guarantees whatsoever about this
// code. You use it at your own risk.
//
// If you find any problems with this file, please contact
// support@xjtag.com
//------------------------------------------------------------

//------------------------------------------------------------
// NOTE
// ----
// This file tests Non-JTAG Memory Card using TestNonDestructive()(INT result)
// TestDestructive()(INT result) can also be used, although this will overwrite
// data on the SD/MMC card.
//------------------------------------------------------------

//--------------------------------------------------------------------------------
// Constants
//--------------------------------------------------------------------------------

CONST INT PROMPT_BEFORE_DESTRUCTIVE_TEST := TRUE;
CONST INT DESTRUCTIVE_TEST_START_ADDRESS := 0; // This block will be over-written with destructive tests

CONST INT RESULT_PASS WIDTH 1   := FALSE;
CONST INT RESULT_FAIL WIDTH 1   := TRUE;

INT DEBUG_SD_MMC := FALSE;

//--------------------------------------------------------------------------------
TestNonDestructive()(INT result)
//--------------------------------------------------------------------------------
  InsertCard()(result);
  IF result != RESULT_PASS THEN RETURN; END;

  Test(FALSE, 0)(result);
  IF result != RESULT_PASS THEN RETURN; END;

  RemoveCard()(result);
END;

//--------------------------------------------------------------------------------
TestDestructive()(INT result)
//--------------------------------------------------------------------------------
  InsertCard()(result);
  IF result != RESULT_PASS THEN RETURN; END;

  Test(TRUE, DESTRUCTIVE_TEST_START_ADDRESS)(result);
  IF result != RESULT_PASS THEN RETURN; END;

  RemoveCard()(result);
END;

//--------------------------------------------------------------------------------
InsertCard()(INT result)
//--------------------------------------------------------------------------------
  INT notDetect;
  INT key;

  result := RESULT_PASS;

  SET CMD := I, DATA := I;

  IF READABLE(nCD) THEN
    SET notDetect := nCD;

    IF notDetect THEN
      // Clear key buffer
      DO WHILE GETKEY() END;
      PRINT("Insert SD card (", DEVICE_REF, "), or press any key to abort\n");
      ALERT();

      DO
        SET notDetect := nCD;
      WHILE (!GETKEY() && notDetect)
      END;

      IF (notDetect) THEN
        PRINT("Waiting for card aborted by user\n");
        result := RESULT_FAIL;
        RETURN;
      END;
    END;
  ELSE
    // Clear key buffer
    DO WHILE GETKEY() END;
    PRINT("Insert SD card (", DEVICE_REF, "), and press any key to continue\n");
    ALERT();

    key := WAITKEY();
  END;

  IF WRITEABLE(VDD_ENABLE) THEN
    // wait for all pins to connect before appling power
    SLEEP(1000);

    // Switch on power and enable (in SD Mode),
    SET VDD_ENABLE := 1;
    SET CLK := 0;

    // Wait for card to start-up
    SLEEP(100);
  END;
END;

//--------------------------------------------------------------------------------
RemoveCard()(INT result)
//--------------------------------------------------------------------------------
  INT notDetect;
  INT key;

  // Turn off power and disable
  IF WRITEABLE(VDD_ENABLE) THEN
    SET VDD_ENABLE := 0;
  END;

  SET CLK := 0;
  SET CMD := I;

  // Wait for removal
  IF READABLE(nCD) THEN
    SET notDetect := nCD;

    IF notDetect THEN
      result := RESULT_PASS;
    ELSE
      // Clear key buffer
      DO WHILE GETKEY() END;
      PRINT("Remove SD card (", DEVICE_REF, "), or press any key to abort\n");
      ALERT();

      DO
        SET notDetect := nCD;
      WHILE (!GETKEY() && !notDetect)
      END;

      IF (notDetect) THEN
        result := RESULT_PASS;
      ELSE
        result := RESULT_FAIL;
      END;
    END;
  ELSE
    // Clear key buffer
    DO WHILE GETKEY() END;
    PRINT("Remove SD card (", DEVICE_REF, "), and press any key to continue\n");
    ALERT();

    key := WAITKEY();
  END;
END;