/****************************************************************
*
* lin_config.h
*
* LIN処理
*
*
*
*
*                                                     2026/04/15
*                                                     DNC S.Tasaka
*
******************************************************************/
#ifndef LIN_CONFIG_H_
#define LIN_CONFIG_H_

// インクルードファイル
#include <ti/devices/msp/msp.h>
#include <ti/driverlib/driverlib.h>
#include <ti/driverlib/m0p/dl_core.h>
#include "ti_msp_dl_config.h"
#include "lin_message.h"

// 定数定義
#ifdef KICK_DEBUG
#define LIN_RESPONDER_NUM_MSGS      (0x04)                      // LINテーブルメッセージ数
#else
#define LIN_RESPONDER_NUM_MSGS      (0x03)                      // LINテーブルメッセージ数
#endif
#define LIN_PID_MASK                (0x3F)                      // LIN PID(Protected IDentifier Field)のID部分のマスク
//#define LIN_DATA_MAX_BUFFER_SIZE    (8)                         // LINフレーム最大ペイロードサイズ(LIN仕様: 1-8 bytes)
#define LIN_TBIT_BREAK_FIELD_MAX    (20)                        // 最大ブレークフィールド長 20Tbit (タイムアウト検出用)
#define LIN_RESPONDER_SYNC_CYCLES   (4)                         // 同期フィールド検証に使用されるPWMサイクル数。
                                                                // LIN 2.2A セクション6.4.2によると、同期フィールドは5つの立ち下がりエッジで構成されます。
                                                                // (スタートビット + 0x55のデータビット4つ)、これにより4つの測定可能なビット期間が得られます。
#define LIN_SYNC_BYTE               (0x55)                      // LIN Syncバイト値0x55（クロック同期のための1と0の交互の並び）
#define LIN_RESPONSE_LAPSE          (LIN_0_INST_FREQUENCY / (2 * LIN_0_BAUD_RATE))
                                                                // バイト間隔：PIDの停止ビットと応答データの開始ビット間の遅延時間。
                                                                // 適切な間隔を確保するため、半ビット時間として計算されます。

#define AUTO_BAUD_ENABLED           (true)                      // 自動ボーレート同期機能を有効/無効
#define LIN_AUTO_BAUD_MAX           (105)                       // 自動ボーレートしきい値MAX
#define LIN_AUTO_BAUD_MIN           (95)                        // 自動ボーレートしきい値MIN
#define AUTO_BAUD_THRESHOLD         (3)                         // 自動ボーレート再調整がトリガーされるまでに必要な連続同期失敗回数。
                                                                // 一時的なエラーによる再調整を防ぎます。
#define AUTO_BAUD_CONFIG_DELAY      (10)                        // ボーレート変更後のUART周辺機器の安定化までの遅延サイクル

#define TIMEOUT                     (48U)                       // 受信タイムアウト期間（フレームタイムアウト検出のためのタイマー再読込値）1.5ms

// TypeDef定義
typedef UART_Regs *LIN_Peripheral_t;                            // UART拡張周辺機器タイプおよびレジスタアクセス
typedef void (*LIN_function_ptr_t)(void* lin,uint8_t index, bool flag);
                                                                // LINメッセージコールバック用の関数ポインタ型
                                                                // 特定のPIDが受信または送信されたときに呼び出されます。
// (LIN_STATE)
// LINの状態遷移 - LINはフレームを受信すると、以下の状態を順に遷移します。
// BREAK -> SYNC (NEG/POSエッジ) -> PID -> DATA
typedef enum {
    LIN_STATE_WAIT_FOR_BREAK        = 0,                        // アイドル状態：ブレークフィールドを待機中（13ビット以上の時間でドミナントバス）
    LIN_STATE_BREAK_FIELD           = 1,                        // ブレークを検出しました: ブレークフィールドの持続時間を測定しています
    LIN_STATE_SYNC_FIELD_NEG_EDGE   = 2,                        // 同期フィールド：ビットタイミングを測定するために立ち下がりエッジを待機
    LIN_STATE_SYNC_FIELD_POS_EDGE   = 3,                        // 同期フィールド：ビット時間測定を完了するために立ち上がりエッジを待機
    LIN_STATE_PID_FIELD             = 4,                        // PIDフィールド：保護識別子バイトを受信して​​検証する
    LIN_STATE_DATA_FIELD            = 5                         // データフィールド：受信/送信データバイトとチェックサム
} LIN_STATE;

// (LIN_ERROR)
// LINエラーコード(ダイアグ用)
#if 1 // DNC
typedef uint16_t    LIN_ERROR;
#define LIN_ERROR_BIT                       (0x01)              // BITエラー        送信データを受信比較して不一致
#define LIN_ERROR_CHECKSUM                  (0x02)              // CHECKSUMエラー   受信データ最後のチェックサム異常
#define LIN_ERROR_IDENTIFIER_PARITY         (0x04)              // PARITYエラー     PID2ビットのパリティエラー
#define LIN_ERROR_INCONSISTENT_SYNCH_FIELD  (0x08)              // SYNCエラー       SYNCエッジエラー
#define LIN_ERROR_FRAME                     (0x10)              // FRAMEエラー      STOP BITエラー
#else
typedef enum {
    LIN_ERROR_NO_ERROR      = 0,                                // エラーなし
    LIN_ERROR_BREAK_SHORT   = 1,                                // ブレークフィールドが短すぎます（レスポンダーの場合、11ビット時間未満）。
    LIN_ERROR_BREAK_LONG    = 2,                                // ブレークフィールドが長すぎます（最大許容時間を超えています）
    LIN_ERROR_SYNC          = 3                                 // 同期バイトの不一致（受信値 != 0x55）
} LIN_ERROR;
#endif

// (16ビット値へのバイト/ワードアクセス用の共用体)
// バイトレベルのアクセスが必要なチェックサム計算に使用
typedef union {
    uint16_t    word;                                           // 16ビットワードとしてアクセス
    uint8_t     byte[2];                                        // 2バイトの配列としてアクセス
} LIN_word_t;

// (LINメッセージテーブルレコード)
// レスポンダーのメッセージテーブルに単一のエントリを定義します。
// 各レコードは、PID、データ長、およびオプションのコールバックをマッピングします。
#if 1
// --LIN PID処理テーブル構造体
typedef struct {
    uint8_t             tableIdx;                                           // TID
    uint8_t             msgID;                                              // PID
    uint8_t             msgIDWithParity;                                    // PID
    uint8_t             msgSize;                                            // データフィールド長
    uint8_t             isMsgRecv;                                          // 受信データか
    LIN_function_ptr_t  callbackFunction;                                   // PIDコールバック関数
} LIN_table_record_t;
#else
typedef struct {
    uint8_t             msgID;                                  // Protected Identifier (PID)
    uint8_t             msgSize;                                // データフィールド長 (1-8 bytes)
    LIN_function_ptr_t  callbackFunction;                       // メッセージの受信/送信時にコールバックが呼び出されます
} LIN_table_record_t;
#endif

//(Syncフィールドビットタイミング測定)
// 同期フィールド中の1ビット期間のタイマーキャプチャ値を格納
typedef struct {
    uint16_t negEdge;                                           // フォーリングエッジのタイマー値
    uint16_t posEdge;                                           // ライジングエッジのタイマー値
} LIN_sync_bits_t;

// (LINタイミングと自動ボーレートコンテキスト)
// タイミング関連の測定値と自動ボーレート状態をすべて含みます。
typedef struct {
    // ブレークフィールドタイミング
    uint32_t        brkW;                                       // 測定されたブレークフィールド幅（タイマーカウント）
    uint16_t        brkCmp;                                     // 検証のために、フィールドの値を比較する区切り

    // Syncフィールド計測
    bool            syncStart;                                  // フラグ: 同期開始ビットが検出されました
    LIN_sync_bits_t syncBt[LIN_RESPONDER_SYNC_CYCLES];          // 各同期サイクルのビットタイミング
    uint8_t         syncOkCnt;                                  // 有効な同期サイクルの数
    uint8_t         syncErrCnt;                                 // 同期サイクルの失敗回数

    // Bit時間計算
    uint16_t        btSum;                                      // 測定されたビット時間の合計
    uint16_t        btAvg;                                      // 平均ビット時間 (btSum / num_cycles)
    uint16_t        btWidth;                                    // 現在のビット時間幅
    uint16_t        btWMin;                                     // 許容される最小ビット幅（下限値）
    uint16_t        btWMax;                                     // 許容される最大ビット幅（上限値）

    // ボーレートトラッキング
    uint16_t        brMeas;                                     // 同期フィールドから計測したボーレート
    uint16_t        brPrev;                                     // 以前のボーレート（再調整前）
    uint16_t        brCurr;                                     // 現在設定されているボーレート

    // 自動ボーレート状態
    bool            autoBaud;                                   // フラグ: 自動ボーレート調整が有効

    // レスポンスタイミング
    uint16_t        respDelay;                                  // PID制御から応答までの遅延時間（クロックサイクル）
} Lin_timing_t;

// (LIN送受信コンテキスト)
// LINステートマシン、バッファ、および設定を含む主要構造
typedef struct {
    // ステートマシン
    volatile LIN_STATE      state;                              // カレントLIN状態

    // メッセージテーブル
    LIN_table_record_t      *respMsgTbl;                        // メッセージテーブルへのポインタ
    uint8_t msgTblIdx;                                          // カレントメッセージテーブルインデックス

    // 受信コンテキスト
    volatile uint8_t        rxIdx;                              // カレント受信バッファインデックス
    uint8_t                 rxBuf[LIN_DATA_MAX_BUFFER_SIZE];    // 受信バッファ

    // 送信コンテキスト
    volatile uint8_t        txIdx;                              // カレント送信バッファインデックス
    uint8_t                 txBuf[LIN_DATA_MAX_BUFFER_SIZE];    // 送信バッファ

    // チェックサム
    LIN_word_t              chkSum;                             // 実行中チェックサム計算
    uint8_t                 sendChkSum;                         // 送信完了したチェックサム

    //タイマー処理
    volatile uint8_t        isNoErr1500ms;                      // DIAG記録用カウンタ

    // タイミング参照
    volatile Lin_timing_t   *timing;                            // タイミングコンテキストへのポインタ
} Lin_TxRxCtx_t;

// (LINダイアグインフォメーション)
// デバッグのために、最後に受信したフレームの診断データを保存
typedef struct {
//    uint8_t                 syncByte;                           // 同期バイト受信（0x55であるはず）--- 未使用
//    uint8_t                 PID;                                // Protected Identifier受信      --- 未使用
    volatile LIN_ERROR        error;                              // 最終エラーコード
} LIN_diag_t;

// 外部参照変数
extern const LIN_table_record_t       gMessageTable[LIN_RESPONDER_NUM_MSGS];
                                                                // メッセージテーブル
                                                                // ユーザーはアプリケーションファイル（lin_responder.c）でメッセージテーブルを定義する必要あり
extern Lin_TxRxCtx_t            gLIN;                           // Global LIN transmit/receive context
extern LIN_diag_t               gLINDiag;                       // Global LIN diagnostic data
extern volatile Lin_timing_t    gLINT;                          // Global LIN timing context
extern void LIN_processMessage_Tx(void);                        // Transmit complete callback (must be defined in application)

void lin_enable(void);
void lin_disable(void);

// プロトタイプ宣言
// Process received Protected Identifier (PID)
// param[in] peripheral  Pointer to LIN peripheral instance
// param[in] rxByte      Received PID byte
// param[in] lin         Pointer to LIN context structure
void LIN_Responder_receivePID(LIN_Peripheral_t peripheral, uint8_t rxByte, Lin_TxRxCtx_t *lin, LIN_diag_t *lin_diag);

// Receive data bytes and validate checksum
// param[in] peripheral  Pointer to LIN peripheral instance
// param[in] rxByte      Received data byte
// param[in] lin         Pointer to LIN context structure
void LIN_Responder_receiveMessage(LIN_Peripheral_t peripheral, uint8_t rxByte, Lin_TxRxCtx_t *lin, LIN_diag_t *lin_diag);

// Transmit data bytes and checksum
// param[in] peripheral  Pointer to LIN peripheral instance
// param[in] lin         Pointer to LIN context structure
void LIN_Responder_transmitMessage(LIN_Peripheral_t peripheral, Lin_TxRxCtx_t *lin, LIN_diag_t *lin_diag);

void lin_reset_response_error(void);
uint8_t lin_get_response_error(void);
void lin_timer0_1p5ms_Handler(void);

#endif /* LIN_CONFIG_H_ */
