/******************************************************************************
*    Photo Fram V0.92  2026/07/30
*                        
*
******************************************************************************
* FileName:           main.c  20241206
* Dependencies:       sd_spi.h
*                     fileio_lfn.h
*                     main.h
*                     rtcc.h
* Processor:          PIC24/dsPIC30/dsPIC33
* Compiler:           XC16
* Company:            Microchip Technology, Inc.
*
* Software License Agreement
*
* The software supplied herewith by Microchip Technology Incorporated
* (the "Company") for its PICmicro(R) Microcontroller is intended and
* supplied to you, the Company's customer, for use solely and
* exclusively on Microchip PICmicro Microcontroller products. The
* software is owned by the Company and/or its supplier, and is
* protected under applicable copyright laws. All rights are reserved.
* Any use in violation of the foregoing restrictions may subject the
* user to criminal sanctions under applicable laws, as well as to
* civil liability for the breach of the terms and conditions of this
* license.
*
* THIS SOFTWARE IS PROVIDED IN AN "AS IS" CONDITION. NO WARRANTIES,
* WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING, BUT NOT LIMITED
* TO, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. THE COMPANY SHALL NOT,
* IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL OR
* CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER.
*
********************************************************************/

#include <stdint.h>
#include <string.h>

#include "sd_spi.h"
#include "fileio_lfn.h"
#include "main.h"
#include "rtcc.h"
#include "system.h"
#include "BMP_display_system_092.h"
 

// GetTimestamp will be called by the FILEIO library when it needs a timestamp for a file
void GetTimestamp (FILEIO_TIMESTAMP * timeStamp);

extern FILEIO_SD_DRIVE_CONFIG sdCardMediaParameters;

// The gSDDrive structure allows the user to specify which set of driver functions should be used by the
// FILEIO library to interface to the drive.
// This structure must be maintained as long as the user wishes to access the specified drive.
const FILEIO_DRIVE_CONFIG gSdDrive =
{
    (FILEIO_DRIVER_IOInitialize)FILEIO_SD_IOInitialize,                      // Function to initialize the I/O pins used by the driver.
    (FILEIO_DRIVER_MediaDetect)FILEIO_SD_MediaDetect,                       // Function to detect that the media is inserted.
    (FILEIO_DRIVER_MediaInitialize)FILEIO_SD_MediaInitialize,               // Function to initialize the media.
    (FILEIO_DRIVER_MediaDeinitialize)FILEIO_SD_MediaDeinitialize,           // Function to de-initialize the media.
    (FILEIO_DRIVER_SectorRead)FILEIO_SD_SectorRead,                         // Function to read a sector from the media.
    (FILEIO_DRIVER_SectorWrite)FILEIO_SD_SectorWrite,                       // Function to write a sector to the media.
    (FILEIO_DRIVER_WriteProtectStateGet)FILEIO_SD_WriteProtectStateGet,     // Function to determine if the media is write-protected.
};

// Declare a state machine for our device
typedef enum
{
    DEMO_STATE_MEDIA_DETECTED = 0,
    DEMO_STATE_NO_MEDIA,
    DEMO_STATE_DRIVE_MOUNTED,
    DEMO_STATE_DONE,
    DEMO_STATE_FAILED
} DEMO_STATE;

// Some sample data to write to the file
uint8_t sampleData[10] = "DATA,10\r\n";
uint16_t searchname[] = {'*','.','b','m','p',0};
uint16_t fname16[32];
uint8_t fname8[32];
uint8_t BMPdata[256];
void fname8tofname16(uint8_t *fname8){//ASCIIをUTF-16に変換します。
        unsigned char i ;
        for (i=0;i<32;i++) {
            fname16[i]=(uint16_t)fname8[i];
        }
    } 


// Main loop.
// This demo program implements a simple data logger.
int SDC_write_DEMO (void)
{
 //   OSCCON = 0b0001000110100001; //Fosc FRCPLL 32MHz 追加
//    CLKDIV = 0x0000;　//追加
    DEMO_STATE demoState = DEMO_STATE_NO_MEDIA;
    FILEIO_OBJECT file;
    RTCC_DATETIME dateTime;

#if !defined (__XC16__)
    const uint16_t fileName[] = {'S','a','m','p','l','e',' ','l','o','n','g',' ',     \
                                    'f','i','l','e',' ','n','a','m','e','.','t','x','t',0};
#endif

    SYSTEM_Initialize();
//GLED=1;
    dateTime.bcdFormat = false;
    RTCC_BuildTimeGet(&dateTime);
    RTCC_Initialize(&dateTime);

    // Initialize the library
    if (!FILEIO_Initialize())
    {
        while(1);
        FILEIO_Initialize();
    }
    
    // Register the GetTimestamp function as the timestamp source for the library.
    FILEIO_RegisterTimestampGet (GetTimestamp);

    while(1)
    { 
//        GLED=demoState;
        switch (demoState)
        {  
            case DEMO_STATE_NO_MEDIA:
                //
                // Loop on this function until the SD Card is detected.
                if (FILEIO_MediaDetect(&gSdDrive, &sdCardMediaParameters) == true)
                {
                    demoState = DEMO_STATE_MEDIA_DETECTED;
                }
                break;
            case DEMO_STATE_MEDIA_DETECTED:
                
#if defined (__XC8__)
                // When initializing an SD Card on PIC18, the the SPI clock must be between 100 and 400 kHz.
                // The largest prescale divider in most PIC18 parts is 64x, which means the clock frequency must
                // be between 400 kHz (for a 4x divider) and 25.6 MHz (for a 64x divider).  In this demo, we are
                // achieving this by disabling the PIC's PLL during the drive mount operation (note that the
                // SYS_CLK_FrequencySystemGet() function must accurate reflect this change).  You could also map the "slow"
                // SPI functions used by the sd-spi driver to an SPI implementation that will run between
                // 100 kHz and 400 kHz at Fosc values greater than 25.6 MHz.  The macros to remap are located in
                // fileio_config.h.
                OSCTUNEbits.PLLEN = 0;
#endif
                // Try to mount the drive we've defined in the gSdDrive structure.
                // If mounted successfully, this drive will use the drive Id 'A'
                // Since this is the first drive we're mounting in this application, this
                // drive's root directory will also become the current working directory
                // for our library.
                if (FILEIO_DriveMount('A', &gSdDrive, &sdCardMediaParameters) == FILEIO_ERROR_NONE)
                {
                    demoState = DEMO_STATE_DRIVE_MOUNTED;
                }
                else
                {
                    demoState = DEMO_STATE_NO_MEDIA;
                }
#if defined (__XC8__)
                OSCTUNEbits.PLLEN = 1;
#endif
                break;
            case DEMO_STATE_DRIVE_MOUNTED:
                // Open "Sample long file name.txt"
                // Specifying CREATE will create the file is it doesn't exist.
                // Specifying APPEND will set the current read/write location to the end of the file.
                // Specifying WRITE will allow you to write to the code.
#if defined (__XC16__)
                // The 'L' prefix lets you declare a wchar_t string.  When using XC16, wchar_t is a 16-bit word, so this can be used to generate Unicode names.
                
                if (FILEIO_Open (&file, (uint16_t *)L"Sample long file name.txt", FILEIO_OPEN_WRITE | FILEIO_OPEN_APPEND | FILEIO_OPEN_CREATE) == FILEIO_RESULT_FAILURE)
                
#else
                // Otherwise, unicode names must be declared as an array of characters (null-terminated)
                if (FILEIO_Open (&file, (uint16_t *)fileName, FILEIO_OPEN_WRITE | FILEIO_OPEN_APPEND | FILEIO_OPEN_CREATE) == false)
#endif
                {
                    demoState = DEMO_STATE_FAILED;
                    break;
                }

                // Write some sample data to the card
                if (FILEIO_Write (sampleData, 1, 9, &file) != 9)
                {
                    demoState = DEMO_STATE_FAILED;
                    break;
                }

                // Close the file to save the data
                if (FILEIO_Close (&file) != FILEIO_RESULT_SUCCESS)
                {
                    demoState = DEMO_STATE_FAILED;
                    break;
                }

                // We're done with this drive.
                // Unmount it.
                FILEIO_DriveUnmount ('A');
                demoState = DEMO_STATE_DONE;
                break;
            case DEMO_STATE_DONE:
                // Now that we've written all of the data we need to write in the application, wait for the user
                // to remove the card
                if (FILEIO_MediaDetect(&gSdDrive, &sdCardMediaParameters) == false)
                {
                    demoState = DEMO_STATE_NO_MEDIA;
                }
                break;
            case DEMO_STATE_FAILED:
                // An operation has failed.  Try to unmount the drive.  This will also try to
                // close all open files that use this drive (it will at least deallocate them).
                FILEIO_DriveUnmount ('A');
                // Return to the media-detect state
                demoState = DEMO_STATE_NO_MEDIA;
                break;
        }
    }
}

//SDカードにセーブされたBMP形式のエクセルデータを検索し、最大20個のファイルを表示
//させ、これを選択した後、データの読み込みを行い、そのデータをLCD上に再表示する
//プログラムの一部で、SDカードに直接アクセスする部分のみ。
unsigned int  finnd_SD_card(void) {// MS-DOSのDIRに相当する関数
 
    DEMO_STATE demoState = DEMO_STATE_NO_MEDIA;
 	FILEIO_OBJECT file;
    FILEIO_SEARCH_RECORD searchRecord;
    RTCC_DATETIME dateTime;
    SYSTEM_Initialize();

    dateTime.bcdFormat = false;
    RTCC_BuildTimeGet(&dateTime);
    RTCC_Initialize(&dateTime);

    // Initialize the library
    if (!FILEIO_Initialize())
    {
     //   while(1);
        FILEIO_Initialize();
    }
    
    // Register the GetTimestamp function as the timestamp source for the library.
    FILEIO_RegisterTimestampGet (GetTimestamp);
    
    //init_SDcard();
//    GLED=1;
    unsigned char i,k;
   uint16_t SD_ER = 0;
    
   while(SD_ER == 0) {

//   testdisp("demostate",demoState,2);//string.val.degi
        switch (demoState) {
            case DEMO_STATE_NO_MEDIA:
                // Loop on this function until the SD Card is detected.
                if (FILEIO_MediaDetect(&gSdDrive, &sdCardMediaParameters) == true) {
                    demoState = DEMO_STATE_MEDIA_DETECTED;
 
                    }

                break;
            case DEMO_STATE_MEDIA_DETECTED://SDカードがみつかればドライブをマウント
                if (FILEIO_DriveMount('A', &gSdDrive, &sdCardMediaParameters) == FILEIO_ERROR_NONE)
                {
                    demoState = DEMO_STATE_DRIVE_MOUNTED;
                }
                else
                {
                    demoState = DEMO_STATE_NO_MEDIA;
                }
                if (FILEIO_DriveMount('A', &gSdDrive, &sdCardMediaParameters) == FILEIO_ERROR_NONE)
//                SD_ER=(FILEIO_DriveMount('A', &gSdDrive, &sdCardMediaParameters));
                
                    {
                    demoState = DEMO_STATE_DRIVE_MOUNTED;
 //                   GLED=1;//LEDは動作確認の為、デバッグに使ったもので、実際は不要です。
                     } else {
                    demoState = DEMO_STATE_NO_MEDIA;

                    }

                    break;
            case DEMO_STATE_DRIVE_MOUNTED://ドライブマウント済みならファイル検索
                i=0;
                if (FILEIO_Find ((uint16_t *)L"*.BMP", FILEIO_ATTRIBUTE_MASK, &searchRecord, true) == FILEIO_RESULT_SUCCESS) {
                    i=0;
                    set_dir_fname(&searchRecord,i);//ファイル名を*.bmpとする

                    i++;
                }//else{testdisp("str",i,2); }
                    while (i < maxDIR) {	//ファイル名は最大64個まで
                        if (FILEIO_Find ((uint16_t *)L"*.BMP", FILEIO_ATTRIBUTE_MASK, &searchRecord, false) == FILEIO_RESULT_SUCCESS) {
                           set_dir_fname(&searchRecord,i);

                            i++;
                            } else {break;}//whileループから抜ける為
                        }
 

                demoState = DEMO_STATE_DONE;
               // SD_ER=1;//アンマウントしたらループから抜ける為SD_ER＝1とする

                break;
              
            case DEMO_STATE_DONE://ファイルを検索して表示したら一旦ドライブをアンマウント
                // Now that we've written all of the data we need to write in the application, wait for the user
                // to remove the card
                 FILEIO_DriveUnmount ('A');//ドライブアンマウント
                if (FILEIO_MediaDetect(&gSdDrive, &sdCardMediaParameters) == false)
                {
                    demoState = DEMO_STATE_NO_MEDIA;
                //    SD_ER=1;

               }
              SD_ER=1;
               break;
            case DEMO_STATE_FAILED:
                // An operation has failed.  Try to unmount the drive.  This will also try to
                // close all open files that use this drive (it will at least deallocate them).
                FILEIO_DriveUnmount ('A');
 
                demoState = DEMO_STATE_NO_MEDIA;
                SD_ER=2;
                break;
        }

    }

        return SD_ER;
}

void get_SDdata(unsigned int *sptr,uint16_t max) {//テキストバイナリデータを40バイト読み込む
     uint8_t C=1;
     uint8_t i=0;
     for (i = 0;i<max;i++){
        C=FILEIO_GetChar(sptr);
        BMPdata[i]=C;
        }
     analysBMPdata();

}
unsigned int  open_SD_card(uint8_t *OFname) {//特定したファイルを読み込む
   DEMO_STATE demoState = DEMO_STATE_NO_MEDIA;
   FILEIO_OBJECT file;
   RTCC_DATETIME dateTime;
    SYSTEM_Initialize();
    dateTime.bcdFormat = false;
    RTCC_BuildTimeGet(&dateTime);
    RTCC_Initialize(&dateTime);
    uint8_t c0,cr,cg,cb;
    int32_t Gifindex,ig;
    // Initialize the library
    if (!FILEIO_Initialize())
    {

        FILEIO_Initialize();
    }
    
    // Register the GetTimestamp function as the timestamp source for the library.
    FILEIO_RegisterTimestampGet (GetTimestamp);
    

    uint16_t SD_ER = 0;

    fname8tofname16(OFname);
    while(SD_ER == 0) {
        switch (demoState) {
            case DEMO_STATE_NO_MEDIA:
                  if (FILEIO_MediaDetect(&gSdDrive, &sdCardMediaParameters) == true) {
                    demoState = DEMO_STATE_MEDIA_DETECTED;
                    } else {
                    SD_ER=2;
                    }
                    break;
            case DEMO_STATE_MEDIA_DETECTED:
                if (FILEIO_DriveMount('A', &gSdDrive, &sdCardMediaParameters) == FILEIO_ERROR_NONE)
                {
                    demoState = DEMO_STATE_DRIVE_MOUNTED;
                }
                else
                {
                    demoState = DEMO_STATE_NO_MEDIA;
                }
                 

                    
                    break;
           case DEMO_STATE_DRIVE_MOUNTED://ドライブマウント完了後、ファイルをオープン
                if (FILEIO_Open (&file,(uint16_t *)fname16, FILEIO_OPEN_READ) == FILEIO_RESULT_FAILURE) {
					//fname16はファイル名をUTF-16でエンコードしたファイル名で、通常の8bit　ASCIIからfname8tofname16(fptr)で作っています。
                    demoState = DEMO_STATE_FAILED;

                    SD_ER=3;
 //                   testdisp("SD_ER",SD_ER,2);
                    break;
                    }
                    SD_ER=50;
 
                get_SDdata(&file,40); //データを1行読む
       if (FILEIO_Seek(&file,offset, FILEIO_SEEK_SET) != FILEIO_RESULT_SUCCESS){
           SD_ER=4;
//           testdisp("SD_ER",SD_ER,2);
           break;} else {
//           testdisp("SD_ER",41,2);
//           if (Vbmp > 480){Vbmp = 480;}
//           if (Hbmp > 320){Hbmp = 320;}
          
           Bmpdisplay(0,0,Hbmp,Vbmp,&file); 
           


    }
      if (FILEIO_Close (&file) != FILEIO_RESULT_SUCCESS) {//ファイルクローズ
                    demoState = DEMO_STATE_FAILED;
                    SD_ER=3;

                    return SD_ER;
                }
              
                // We're done with this drive.
                // Unmount it.
                FILEIO_DriveUnmount ('A');//ドライブアンマウント
                demoState = DEMO_STATE_DONE;
                SD_ER=20;

       return SD_ER;
}

    }

}

void GetTimestamp (FILEIO_TIMESTAMP * timeStamp)
{
    BSP_RTCC_DATETIME dateTime;

    dateTime.bcdFormat = false;

    RTCC_TimeGet(&dateTime);

    timeStamp->timeMs = 0;
    timeStamp->time.bitfield.hours = dateTime.hour;
    timeStamp->time.bitfield.minutes = dateTime.minute;
    timeStamp->time.bitfield.secondsDiv2 = dateTime.second / 2;

    timeStamp->date.bitfield.day = dateTime.day;
    timeStamp->date.bitfield.month = dateTime.month;
    // Years in the RTCC module go from 2000 to 2099.  Years in the FAT file system go from 1980-2108.
    timeStamp->date.bitfield.year = dateTime.year + 20;;
}

