/*
 * ILI9341_Display_Graph.c
 *
 *  Created on: 2024/11/21
 *      Author: egaono-electronics
 */

#include "ILI9341_Display_Graph.h"

#include def_H_Periph_SPI
#include "ILI9341_SPI_Draw.h"



//----------------------------------------------------------
// LCDにグラフデータを送信する。 : ILI9341
//----------------------------------------------------------
// 引数;
// uint8_t *puint8_JobNum : 処理番号を格納する変数のポインタ

// uint8_t uint8_Oblong : 縦長/横長
//    0 : Lengthwise : 縦長 左
//    1 : Lengthwise : 縦長 右
//    2 : WidthwiseL : 横長 左
//    3 : WidthwiseR : 横長 右

// uint16_t uint16_StartX : 表示開始位置X
// uint16_t uint16_StartY : 表示開始位置Y

// uint16_t uint16_Width : 表示幅
// uint16_t uint16_Height : 表示高さ

// uint8_t *puint8_aGraphData :
//              Graphデータが格納されているBufferのポインタ


// 戻り値;
//   -1 : 処理中
//    0 : OK終了
//    1 : NG終了
//----------------------------------------------------------
int16_t ILI9341_SPI_Send_GraphData(uint8_t *puint8_JobNum,
                                   uint8_t uint8_Oblong,
                                   uint16_t uint16_StartX,
                                   uint16_t uint16_StartY,
                                   uint16_t uint16_Width,
                                   uint16_t uint16_Height,
                                   uint8_t *puint8_aGraphData)
{
  static struct sFrame_LCD STC_structFrame_LCD;
  static uint8_t STC_uint8_JobNum;  // 設定処理番号

  static uint16_t STC_uint16_SendLength;
  static uint16_t STC_uint16_Position;
  static uint16_t STC_uint16_SendCount;

  static int16_t STC_int16_Value_Wait_SPI_TxRx;
                                    // SPI送受信待ちの値


  int16_t int16_Return;
  int16_t int16_I;


  switch(*puint8_JobNum)
  {
  case 0:
    STC_uint8_JobNum = 0;  // 設定処理番号初期化

    STC_uint16_Position = 0;
    STC_uint16_SendCount = 0;

    //--------------------------------------
    // 表示Frame位置を構造体に設定
    //--------------------------------------
    STC_structFrame_LCD.uint16_SC = uint16_StartX;
    STC_structFrame_LCD.uint16_EC
                    = uint16_StartX + uint16_Width - 1;

    STC_structFrame_LCD.uint16_SP = uint16_StartY;
    STC_structFrame_LCD.uint16_EP
                    = uint16_StartY + uint16_Height - 1;


    (*puint8_JobNum)++;  // 次の処理番号に移行する。
    int16_Return = -1;   // 処理継続
    break;

  case 1:
    //----------------------------------------------------------
    // 表示Frame設定
    //----------------------------------------------------------
    // 引数;
    // uint8_t *puint8_JobNum : 処理番号を格納する変数のポインタ

    // uint16_t uint16_Oblong : 縦長/横長 選択
    //    0 : Lengthwise : 縦長 左
    //    1 : Lengthwise : 縦長 右
    //    2 : WidthwiseL : 横長 左
    //    3 : WidthwiseR : 横長 右

    // struct sFrame_LCD *pstructFrame_LCD :
    //                      表示パラメータ構造体のポインタ

    // 戻り値;
    //   -1 : 処理中
    //    0 : OK
    //    1 : NG
    //----------------------------------------------------------
    int16_Return = ILI9341_SPI_SetFrame(&STC_uint8_JobNum,
                                        (uint16_t)uint8_Oblong,
                                        &STC_structFrame_LCD);
    if(int16_Return == -1){
      // 処理中
      break;  // 処理番号維持 : 処理継続 : 現在の処理番号をループ
    }

    if(int16_Return != 0){
      *puint8_JobNum = 0;  // 処理番号初期化
      break;  // NG終了
    }

    // 送信データ数セット
    STC_uint16_SendLength = uint16_Width * def_RGB_byte;

    (*puint8_JobNum)++;  // 次の処理番号に移行する。
    int16_Return = -1;   // 処理継続
    break;

  case 2:
    //----------------------------------------------------------
    // LCDに表示Dataを送信する。
    //----------------------------------------------------------
    // 引数;
    // uint8_t *puint8_JobNum : 処理番号を格納する変数のポインタ

    // int16_t int16_NSS_OnOff :
    //                  設定データ送信終了時NSS ON/OFF選択
    //    0 : 送信後 NSSをOFFにする。
    //    1 : 送信後 NSSをONのままにする。

    // uint16_t uint16_Length : 送信データ数
    // uint8_t *puint8_aData :
    //          送信データが格納されているBufferのポインタ

    // 戻り値;
    //   -1 : 処理中
    //    0 : OK
    //    1 : NG
    //----------------------------------------------------------
    int16_Return = ILI9341_SPI_SendData(&STC_uint8_JobNum,
                                        1,
                                        STC_uint16_SendLength,
                        &puint8_aGraphData[STC_uint16_Position]);
    if(int16_Return == -1){
      // 処理中
      break;  // 処理番号維持 : 処理継続 : 現在の処理番号をループ
    }

    if(int16_Return != 0){
      *puint8_JobNum = 0;  // 処理番号初期化
      break;  // NG終了
    }

    // 終了判定
    STC_uint16_SendCount++;
    // 指定された表示高さの分、データを送信したか判定する。
    if(STC_uint16_SendCount < uint16_Height){
      // 全てを送信していない場合
      STC_uint16_Position += STC_uint16_SendLength;
                                    // 次のデータ位置をセット

      (*puint8_JobNum)++;  // 次の処理番号に移行する。: case 3:
      int16_Return = -1;   // 処理継続
      break;
    }

    *puint8_JobNum = 0;  // 処理番号初期化
    int16_Return = 0;    // OK終了
    break;

  case 3:
    // 送信データ数セット
    GLB_structParam_Handle_SPI1.int16_vSPI_TxNumber
                            = uint16_Width * def_RGB_byte;

    for(int16_I = 0;
        int16_I < GLB_structParam_Handle_SPI1.int16_vSPI_TxNumber;
        int16_I++){
      GLB_structParam_Handle_SPI1.puint8_aSPI_TxBuffer[int16_I]
            = puint8_aGraphData[STC_uint16_Position
            + (uint16_t)int16_I];
    }

    (*puint8_JobNum)++;  // 次の処理番号に移行する。
    int16_Return = -1;   // 処理継続
    break;

  case 4:
    // SPI送信 : データのみ送信
    if(STC_uint16_SendCount == uint16_Height - 1){
      //----------------------------------------------------------
      // SPIx  Master送受信
      //----------------------------------------------------------
      // 引数;
      // uint8_t *puint8_JobNum : 処理番号を格納する変数のポインタ

      // SPI_HandleTypeDef *pHandle_SPIx : SPI handler declaration

      // IRQn_Type DMA_Stream_IRQn_Transmit_SPIx : SPI DMA Transmit IRQn
      // IRQn_Type DMA_Stream_IRQn_Receive_SPIx : SPI DMA Receive IRQn

      // struct sParam_Handle_SPIx *pstructParam_Handle_SPIx :
      //              Handle SPI用パラメータの構造体のポインタ

      // GPIO_TypeDef *pGPIOx_SPIx_NSS : SPIx_NSS のGPIOポート
      // uint16_t uint16_GPIO_Pin_x_SPIx_NSS : SPIx_NSS のGPIOピン

      // int16_t int16_Value_Wait_SPI_TxRx : SPI送受信待ちの値

      // int16_t int16_NSS_OnOff : 送信終了時NSS ON/OFF選択
      //    0 : 送信後 NSSをOFFにする。
      //    1 : 送信後 NSSをONのままにする。


      // 戻り値;
      //   -1 : 処理中
      //    0 : OK
      //    1 : NG
      //----------------------------------------------------------
      int16_Return = SPIx_Master_TxRxByte(&STC_uint8_JobNum,
                                          &Handle_SPI1,
                                          DMA2_Stream3_IRQn,
                                          DMA2_Stream2_IRQn,
                                          &GLB_structParam_Handle_SPI1,
                                          def_GPIOx_SPI1_NSS,
                                          def_GPIO_PIN_x_SPI1_NSS,
                                          STC_int16_Value_Wait_SPI_TxRx,
                                          0);
    }
    else{
      int16_Return = SPIx_Master_TxRxByte(&STC_uint8_JobNum,
                                          &Handle_SPI1,
                                          DMA2_Stream3_IRQn,
                                          DMA2_Stream2_IRQn,
                                          &GLB_structParam_Handle_SPI1,
                                          def_GPIOx_SPI1_NSS,
                                          def_GPIO_PIN_x_SPI1_NSS,
                                          STC_int16_Value_Wait_SPI_TxRx,
                                          1);
    }
    if(int16_Return == -1){
      // 処理中
      break;  // 処理番号維持 : 処理継続
    }

    if(int16_Return != 0){
      *puint8_JobNum = 0;  // 処理番号初期化
      break;  // NG終了
    }

    // 終了判定
    STC_uint16_SendCount++;
    // 指定された表示高さの分、データを送信したか判定する。
    if(STC_uint16_SendCount < uint16_Height){
      // 全てを送信していない場合
      STC_uint16_Position
          += GLB_structParam_Handle_SPI1.int16_vSPI_TxNumber;
                                    // 次のデータ位置をセット

      (*puint8_JobNum)--;  // 次の処理番号に移行する。: case 3:
      int16_Return = -1;   // 処理継続
      break;
    }


    // End : NSS OFF
    HAL_GPIO_WritePin(def_GPIOx_LCD_SPI_NSS,
                      def_GPIO_PIN_x_LCD_SPI_NSS,
                      GPIO_PIN_SET);


    *puint8_JobNum = 0;  // 処理番号初期化
    int16_Return = 0;    // OK終了
    break;

  default:
    *puint8_JobNum = 0;  // 処理番号初期化
    int16_Return = 1;    // NG
    break;
  }

  return(int16_Return);
}
