/*******************************************************************************
 * 　Task5　SDカードへのログ実行
 * 　　2種類のデータを「LogFile.txt」ファイルに追記する
 * 　　　センサデータ3種　と　電圧データ2種 
 *******************************************************************************/

// *****************************************************************************
// *****************************************************************************
// Section: Included Files
// *****************************************************************************
// *****************************************************************************

#include "task5.h"

// *****************************************************************************
// *****************************************************************************
// Section: Global Data Definitions
// *****************************************************************************
// *****************************************************************************

// *****************************************************************************
/* Application Data

  Summary:
    Holds application data

  Description:
    This structure holds the application's data.

  Remarks:
    This structure should be initialized by the TASK5_Initialize function.

    Application strings and buffers are be defined outside this structure.
*/

TASK5_DATA task5Data;

// キューハンドル定義
QueueHandle_t  LOGQueue;
QueueHandle_t  LCDQueue;
/* Application Data*/
APP_DATA appData;
#define SDCARD_MOUNT_NAME    "/mnt/mydrive"
#define SDCARD_DEV_NAME      "/dev/mmcblka1"

/** グローバル変数定義 ***/
uint8_t WriteBufM[] = "M,xxxx.x,xx.xx,xx.xx\r\n";
uint8_t WriteBufV[] = "V,x.xx,x.xx\r\n";
uint8_t LogFlag;                        // ログ中フラグ
/** キュー受信用バッファ定義 ***/
union {
    uint8_t Buf[20];
    struct {
        uint8_t kind;
        float data1;
        float data2;
        float data3;
    }mes;
}LogData;

/** LCDメッセージ用データ定義 ****/
union {
    uint8_t Buf[20];
    struct{
        uint8_t kind;
        uint8_t msg[13];    // メッセージデータ
    }mes;
}LogMsg;
/** LCDメッセージ漢字データ定義 ***/
uint8_t StartLog[]  = {0x81,0x40,0x83,0x8D,0x83,0x4D,0x83,0x93,0x83,0x4F,0x8A,0x4A,0x8E,0x6E,0x81,0x40,0x00,0x00};     //ロギング開始
uint8_t EndLog[]    = {0x81,0x40,0x83,0x8D,0x83,0x4D,0x83,0x93,0x83,0x4F,0x8F,0x49,0x97,0xB9,0x81,0x40,0x00,0x00};     //ロギング終了
uint8_t WriteErr[]  = {0x81,0x40,0x8F,0x91,0x8D,0x9E,0x82,0xDD,0x83,0x43,0x83,0x89,0x81,0x5B,0x81,0x40,0x00,0x00};     //書込みエラー
/** 関数プロト ***/        
void ftostring(int seisu, int shousu, float data, uint8_t *buffer);
// *****************************************************************************
// *****************************************************************************
// Section: Application Callback Functions
// *****************************************************************************
// *****************************************************************************

/* TODO:  Add any necessary callback functions.
*/

// *****************************************************************************
// *****************************************************************************
// Section: Application Local Functions
// *****************************************************************************
// *****************************************************************************


/* TODO:  Add any necessary local functions.
*/


// *****************************************************************************
// *****************************************************************************
// Section: Application Initialization and State Machine Functions
// *****************************************************************************
// *****************************************************************************

/*******************************************************************************
  Function:
    void TASK5_Initialize ( void )

  Remarks:
    See prototype in task5.h.
 */

void TASK5_Initialize ( void )
{
    /* Place the App state machine in its initial state. */
    task5Data.state = TASK5_STATE_INIT;
    
    appData.APstate = APP_WAIT_SWITCH_PRESS;

    /* TODO: Initialize your application's state machine and other
     * parameters.
     */
}


/******************************************************************************
  Function:
    void TASK5_Tasks ( void )

  Remarks:
    See prototype in task5.h.
 */

void TASK5_Tasks ( void )
{

    /* Check the application's current state. */
    switch ( task5Data.state )
    {
        /* Application's initial state. */
        case TASK5_STATE_INIT:
        {
            bool appInitialized = true;


            if (appInitialized)
            {

                task5Data.state = TASK5_STATE_SERVICE_TASKS;
            }
            break;
        }

        case TASK5_STATE_SERVICE_TASKS:
        {

            switch ( appData.APstate )
            {  
                /** S1スイッチオン待ち **/
                case APP_WAIT_SWITCH_PRESS:
                    if(S1_Get() == 0){                                      // S1オン
                        LogFlag = 1;                                        // ログ中フラグオン
                        LogMsg.mes.kind = 'S';                              // 種類                        
                        strcpy((char *)LogMsg.mes.msg, (char *)StartLog);
                        /** キューへ送信 **/
                        xQueueSend(LCDQueue, LogMsg.Buf, 0);
                        appData.APstate = APP_MOUNT_DISK;                   // マウントへ
                    }
                    break;
                /** SDカードのマウント **/
                case APP_MOUNT_DISK:
                    if(SYS_FS_Mount(SDCARD_DEV_NAME, SDCARD_MOUNT_NAME, FAT, 0, NULL) != 0){
                        appData.APstate = APP_MOUNT_DISK;                   // 失敗ならマウント繰り返し
                    }
                    else{                                           
                        appData.APstate = APP_OPEN_FILE;                    // 成功ならファイルオープンへ
                    }
                    break;
                /* ファイルオープン実行 */  
                case APP_OPEN_FILE:
                    appData.fileHandle = SYS_FS_FileOpen("LogFile.txt", (SYS_FS_FILE_OPEN_APPEND));
                    if(appData.fileHandle == SYS_FS_HANDLE_INVALID)         // ハンドル無効の場合
                        appData.APstate = APP_ERROR;                        // エラーへ
                    else{
                        appData.APstate = APP_WAIT_QUEUE;                   // 成功なら書き込みへ
                    }
                    break;                    
                /** キューからデータ取り出し **/    
                case APP_WAIT_QUEUE:                                        // キュー待ち
                    if(S2_Get() == 0)                                       // S2がオンの時
                        appData.APstate = APP_CLOSE_FILE;                   // 終了クローズへ
                    else{
                        /** キューから取り出し **/
                        xQueueReceive(LOGQueue, LogData.Buf, portMAX_DELAY);
                        appData.APstate = APP_WRITE_FILE;                   // 書き込みへ
                    }
                    break;                  
                /** 書き込み実行 ***/
                case APP_WRITE_FILE:
                    if(LogData.mes.kind == 'M'){                            // センサデータの場合
                        Red_Set();                        
                        ftostring(4, 1, LogData.mes.data1, WriteBufM+2);    // データ文字変換
                        ftostring(2, 2, LogData.mes.data2, WriteBufM+9);
                        ftostring(2, 2, LogData.mes.data3, WriteBufM+15);

                        if(SYS_FS_FileWrite(appData.fileHandle, (const void *)WriteBufM, 22) == -1)
                        {   /* エラーの場合 */             
                            SYS_FS_FileClose(appData.fileHandle);           // ファイルクローズ 
                            appData.APstate = APP_ERROR;                    // エラーへ
                        }
                        else{
                           appData.APstate = APP_WAIT_QUEUE;                // キュー待ちへ戻る 
                           Red_Clear();
                        }
                    }
                    else if(LogData.mes.kind == 'V'){                       // 電圧データの場合
                        Green_Set();                         
                        ftostring(1, 2, LogData.mes.data1, WriteBufV+2);    // データ文字変換
                        ftostring(1, 2, LogData.mes.data2, WriteBufV+7);  
                        if(SYS_FS_FileWrite(appData.fileHandle, (const void *)WriteBufV, 13) == -1)
                        {   /* エラーの場合 */             
                            SYS_FS_FileClose(appData.fileHandle);           // ファイルクローズ 
                            appData.APstate = APP_ERROR;                    // エラーへ
                        }
                        else{
                            appData.APstate = APP_WAIT_QUEUE;               // キュー待ちへ戻る 
                            Green_Clear();
                        }
                    }
                    break;
                /** ファイルクローズ処理 ***/    
                case APP_CLOSE_FILE:
                    SYS_FS_FileClose(appData.fileHandle);                   // ファイルクローズ                    
                    appData.APstate = APP_UNMOUNT;                          // アンマウントへ
                    LogFlag = 0;                                            // ログ中フラグオフ
                    break;
                /*** ドライブアンマウント実行 ***/    
                case APP_UNMOUNT:
                    if(SYS_FS_Unmount(SDCARD_MOUNT_NAME) != SYS_FS_RES_SUCCESS)
                        appData.APstate = APP_UNMOUNT;                      // 失敗なら繰り返し
                    else{
                        LogMsg.mes.kind = 'S';                              // 種類  
                        strcpy((char *)LogMsg.mes.msg, (char *)EndLog);
                        /** キューへ送信 **/
                        xQueueSend(LCDQueue, LogMsg.Buf, 0);                        
                        appData.APstate = APP_WAIT_SWITCH_PRESS;            // 次の開始待ちへ                 
                    }
                    break;  
                case APP_ERROR:
                        /** エラー処理なし **/
                        LogMsg.mes.kind = 'E';                              // 種類  
                        strcpy((char *)LogMsg.mes.msg, (char *)WriteErr);
                        /** キューへ送信 **/
                        xQueueSend(LCDQueue, LogMsg.Buf, 0);                      
                    break;            
                default:
                    break;
            } 
            
            break;
        }

        /* TODO: implement your application state machine.*/


        /* The default state should never be executed. */
        default:
        {
            /* TODO: Handle error in application's state machine. */
            break;
        }
    }
}


/*******************************************************************************
 End of File
 */
