/* ---------------------------------------------------------------------------
 * testMMC.c                                            (c) 2008 Micro-key bv
 * ---------------------------------------------------------------------------
 * Micro-key bv
 * Industrieweg 28, 9804 TG Noordhorn
 * Postbus 92, 9800 AB Zuidhorn
 * The Netherlands
 * Tel: +31 594 503020 
 * Fax: +31 594 505825
 * Email: support@microkey.nl  
 * Web: www.microkey.nl
 * ---------------------------------------------------------------------------
 * Description: 
 * MemoryCard Test Application
 * ---------------------------------------------------------------------------
 * Version(s):  0.1, Apr 24, 2008, MMi
 *                   Creation.
 * ---------------------------------------------------------------------------
 */

/* ---------------------------------------------------------------------------
 * System include files
 * ---------------------------------------------------------------------------
 */
/* Compiler includes */
#include <string.h>

#include "LPC23xx.h"
#include "types.h"

/* FreeRTOS includes */
#include "FreeRTOS.h"
#include "Task.h"
/* ---------------------------------------------------------------------------
 * Application include files
 * ---------------------------------------------------------------------------
 */
#include "testMMC.h"
#include "mmc.h"
#include "mmc_transfer.h"
#include "ledfunctions.h"
#include "SerOut.h"
#include "dio.h"
/* ---------------------------------------------------------------------------
 * Local constant and macro definitions
 * ---------------------------------------------------------------------------
 */
#define PageSize            512         /* MMC Card Memory Page Size        */
#define ArrayLength         0x1000      /* Length of test Arrays            */

#define MaxNumberOfAddress  7           /* Number of Testadresses           */
#define MaxNumberOfLength   7           /* Number of Testlengths            */

/* ---------------------------------------------------------------------------
 * Global variable definitions
 * ---------------------------------------------------------------------------
 */

/* ---------------------------------------------------------------------------
 * Local variable definitions
 * ---------------------------------------------------------------------------
 */
/* Array contains all Adresses, where Data should be written to             */
UINT32 AddressArray[MaxNumberOfAddress] =
    {
    0x00,
    0x10,
    0x200,
    0x23E,
    0x3FF,
    0x400,
    0x401,
    };

/* Array contains all Lengths, that should be written to the Testadresses   */
UINT32 LengthArray[MaxNumberOfLength]=
    {
    0x00,
    0x80,
    0x199,
    0x200,
    0x201,
    0x800,
    0x1000
    };

UINT8 Write[0x1000];                    /* used with MMC Write Function     */
UINT8 Read[0x1000];                     /* used with MMC Read Function      */
UINT8 nullarray[0x1000];

/* ---------------------------------------------------------------------------
 * Local function definitions
 * ---------------------------------------------------------------------------
 */

BOOLEAN testmmcStart(void)
{
    BOOLEAN testMMCResult = FALSE;
    
    testMMCResult = DoMMCTest();
    
    return (testMMCResult);
}

BOOLEAN DoMMCTest (void)
{
    UINT32 loopcnt;
    UINT32 AddressIndex= 0;
    UINT32 LengthIndex = 0;
    UINT8 character = 4;
    BOOLEAN MMCTestResult = FALSE;
    BOOLEAN RWTest = TRUE; 
    BOOLEAN LengthTest = TRUE;
    BOOLEAN MBSTest = TRUE;
    BOOLEAN PresentTest = TRUE;
    MmcState_t WriteStatus;
    MmcState_t ReadStatus;
    MmcState_t DiscStatus;

    /* Prepare Read and Write Array with writing Zero to every Position     */
    for (loopcnt = 0; loopcnt < ArrayLength; loopcnt++)
        {
        Read[loopcnt] = 0;
        Write[loopcnt] = 0;
        nullarray[loopcnt] = 0;

        }
    
    /* Fill WriteArray with Characters                                      */
    for (loopcnt = 0; loopcnt < ArrayLength; loopcnt++)
        {
        Write[loopcnt] = character;
        character += 3;
        }

    MMC_StatusOut (DiscStatus = MmcInitMedia()); /* Init Card, give Status  */
    
    if (DiscStatus == MmcNoPresent)
        {
        /* disc is not inserted, so Test will be aborted here               */
        PresentTest = FALSE;
        }
    else
        {
        /* Nested Test
         * Array "Write" is written with all available Lengths in LengthArray
         * to all available Adresses in AdressArray.
         */
        while (AddressIndex < MaxNumberOfAddress)
            {
            LengthIndex = 0;                /* Reset LengthIndex            */
            while (LengthIndex < MaxNumberOfLength)
                {
                WriteStatus = CardWrite ((pUINT8)Write, AddressArray[AddressIndex], 
                        LengthArray[LengthIndex]); /* Write to MMC          */
                
                ReadStatus = CardRead ((pUINT8)Read, AddressArray[AddressIndex], 
                        LengthArray[LengthIndex]); /* Read from MMC         */
                
                /* Check Status of Read and Write Events                    */
                if ((ReadStatus == MmcOk) && (WriteStatus == MmcOk))
                    {
                    for (loopcnt = 0; loopcnt < LengthArray[LengthIndex]; loopcnt++)
                        {                   /* Compare both Arrays          */
                        if (Read[loopcnt] != Write[loopcnt])
                            {               /* If miscompare occures        */
                            dioWrite(0, 6, TRUE); 
                            RWTest = FALSE;
                            } 
                        else                /* Everything's OK              */
                            {
                            dioWrite(0, 7, TRUE);
                            }
                        }
                    }
                
                /* Check if Length-Control in MMC-Read/Write works correctly*/
                else if (((LengthArray[LengthIndex] % PageSize) != 0)
                       || (LengthArray[LengthIndex] == 0))
                    {
                    if ((WriteStatus == MmcMiscompare) 
                      && (ReadStatus == MmcMiscompare))
                        {
                        dioWrite (0,5,TRUE);    /* Length Control works     */
                        }
                    else
                        {
                        dioWrite (0,4,TRUE);    /* Length Control works not */
                        LengthTest = FALSE;
                        }
                    }
                /* Check if MasterBootSector Protection works               */
                else if ((AddressArray[AddressIndex] < 0x200) 
                          && (LengthArray[LengthIndex] != 0))
                    {
                    if (WriteStatus == MmcCardError)
                        {
                        dioWrite (0,3,TRUE);    /* MBS Protection works     */
                        }
                    else
                        {
                        dioWrite (0,2,TRUE);    /* MBS Protection works not */
                        MBSTest = FALSE;
                        }
                    }
                
                else
                    {
                    dioWrite (0,1,TRUE);
                    dioWrite (0,0,TRUE);
                    sendString (SerOutPort, TRUE, testMessage,
                            "\t Length: ", s_tab, ItoDStr (LengthArray[LengthIndex]));
                    sendString (SerOutPort, TRUE, testMessage,
                            "\t Address: ", s_tab, ItoDStr (AddressArray[AddressIndex]));
                    MMC_StatusOut (WriteStatus);
                    MMC_StatusOut (ReadStatus);
                    RWTest = FALSE;
                    }
                
                LengthIndex++;
                } // End LENGTH WHILE-LOOP
            AddressIndex++;
            }  // End ADDRESS WHILE-LOOP
        }
    
    
    vTaskDelay (1000);
    /* Test Result Message Output                                       */
    sendString (SerOutPort, TRUE, testMessage,
            "\t Disc present: ", s_tab, BoolRestoStr (PresentTest));
    sendString (SerOutPort, TRUE, testMessage,
            "\t Read and Write Test: ", f_tab, BoolRestoStr(RWTest));
    sendString (SerOutPort, TRUE, testMessage,
            "\t Length Status Check: ", f_tab, BoolRestoStr(LengthTest));
    sendString (SerOutPort, TRUE, testMessage,
            "\t MBS Defend Check: ", f_tab, BoolRestoStr(MBSTest));
    
    /* Calculate complete Test Result out of single Tests               */
    if ((RWTest == TRUE) && (LengthTest == TRUE) 
            && (MBSTest == TRUE) && (PresentTest == TRUE))
        {
        MMCTestResult = TRUE;
        }
    else
        {
        MMCTestResult = FALSE;
        }
    
    
    return (MMCTestResult);
}

void MMC_StatusOut (MmcState_t Status)
{
    switch (Status) 
        {
        case MmcOk: 
            sendString (SerOutPort, TRUE, testMessage,
                    "MMC is OK", Dummy, Dummy);
            break;
        case MmcNoPresent: 
            sendString (SerOutPort, TRUE, testMessage,
                    "MMC is not present", Dummy, Dummy);
            break;
        case MmcNoResponse: 
            sendString (SerOutPort, TRUE, testMessage,
                    "MMC not responding", Dummy, Dummy);
            break;
        case MmcCardError: 
            sendString (SerOutPort, TRUE, testMessage,
                    "MMC Card Error", Dummy, Dummy);
            break;
        case MmcMiscompare: 
            sendString (SerOutPort, TRUE, testMessage,
                    "MMC Miscompare", Dummy, Dummy);
            break;
        case MmcDmaError: 
            sendString (SerOutPort, TRUE, testMessage,
                    "MMC DMA Error", Dummy, Dummy);
            break; 
        case MmcProtect:
            sendString (SerOutPort, TRUE, testMessage,
                    "Card is Protected", Dummy, Dummy);
            break;
        default:
            break;
        }
}
