/******************************************************************************
**
** RASP-MXからデータをUART経由で送信するAPI
**
** 2017.08.25 K.Takagi 分離音出力のバッファ追加
** 2017.08.22 K.Takagi UART出力方法の修正
**                     関連パラメータの追加
** 2017.05.31 K.Takagi RAW保存のサイズ指定を追加
** 2017.05.25 K.Takagi UART速度を拡張
**                     分離音転送を組み込み＆確認
** 2017.05.24 K.Takagi バッファの数を拡張
** 2017.05.23 K.Takagi カウント、時刻、音源情報、MUSICの転送を確認
** 2017.05.22 K.Takagi 設定をパラメータファイル化
**                     RAWデータ保存を組み込み＆確認
** 2017.05.17 K.Takagi 各種実装
**                     PC上での動作を確認
** 2017.05.15 K.Takagi 各種関数を定義
**
**
*/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <pthread.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>

#define __USE_GNU
#include <fcntl.h>

#include "MxUartSend.h"

#undef  DBG_MX_UART_PRINT
#define DBG_MX_UART_PRINT(...)
//#define DBG_MX_UART_PRINT(...) printf(__VA_ARGS__)

/* 内部バッファは2のべき数にする */
#define MX_UART_DATA_MAX_NUM    256
#define MX_UART_DATA_NUM_MASK   (MX_UART_DATA_MAX_NUM-1)

// 512kサンプルで約32秒
#define MX_UART_SEP_BUFF_LENGTH (512*1024)

static char mx_uart_dev_name[128];
static int fd_mx_uart;
static struct termios org_term;

static mx_uart_t mx_uart_data[MX_UART_DATA_MAX_NUM];

typedef struct _prm_mx_uart_t_
{
    int raw_save_enable;
    int time_enable;
    int music_enable;
    int src_enable;
    int wav_enable;
    int uart_enable;
} prm_mx_uart_t;

static prm_mx_uart_t prm_uart;
static speed_t uart_speed;
static int raw_save_length;
static int src_out_cnt;
static int src_out_interval;
static int wav_out_length;
static int wav_out_count;

typedef struct _uart_sep_buff_t
{
    int wp;
    int rp;
    short wav[MX_UART_SEP_BUFF_LENGTH];
} uart_sep_buff_t;

static uart_sep_buff_t uart_sep_data; 


/******************************************************************************
**
** 設定ファイルから動作パラメータ取得
**
*/

static int MxUartConfig(char *cfg_file)
{
    FILE *fp;
    char *ptr;
    char prm_str[256];
    int val;
    int ret;
    
    memset(&prm_uart, 0, sizeof(prm_uart));
    uart_speed = B115200;
    raw_save_length = 30;
    
    src_out_cnt      = 0;
    src_out_interval = 1;
    wav_out_length   = 512;
    uart_sep_data.wp = 0;
    uart_sep_data.rp = 0;

    fp = fopen(cfg_file, "rt");
    if(fp == NULL)
    {
        printf("MX Uart config file error.\n");
        return -1;
    }
    
    strcpy(mx_uart_dev_name, "/dev/ttyUSB0");
    
    while(1)
    {
        ptr = fgets(prm_str, sizeof(prm_str), fp);
        if(ptr == NULL)
        {
            break;
        }
        
        /* #以降はコメントとして扱う */
        ptr = strchr(prm_str, '#');
        if(ptr != NULL)
        {
            *ptr = '\0';
        }
        
        if((ptr = strstr(prm_str, "--param-raw-save-enable")) != NULL) 
        {
            ret = sscanf(ptr, "%*s %d", &val);
            if(ret == 1)
            {
                prm_uart.raw_save_enable = (val > 0);
            }
        }
        else if((ptr = strstr(prm_str, "--param-raw-save-length")) != NULL) 
        {
            ret = sscanf(ptr, "%*s %d", &val);
            if(ret == 1)
            {
                raw_save_length = val;
            }
        }
        else if((ptr = strstr(prm_str, "--param-time-enable")) != NULL) 
        {
            ret = sscanf(ptr, "%*s %d", &val);
            if(ret == 1)
            {
                prm_uart.time_enable = (val > 0);
            }
        }
        else if((ptr = strstr(prm_str, "--param-music-enable")) != NULL) 
        {
            ret = sscanf(ptr, "%*s %d", &val);
            if(ret == 1)
            {
                prm_uart.music_enable = (val > 0);
            }
        }
        else if((ptr = strstr(prm_str, "--param-src-enable")) != NULL) 
        {
            ret = sscanf(ptr, "%*s %d", &val);
            if(ret == 1)
            {
                prm_uart.src_enable = (val > 0);
            }
        }
        else if((ptr = strstr(prm_str, "--param-src-out-interval")) != NULL) 
        {
            ret = sscanf(ptr, "%*s %d", &val);
            if(ret == 1)
            {
                src_out_interval = val;
            }
        }
        else if((ptr = strstr(prm_str, "--param-wav-enable")) != NULL) 
        {
            ret = sscanf(ptr, "%*s %d", &val);
            if(ret == 1)
            {
                prm_uart.wav_enable = (val > 0);
            }
        }
        else if((ptr = strstr(prm_str, "--param-wav-out-length")) != NULL) 
        {
            ret = sscanf(ptr, "%*s %d", &val);
            if(ret == 1)
            {
                wav_out_length = val;
            }
        }
        else if((ptr = strstr(prm_str, "--param-uart-dev")) != NULL) 
        {
            ret = sscanf(ptr, "%*s %s", mx_uart_dev_name);
            if(ret != 1)
            {
                strcpy(mx_uart_dev_name, "/dev/ttyUSB0");
            }
        }
        else if((ptr = strstr(prm_str, "--param-uart-speed")) != NULL) 
        {
            ret = sscanf(ptr, "%*s %d", &val);
            if(ret == 1)
            {
                switch(val)
                {
                    case   9600: uart_speed = B9600;   break;
                    case  19200: uart_speed = B19200;  break;
                    case  38400: uart_speed = B38400;  break;
                    case  57600: uart_speed = B57600;  break;
                    case 115200: uart_speed = B115200; break;
                    case 230400: uart_speed = B230400; break;
                    case 460800: uart_speed = B460800; break;
                    case 500000: uart_speed = B500000; break;
                    case 576000: uart_speed = B576000; break;
                    case 921600: uart_speed = B921600; break;
                    default: uart_speed = B115200; break;
                }
            }
        }
    }
    
    if(src_out_interval <= 0)
    {
        src_out_interval = 1;
    }
    
    if(raw_save_length <= 0)
    {
        raw_save_length = 30;
    }
    
    if(wav_out_length <= 0)
    {
        /* この時点ではAdvanceが不明なので最大にする */
        wav_out_length = 512;
    }
    
    prm_uart.uart_enable  = prm_uart.time_enable;
    prm_uart.uart_enable |= prm_uart.music_enable;
    prm_uart.uart_enable |= prm_uart.src_enable;
    prm_uart.uart_enable |= prm_uart.wav_enable;
    
    printf("MxUartSend\n");
    printf(" dev   %s\n", mx_uart_dev_name);
    printf(" raw   %d\n", prm_uart.raw_save_enable);
    printf("  len   %d[s]\n", raw_save_length);
    printf(" time  %d\n", prm_uart.time_enable);
    printf(" music %d\n", prm_uart.music_enable);
    printf(" src   %d\n", prm_uart.src_enable);
    printf("  int   %d\n", src_out_interval);
    printf(" wav   %d\n", prm_uart.wav_enable);
    printf("  len   %d\n", wav_out_length);
    printf(" uart  %d\n", prm_uart.uart_enable);
    printf("");
    /*
    */
    
    return 0;
}

/******************************************************************************
**
** UART APIの初期化
**
*/

int  InitMxUart(char *cfg_file)
{
    struct termios raw_term;
    
    MxUartConfig(cfg_file);
    
#ifdef DUMMY_UART_MODE
    /* ローカルテストではFIFOを利用するためUART設定不要 */
    fd_mx_uart = open(MX_UART_DUMMY_NAME, O_WRONLY);
    if(fd_mx_uart < 0)
    {
        return -1;
    }
#else
    /* UARTデバイスを開く */
    fd_mx_uart = open(mx_uart_dev_name, O_RDWR);
    if(fd_mx_uart < 0)
    {
        return -1;
    }
    tcgetattr(fd_mx_uart, &org_term);
    cfmakeraw(&raw_term);
    cfsetispeed(&raw_term, uart_speed);
    cfsetospeed(&raw_term, uart_speed);
    tcsetattr(fd_mx_uart, TCSAFLUSH, &raw_term);

    printf("%s open.\n", mx_uart_dev_name);
#endif
    
    /* UARTデータ用のバッファクリア */
    memset(mx_uart_data, 0, sizeof(mx_uart_data));
    wav_out_count = 0;
    
    return 0;
    
}

/******************************************************************************
**
** フレームデータの初期化
**
*/

void ClearMxUartData(int frame_count)
{
    int index;
    
    index = frame_count & MX_UART_DATA_NUM_MASK;
    DBG_MX_UART_PRINT("%s : index = %d (%d)\n", __func__, index, frame_count);
    
    /* データクリア */
    mx_uart_data[index].header      = 0xaa55a5a5;
    mx_uart_data[index].data_flag   = 0;
    mx_uart_data[index].frame_count = frame_count & 0x7fffffff;
    mx_uart_data[index].mx_sec      = 0;
    mx_uart_data[index].mx_usec     = 0;
    mx_uart_data[index].music_num   = 0;
    mx_uart_data[index].src_num     = 0;
    mx_uart_data[index].advance     = 0;
    mx_uart_data[index].csum        = 0x0;
    
}

/******************************************************************************
**
** フレームデータに時刻情報追加
**
*/

void SetMxUartTime(int frame_count, uint32 mx_sec, uint32 mx_usec)
{
    int index;
    
    index = frame_count & MX_UART_DATA_NUM_MASK;
    DBG_MX_UART_PRINT("%s : index = %d (%d)\n", __func__, index, frame_count);
    
    if(!prm_uart.time_enable)
    {
        return;
    }
    
    /* 時刻設定 */
    mx_uart_data[index].mx_sec  = mx_sec;
    mx_uart_data[index].mx_usec = mx_usec;
}

/******************************************************************************
**
** フレームデータにMUSICスペクトル追加
**
*/

void SetMxUartMusicData(int frame_count, int music_num, float *music_power)
{
    int index;
    int i;
    int val;
    
    index = frame_count & MX_UART_DATA_NUM_MASK;
    DBG_MX_UART_PRINT("%s : index = %d (%d)\n", __func__, index, frame_count);
    
    if(!prm_uart.music_enable)
    {
        return;
    }
    
    mx_uart_data[index].music_num = music_num;
    
    /*
    ** 転送データ量削減のため float --> short に変換
    ** MUSICパワーは30程度
    ** 単純に型変換すると小数点以下がなくり違いが分からなくなるので512倍（固定小数点化）
    ** ちなみに 64 x 512 = 0x8000
    **
    */
    for(i=0; i<music_num; i++)
    {
        val = music_power[i] * MX_UART_MUSIC_GAIN;
        if(val > 0x00007fff)
        {
            val = 0x7fff;
        }
        mx_uart_data[index].music[i] = (short)val;
    }
}

/******************************************************************************
**
** フレームデータに音源情報追加
**
*/

void SetMxUartSrcData(int frame_count, int src_num, int *src_id, int *src_dir, float *src_power)
{
    int index;
    int i;
    int val;
    
    index = frame_count & MX_UART_DATA_NUM_MASK;
    DBG_MX_UART_PRINT("%s : index = %d (%d)\n", __func__, index, frame_count);
    
    if(!prm_uart.src_enable)
    {
        return;
    }
    
    mx_uart_data[index].src_num = src_num;
    
    for(i=0; i<src_num; i++)
    {
        val = src_power[i] * MX_UART_MUSIC_GAIN;
        if(val > 0x00007fff)
        {
            val = 0x7fff;
        }
        
        mx_uart_data[index].src_info[i].src_id = src_id[i];
        mx_uart_data[index].src_info[i].dir_id = src_dir[i];
        mx_uart_data[index].src_info[i].power  = (short)val;
    }
    
}

/******************************************************************************
**
** フレームデータに分離音情報追加
**
*/

#undef UART_DEBUG_RAW_SAVE
#ifdef UART_DEBUG_RAW_SAVE
static FILE *fp_uart_sep;
#endif

void SetMxUartSepWave(int frame_count, int advance, float *wav)
{
    int index;
    int i;
    int val;
    
    index = frame_count & MX_UART_DATA_NUM_MASK;
    DBG_MX_UART_PRINT("%s : index = %d (%d)\n", __func__, index, frame_count);
    
    if(!prm_uart.wav_enable)
    {
        return;
    }
    
    mx_uart_data[index].advance = advance;
    
    for(i=0; i<advance; i++)
    {
        /* 入力24bitデータ、出力16bit */
        val = (int)wav[i];
        mx_uart_data[index].wav[i] = (short)(val >> 8);
    }
    
#ifdef UART_DEBUG_RAW_SAVE
    if(fp_uart_sep == NULL)
    {
        fp_uart_sep = fopen("uart_sep.raw", "wb");
    }
    fwrite(mx_uart_data[index].wav, sizeof(short), advance, fp_uart_sep);
#endif
    
}

/******************************************************************************
**
** 分離音データの転送が有効であるかを取得
**
*/

int GetMxUartSepWaveEnable()
{
    return prm_uart.wav_enable;
}

/******************************************************************************
**
** 分離音データ用バッファのクリア
**
*/

void ClearMxUartSepWaveBuff()
{
    /* 新しい分離音が現れたときに呼び出される */
    uart_sep_data.wp = 0;
    uart_sep_data.rp = 0;
    wav_out_count++;
}

/******************************************************************************
**
** 分離音データ用バッファ制御
**
*/

static void WriteLocalBufferSepWave(int req_num, short *data)
{
    int free_num;
    int copy_num;
    int offset;
    
    // wp,rpが一致するのはempty時のみ
    if(uart_sep_data.wp == uart_sep_data.rp)
    {
        // emptyなので単純コピー
        memcpy(&uart_sep_data.wav[0], data, req_num * sizeof(short));
        uart_sep_data.wp = req_num;
        uart_sep_data.rp = 0;
        return;
    }
    
    //
    // 処理を簡略化するため
    // 書き込みをした結果 wp = rp とならないようにする
    //
    if(uart_sep_data.rp > uart_sep_data.wp)
    {
        free_num = uart_sep_data.rp - uart_sep_data.wp;
        if(free_num > req_num)
        {
            // 空きがあるので単純コピー
            memcpy(&uart_sep_data.wav[uart_sep_data.wp], data, req_num * sizeof(short));
            uart_sep_data.wp += req_num;
            if(uart_sep_data.wp >= MX_UART_SEP_BUFF_LENGTH)
            {
                uart_sep_data.wp = 0;
            }
        }
        return;
    }
    
    //if(uart_sep_data.rp < uart_sep_data.wp)
    {
        free_num = MX_UART_SEP_BUFF_LENGTH - (uart_sep_data.wp - uart_sep_data.rp);
        if(free_num > req_num)
        {
            free_num = MX_UART_SEP_BUFF_LENGTH - uart_sep_data.wp;
            if(free_num >= req_num)
            {
                // バッファの終端までに空きがある場合
                
                // 単純コピー
                memcpy(&uart_sep_data.wav[uart_sep_data.wp], data, req_num * sizeof(short));
                uart_sep_data.wp += req_num;
                if(uart_sep_data.wp >= MX_UART_SEP_BUFF_LENGTH)
                {
                    uart_sep_data.wp = 0;
                }
            }
            else
            {
                // バッファが折り返している場合
                
                // バッファ終端までコピー
                copy_num = free_num;
                memcpy(&uart_sep_data.wav[uart_sep_data.wp], data, copy_num * sizeof(short));
                offset = copy_num;
                
                // 残りをバッファ先頭にコピー
                copy_num = req_num - offset;
                memcpy(&uart_sep_data.wav[0], &data[offset], copy_num * sizeof(short));
                uart_sep_data.wp = copy_num;
            }
        }
    }
    
    return;
}


static int ReadLocalBufferSepWave(int req_num, short *data)
{
    int buff_num;
    int offset;
    int copy_num;
    
    //
    // 今回は Wriet --> Read をペアで使うため常にデータの取り出しは可能
    // バッファへの書き込みサイズ＞読み出しサイズ なので
    // rp が wp に追いつくのはバッファが空になるタイミングのみ（バッファへの書き込み側でもケア）
    //
    if(uart_sep_data.rp == uart_sep_data.wp)
    {
        return 0; // バッファが空の状態
    }
    
    if(uart_sep_data.rp < uart_sep_data.wp)
    {
        // バッファにあるデータ量を確認
        buff_num = uart_sep_data.wp - uart_sep_data.rp;
        if(buff_num >= req_num)
        {
            copy_num = req_num;
        }
        else
        {
            // バッファのデータが不足しているので足りない分をゼロ埋め
            copy_num = buff_num;
            memset(data, 0, req_num * sizeof(short));
        }
        
        // 単純コピー
        memcpy(data, &uart_sep_data.wav[uart_sep_data.rp], copy_num * sizeof(short));
        uart_sep_data.rp += copy_num;
        if(uart_sep_data.rp >= MX_UART_SEP_BUFF_LENGTH)
        {
            uart_sep_data.rp = 0;
        }
            
        return req_num;
    }

    //if(uart_sep_data.rp > uart_sep_data.wp)
    {
        // バッファにあるデータ量を確認
        buff_num = MX_UART_SEP_BUFF_LENGTH - (uart_sep_data.rp - uart_sep_data.wp);
        if(buff_num >= req_num)
        {
            copy_num = req_num;
        }
        else
        {
            // バッファのデータが不足しているので足りない分をゼロ埋め
            copy_num = buff_num;
            memset(data, 0, req_num * sizeof(short));
        }
        
        buff_num = MX_UART_SEP_BUFF_LENGTH - uart_sep_data.rp;
        if(buff_num >= copy_num)
        {
            // バッファの終端までにデータがある場合
            
            // 単純コピー
            memcpy(data, &uart_sep_data.wav[uart_sep_data.rp], copy_num * sizeof(short));
            uart_sep_data.rp += copy_num;
            if(uart_sep_data.rp >= MX_UART_SEP_BUFF_LENGTH)
            {
                uart_sep_data.rp = 0;
            }
        }
        else
        {
            // バッファが折り返している場合
            
            // バッファ終端までコピー
            memcpy(data, &uart_sep_data.wav[uart_sep_data.rp], buff_num * sizeof(short));
            offset = buff_num;
            
            // 残りをバッファ先頭からコピー
            copy_num = req_num - buff_num;
            memcpy(&data[offset], &uart_sep_data.wav[0], copy_num * sizeof(short));
            uart_sep_data.rp = copy_num;
        }
    }
    
    return req_num;
}


static int SetupUartSepWave(int input_num, short *data)
{
    int ret_num;
    
    ret_num = 0;
    if(input_num > 0)
    {
        /*
        ** 要求されているUART出力サイズが1フレームあたりの分離音サイズより大きい場合
        ** UART出力サイズ＝1フレームサイズとし、内部バッファへのコピー不要
        */
        if(input_num <= wav_out_length)
        {
            return input_num;
        }
        
        /* 内部バッファに一旦保存 */
        WriteLocalBufferSepWave(input_num, data);
    }
    
    /* 内部バッファから必要分を取得 */
    ret_num = ReadLocalBufferSepWave(wav_out_length, data);
    
    return ret_num;
}

/******************************************************************************
**
** フレームデータをUARTに送信
**
*/

static uint8 csum_buff[sizeof(mx_uart_t)];

void SendMxUartData(int frame_count)
{
    int i;
    int total_wsize;
    int wsize;
    int req_size;
    
    int time_en;
    int src_num;
    int music_num;
    int advance;
    
    int index;
    
    uint8 csum;
    
    index = frame_count & MX_UART_DATA_NUM_MASK;
    DBG_MX_UART_PRINT("%s : index = %d (%d)\n", __func__, index, frame_count);
    
    if((fd_mx_uart <= 0) || (prm_uart.uart_enable == 0))
    {
        return;
    }
    
    /* 分離音用の内部バッファ処理 */
    advance = SetupUartSepWave(mx_uart_data[index].advance, mx_uart_data[index].wav);
    
    /* データフラグ設定 */
    time_en = 0;
    if((mx_uart_data[index].mx_sec != 0) || (mx_uart_data[index].mx_usec != 0))
    {
        time_en = 1;
    }
    //advance = mx_uart_data[index].advance;
    
    src_num = 0;
    if((src_out_interval == 1) || ((src_out_cnt % src_out_interval) == 0))
    {
        src_num = mx_uart_data[index].src_num;
        src_out_cnt = 0;
    }
    src_out_cnt++;
    
    music_num = mx_uart_data[index].music_num;
    mx_uart_data[index].data_flag = CONV_to_FLAG(time_en, advance, src_num, music_num);
    
    total_wsize = 0;
    
    /* ヘッダをコピー */
    req_size = sizeof(int);
    memcpy(&csum_buff[total_wsize], &mx_uart_data[index].header, req_size);
    total_wsize += req_size;
    
    /* フラグをコピー */
    req_size = sizeof(int);
    memcpy(&csum_buff[total_wsize], &mx_uart_data[index].data_flag, req_size);
    total_wsize += req_size;
    
    /* フレームカウントコピー */
    req_size = sizeof(int);
    memcpy(&csum_buff[total_wsize], &mx_uart_data[index].frame_count, req_size);
    total_wsize += req_size;
    
    /* 時刻情報コピー */
    if(time_en)
    {
        req_size = sizeof(uint32);
        memcpy(&csum_buff[total_wsize], &mx_uart_data[index].mx_sec, req_size);
        total_wsize += req_size;
        memcpy(&csum_buff[total_wsize], &mx_uart_data[index].mx_usec, req_size);
        total_wsize += req_size;
    }
    
    /* MUSICスペクトルコピー */
    if(music_num > 0)
    {
        req_size = sizeof(short) * music_num;
        memcpy(&csum_buff[total_wsize], &mx_uart_data[index].music, req_size);
        total_wsize += req_size;
    }
    
    /* 音源情報コピー */
    if(src_num > 0)
    {
        req_size = sizeof(mx_uart_src_t) * src_num;
        memcpy(&csum_buff[total_wsize], &mx_uart_data[index].src_info, req_size);
        total_wsize += req_size;
    }
    
    /* 分離音コピー */
    if(advance > 0)
    {
        req_size = sizeof(short) * advance;
        //memcpy(&csum_buff[total_wsize], &mx_uart_data[index].wav, req_size);
        memcpy(&csum_buff[total_wsize], &mx_uart_data[index].wav[0], req_size);
        total_wsize += req_size;
    }
    
    /* チェックサム生成 */
    csum = 0;
    for(i=0; i<total_wsize; i++)
    {
        csum += csum_buff[i];
#ifdef UART_DATA_DUMP
        printf("  %02x\n", csum_buff[i]);
#endif
    }
    mx_uart_data[index].csum = csum;
    csum_buff[total_wsize] = csum;
    total_wsize += 1;
    
    
    /* 擬似欠落テスト 確認済み */
    /*
    if(index == 3)
        total_wsize -= 3;
    */
    
    /* 過剰データ転送  */
    /*
    if(index == 3)
        total_wsize += 10;
    */
    
    /* デバックログ */
    /*
    {
        //if(src_num > 0)
        {
            printf("count = %d\n", mx_uart_data[index].frame_count);
            printf("time  = %d, %d\n", mx_uart_data[index].mx_sec, mx_uart_data[index].mx_usec);
            for(i=0; i<src_num; i++)
            {
                printf("(%d, %d, %f) ", 
                    mx_uart_data[index].src_info[i].src_id, 
                    mx_uart_data[index].src_info[i].dir_id, 
                    (float)(mx_uart_data[index].src_info[i].power/512.0f));
            }
            printf("\n");
        }
    }
    */
    
    /* UART送信 */
    {
        req_size = total_wsize;
        total_wsize = 0;
        while(req_size > 0)
        {
            wsize = write(fd_mx_uart, &csum_buff[total_wsize], req_size);
            if(wsize < 0)
            {
                break;
            }
            total_wsize += wsize;
            req_size    -= wsize;
        }
    }
    
    return;
}

/******************************************************************************
**
** UART APIの終了処理
**
*/

void UninitMxUart()
{
    if(fd_mx_uart > 0)
    {
#ifdef DUMMY_UART_MODE
        /* ローカルテストではFIFOを利用するためUART設定不要 */
#else
        tcsetattr(fd_mx_uart, TCSAFLUSH, &org_term);
#endif
        close(fd_mx_uart);
    }
    
    fd_mx_uart = 0;
}


/******************************************************************************
**
** 入力音をRAW保存するためのファイル名チェック
**
*/

static char uart_raw_file_path[64];

int UartRawFileCheck()
{
    FILE *fp;
    int val;
    int rec_no;
    int ret;
    char *ptr;
    char str[128];
    
    /*
    ** /tmp/raw にSDカードがマウントされているものとする
    **
    */
    uart_raw_file_path[0] = '\0';
    
    /* ディレクトリリスト作成 */
    system("ls -1 /tmp/raw/ | grep hark > /tmp/raw-list.txt");
    
    fp = fopen("/tmp/raw-list.txt", "rt");
    if(fp == NULL)
    {
        printf("file open error.\n");
        return -1;
    }
    
    rec_no = 0;
    while(1)
    {
        ptr = fgets(str, sizeof(str), fp);
        if(ptr == NULL)
        {
            break;
        }
        
        ptr = strstr(str, "hark");
        if(ptr != NULL)
        {
            ret = sscanf(ptr, "hark%d", &val);
            if(ret == 1)
            {
                if(rec_no < val)
                {
                    rec_no = val;
                }
            }
        }
        
    }
    
    sprintf(uart_raw_file_path, "/tmp/raw/hark%03d", (rec_no+1));
    
    return 0;
}

/******************************************************************************
**
** 入力音をRAW保存するための開始処理
**
*/

static FILE *fp_uart_raw;
static int uart_raw_file_count;
static int uart_raw_file_sample;

int UartRawSaveStart()
{
    int stat;
    char cmd[128];
    char file_name[128];
    
    fp_uart_raw = NULL;
    uart_raw_file_count = 0;
    uart_raw_file_sample = 0;
    
    if(!prm_uart.raw_save_enable)
    {
        /* ファイル保存なし */
        return 0;
    }
    
    stat = UartRawFileCheck();
    if(stat != 0)
    {
        return -1;
    }
    
    sprintf(cmd, "mkdir -p %s", uart_raw_file_path);
    system(cmd);
    
    sprintf(file_name, "%s/input%03d.raw", uart_raw_file_path, uart_raw_file_count);
    fp_uart_raw = fopen(file_name, "wb");
    
    return 0;
}

/******************************************************************************
**
** 入力音をRAW保存
**
*/

static unsigned char raw_data[1024 * 16 * 4];

int UartRawSave(float *data, int ch_num, int save_samples, int wav_length)
{
    char file_name[128];
    int val;
    unsigned char *ptr;
    
    int i, j, k;
    
    if((prm_uart.raw_save_enable == 0) || (fp_uart_raw == NULL))
    {
        return 0;
    }
    
    /* ファイル保存 */
    ptr = (unsigned char *)&val;
    for(i=0; i<save_samples; i++)
    {
        for(j=0, k=0; j<ch_num; j++, k+=3)
        {
            val = (int)(data[((j+1) * wav_length) - save_samples + i]);
            raw_data[i * ch_num * 3 + k    ] = ptr[0];
            raw_data[i * ch_num * 3 + k + 1] = ptr[1];
            raw_data[i * ch_num * 3 + k + 2] = ptr[2];
        }
    }
    fwrite(raw_data, sizeof(char), (save_samples * ch_num * 3), fp_uart_raw);
    uart_raw_file_sample += save_samples;
    
    /* あるサンプル数（秒数）を保存したらファイルを分割 */
    if(uart_raw_file_sample > 16 * 1000 * raw_save_length)
    {
        uart_raw_file_sample = 0;
        uart_raw_file_count++;
        
        fclose(fp_uart_raw);
        
        sprintf(file_name, "%s/input%03d.raw", uart_raw_file_path, uart_raw_file_count);
        fp_uart_raw = fopen(file_name, "wb");
    }

    return 0;
}


/******************************************************************************
**
** 入力音をRAW保存したあとの終了処理
**
*/

int UartRawSaveStop()
{
    if(fp_uart_raw != NULL)
    {
        fclose(fp_uart_raw);
    }

    return 0;
}


/* EOF */

