/*****************************************************************************
 * Module    : Task
 * File      : task_record.c
 * Author    : Hanny
 * Function  : 录音任务流程
 *****************************************************************************/
#include "include.h"
#include "task.h"
#include "task_record.h"

#if (TASK_MIC_EN)

//录音任务调试使能
#define DBG_TASK_RECORD(...)          //printf(__VA_ARGS__)
#define RECORD_DIR_NAME_LEN     max(MIC_DIR_NAME_LEN, LINE_DIR_NAME_LEN)

#pragma constseg="TASK_RECORD_1_CONST"
IAR_CONST char str_mic_rec_dir[] = "RECORD";
IAR_CONST char str_aux_rec_dir[] = "RECORDL";

#if (RECORD_FILE_NAME == SHORT_NAME)
IAR_CONST char str_mic_rec_file[] = "RECORD/REC0001.WAV";

#define REC_FNAME_NUM_LEN           4                               //文件编号长度，4位
#define MIC_FNAME_NUM_OFS           (sizeof(str_mic_rec_file)-8-1)  //文件编号位置，总长减去“0001.MP3”和\0
#else
#define REC_FNAME_NUM_LEN           4                               //文件编号长度，4位
#define MIC_FNAME_NUM_OFS           sizeof(str_mic_rec_dir)         //文件编号位置，在"RECORD/"之后
#define AUX_FNAME_NUM_OFS           sizeof(str_aux_rec_dir)         //文件编号位置，在"RECORDL/"之后
#define FM_FNAME_NUM_OFS            sizeof(str_fm_rec_dir)          //文件编号位置，在"RECORDL/"之后
#endif
IAR_CONST u8 long_name_file[] = {
    //短文件名前8个字符不能使用空格“space”
    0x30, '0', '0', '1', 0xBD, 0xA8, 0x7E, 0x31, '.', 'w', 'a', 'v', '\0',
    //长文件名,中文要参照Winhex查看
#if 1
  //             0          0            1          建          荣          珠          海
    0x30, 0x00, '0',  0x00, '0',  0x00, '1',  0x00, 0xfa, 0x5e, 0x63, 0x83, 0xe0, 0x73, 0x77, 0x6d,
  //有          限          公          司          -           2           0           1
    0x09, 0x67, 0x50, 0x96, 0x6c, 0x51, 0xf8, 0x53, 0x2d, 0x00, 0x32, 0x00, 0x30, 0x00, 0x31, 0x00,
  //3           年          4           月          2           日          .           W
    0x33, 0x00, 0x74, 0x5e, 0x34, 0x00, 0x08, 0x67, 0x32, 0x00, 0xe5, 0x65, 0x2e, 0x00, 0x57, 0x00,
  //A           V
    0x41, 0x00, 0x56, 0x00,
#else
//              1            0           0          建          荣          .           W
    0x30, 0x00, '1',  0x00, '0',  0x00, '0',  0x00, 0xfa, 0x5e, 0x63, 0x83, 0x2e, 0x00, 0x57, 0x00,
//  A           V
    0x41, 0x00, 0x56, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
#endif
};
#endif
#pragma constseg=default
#pragma constseg="TASK_RECORD_CONST"
IAR_CONST u8 tbl_wav_head[52] = {
    0x52, 0x49, 0x46, 0x46, 0x00, 0x00, 0x00, 0x00, 0x57, 0x41, 0x56, 0x45, 0x66, 0x6D, 0x74, 0x20,
    0x14, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x04, 0x00, 0x02, 0x00, 0x00, 0x00, 0x66, 0x61, 0x63, 0x74, 0xC8, 0x01, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00,
};
#pragma constseg=default
IAR_XDATA_A type_task_rec t_rec @ "RECORD_XDATA";

#include SET_USER_PATH(CFG_UI_RECORD_DIR, /ui/ui_record.c)

__near_func void task_record_process(void)
{
    if (t_rec.block_cnt >= t_rec.block_lmt) {
        printf("err\n");
        return;
    }
    if (!t_rec.pos) {
        adpcm_input = (u16)adc_buf;
    }
    adpcm_encode(t_rec.slice+t_rec.pos, t_rec.pos);
    if (t_rec.pos) {
        t_rec.block_cnt++;
        if (adpcm_output == REC_BUF_END) {
            adpcm_output = REC_BUF_BEG;
        }
    }
    t_rec.pos ^= 1;
}

#pragma location="TASK_RECORD_SEG"
bool wav_write_header(void *buf)
{
    t_rec.file_size = fat_file.fsize;

    my_memset((void *)buf, 0, 512);
    smemcpy_c((void *)buf, (void __code *)tbl_wav_head, 52);

    u32 *ptr0 = (u32 *)buf;
    ptr0[1] = t_rec.file_size - 8;
    ptr0[6] = t_rec.spr;
    ptr0[7] = (t_rec.spr * BLOCK_SIZE) / t_rec.spl;
    ptr0[12] = ((t_rec.file_size - 512) * t_rec.spl) / BLOCK_SIZE;
    ptr0[126] = 0x61746164;
    ptr0[127] = t_rec.file_size - 512;

    u16 *ptr1 = (u16 *)buf;
    ptr1[11] = adpcm_channel;
    ptr1[16] = BLOCK_SIZE;
    ptr1[19] = t_rec.spl;

    //printf("ssect=%08lx\n", t_rec.file_ssect);
    if (fat_fs.disk_write(buf, t_rec.file_ssect)) {
        return false;
    }
    return true;
}

#pragma location="TASK_RECORD_SEG"
bool wav_close_file(void)
{
    if(!wav_write_header(dec_bs)) {
        return false;
    }
    if(!f_close()) {
        return false;
    }
    return true;
}

#pragma location="TASK_RECORD_SEG"
void wav_record_abort(void)
{
        mic_adc_stop();
        t_rec.block_cnt = 0;
        DBG_TASK_RECORD("adc stop\n");
}

#pragma location="TASK_RECORD_SEG"
void wav_record_stop(void)
{
    wav_record_abort();
    if (!wav_close_file()) {
        DBG_TASK_RECORD("close Fail!\n");
    }
}

#pragma location="TASK_RECORD_SEG"
bool wav_sync_file(void *buf)
{
    if (!move_window(0)) {
        return false;
    }

    if(!wav_write_header(buf)) {
        return false;
    }
    if(fat_fs.disk_read(buf, fat_file.dir_sect)) {
        return false;
    }
    u8 *dir;
    dir = (u8 *)buf + (fat_file.dir_ptr - fat_fs.win);
    if(fat_fs.fs_type == FS_EXFAT) {
        mkitem_exfat(dir, (char *)fat_file.fname, AM_ARC, fat_file.sclust, t_rec.file_size);
    } else {
        mkitem_fat(dir, (char *)fat_file.fname, dir[DIR_Attr]|AM_ARC, fat_file.sclust, t_rec.file_size);
    }
    if(fat_fs.disk_write(buf, fat_file.dir_sect)) {
        return false;
    }
    return true;
}

//录音控制器初始化
#pragma location="TASK_RECORD_SEG_1"
void task_record_wav_init(void)
{
    //关闭AMUX模块
    //mp3en_exit();
    if (t_rec.file_open) {
        f_close();
    }
    //选择MIC录音
    mic_init(SEL_RECMIC);
    t_rec.rec_time = 0;                                 //时间清0
    t_rec.file_open = 0;
    t_rec.dir_open = 0;
}


#pragma location="TASK_RECORD_SEG_1"
bool record_fname_inc(u8 *buf)
{
    u8 i;
    u8 *p = buf + (REC_FNAME_NUM_LEN-1);

    *p += 1;
    for(i=0; i<(REC_FNAME_NUM_LEN-1); i++) {
        if(*p > '9') {
            *p-- = '0';
            *p += 1;
        } else {
            return true;
        }
    }

    return (*p > '9')? false : true;
}


#pragma location="TASK_RECORD_SEG_1"
u8 task_record_copy_name(void)
{
#if (RECORD_FILE_NAME == SHORT_NAME)
        memcpy(filename, (char *)str_mic_rec_file, sizeof(str_mic_rec_file));
        return MIC_FNAME_NUM_OFS;
#else
        memcpy(filename, (char *)str_mic_rec_dir, sizeof(str_mic_rec_dir));
        t_rec.sname_ptr = sizeof(str_mic_rec_dir) - 1;
        t_rec.lname_ptr = t_rec.sname_ptr + 14;
        //短文件名使用的是gbk编码，长文件名使用的是unicode编码
        filename[t_rec.sname_ptr]='/';
        smemcpy_c((void *)(filename+t_rec.sname_ptr+1), (void __code *)long_name_file, sizeof(long_name_file));
#endif
}

//根据文件编号新建文件
#pragma location="TASK_RECORD_SEG_1"
bool task_record_create(void)
{
    u8 file_creat = 0;
    t_rec.file_open = 1;
    u8 rec_fname_ofs = task_record_copy_name();
    while (1) {
#if (RECORD_FILE_NAME == LONG_NAME)
        file_creat = f_create_long_name(filename,t_rec.lname_ptr);
#else
        file_creat = f_create(filename);
#endif
        if (file_creat == 1) {
            //printf(str_rec_create_ok, filename);
            break;
        } else if(file_creat == 0) {
            if(!record_fname_inc((u8 *)&filename[rec_fname_ofs])) {
                //printf(str_rec_create_fail, filename);
                return false;
            }
#if (RECORD_FILE_NAME == LONG_NAME)
            filename[t_rec.lname_ptr+0] = filename[t_rec.sname_ptr+1];
            filename[t_rec.lname_ptr+2] = filename[t_rec.sname_ptr+2];
            filename[t_rec.lname_ptr+4] = filename[t_rec.sname_ptr+3];
            filename[t_rec.lname_ptr+6] = filename[t_rec.sname_ptr+4];
#endif
        } else if (file_creat == 2) {
            //printf(str_rec_disk_full);
            return false;
        }
    }
    return true;
}



#pragma location="TASK_RECORD_SEG_1"
bool task_record_dirmake(void)
{
    char dir_name[sizeof(str_mic_rec_dir)];
    memcpy(dir_name, (char *)str_mic_rec_dir, sizeof(str_mic_rec_dir));
    return f_mkdir(dir_name);
}

#pragma location="TASK_RECORD_SEG_1"
bool wav_record_init(void)
{
    //预留512byte写文件头
    my_memset((void *)dec_bs, 0, 512);
    if(f_write((void *)dec_bs)) {
        msgbox(STR_WRITE_DISABLE, NULL, MSGBOX_TIME);
        DBG_TASK_RECORD("write fail\n");
        return false;
    }
    t_rec.file_ssect = clust2sect(fat_file.org_clust);
    //printf("file_ssect1=%08lx, sclust=%08lx\n", t_rec.file_ssect, fat_file.org_clust);

    t_rec.spr = 16000L;
    t_rec.chs = 1;
    t_rec.spl = RECORD_AGC_SAMPLES;
    t_rec.pos = 0;
    t_rec.block_cnt = 0;
    t_rec.block_adr = REC_BUF_BEG;
    t_rec.block_lmt = (REC_BUF_END - REC_BUF_BEG)/BLOCK_SIZE;
    t_rec.slice = t_rec.spl >> 4;
    t_rec.sample_cnt = 0;

    adpcm_channel = t_rec.chs;
    adpcm_index[0] = 0;
    adpcm_index[1] = 0;
    adpcm_output = REC_BUF_BEG;

    return true;
}

//开始录音
#pragma location="TASK_RECORD_SEG_1"
u8 task_record_start(void)
{
    if(!record_mount_device()) {
        return 1;       //err
    }
    if(!t_rec.dir_open) {
        t_rec.dir_open = task_record_dirmake();
        if(!t_rec.dir_open) {
            return 1;   //make dir fail
        }
    }
    if (!fs_writable()) {
        return 1;
    }
    if (!t_rec.file_open) {
        if(!task_record_create()) {
            return 2;   //disk full
        }
        if (!wav_record_init()) {
            return 1;
        }
        t_rec.file_open = 1;
    }
    return 0;
}


//暂停录音
#pragma location="TASK_RECORD_SEG_1"
void task_record_pause(void)
{
    wav_record_abort();
    wav_sync_file(dec_bs);
}

//停止录音
#pragma location="TASK_RECORD_SEG_1"
void task_record_stop(void)
{
    wav_record_stop();
    t_rec.file_open = 0;
    t_rec.dir_open = 0;
    t_rec.rec_sta = REC_STA_STOP;
}


//录音中事务处理
#pragma location="TASK_RECORD_SEG"
void task_recording_event(void)
{
    WATCHDOG_CLR();
    comm_event();
    if (device_change()) {
        t_rec.rec_sta = REC_STA_STOPPING;           //设备变动，停止录音
        return;
    }
    if (t_rec.block_cnt < 4) {
        return;
    }
    u8 res = f_write((void *)t_rec.block_adr);
    if (res) {
        if (res == 6) {
            //磁盘已满，停止录音
            DBG_TASK_RECORD("disk full!\n");
           /* wav_record_stop();
            msgbox(STR_DISK_FULL, NULL, MSGBOX_TIME);
            t_rec.file_open = 0;  */
            t_rec.rec_sta = REC_STA_STOPPING;           //磁盘已满，停止录音
        } else {
            //录音出错，停止录音
            DBG_TASK_RECORD("write err!\n");
           // wav_record_abort();
            task_ctl.dev_change = 1;
            t_rec.rec_sta = REC_STA_STOPPING;           //录音出错，停止录音
        }
        return;
    }
    t_rec.block_cnt -= 4;
    t_rec.block_adr += 0x200;
    if (t_rec.block_adr == REC_BUF_END) {
        t_rec.block_adr = REC_BUF_BEG;
    }
    t_rec.sample_cnt += 4*t_rec.spl;


#if MUSIC_MODE_AUTO
    if (device_need_activate(DEVICE_SDMMC) || device_need_activate(DEVICE_UDISK)) {
        if(task_ctl.work_sta == TASK_MUSIC) {           //插入U盘或SD卡时不切模式
            task_ctl.work_sta = task_ctl.last_work;
        }
    }
#endif
    if (device_change()) {
        if(t_rec.rec_sta == REC_STA_RECORD) {
            t_rec.rec_sta = REC_STA_STOPPING;           //设备变动，停止录音
        }
    }
}


//录音任务初始化
#pragma location="TASK_RECORD_SEG_1"
void task_record_enter(void)
{
    u8 res;
    set_sys_clk(SYS_24M);
    //播放状态
    memset(&t_rec,0,sizeof(t_rec));
    t_rec.rec_sta = REC_STA_STOP;
    ocx_clear();
    led_busy();
    draw_wait();
    res = task_record_start();
    flush_msg();                        //清空消息池
    if(res == 2) {
        show_full();
        //printf(str_rec_err);
        WATCHDOG_CLR();
        delay_5ms(200);
        return;
    } else if(res == 1) {
        show_err();
        //printf(str_rec_err);
        WATCHDOG_CLR();
        delay_5ms(200);
        return;
    } else {
        //printf(str_rec_start);
        mic_adc_start();
        t_rec.rec_sta = REC_STA_RECORD;
        ocx_show_cnt = 0;//控制录音闪烁时间
    }
}

//正在录音中任务消息处理
#pragma location="TASK_RECORD_SEG"
void task_recording_deal_msg(u8 msg)
{
    switch(msg) {
        //暂停录音
    case KU_PLAY:
       // task_record_pause();
        task_record_stop();
        break;
        //停止录音
    case KU_MODE:
        task_record_stop();
        task_ctl.work_sta = TASK_EXIT;              //返回主菜单
        break;
    case QSYSTEM_1S:
        t_rec.rec_time++;                           //录音计时
        if (t_rec.sync_cnt++ < REC_SYNC_CNT) {
            break;
        }
        t_rec.sync_cnt = 0;                     //同步
        if (!wav_sync_file(dec_bs)) {
            DBG_TASK_RECORD("file sync Fail!\n");
            wav_record_abort();
        }
        break;
        //调用公共消息函数
    default:
        break;
    }
}
//退出录音任务
#pragma location="TASK_RECORD_SEG_1"
void task_record_exit(void)
{
    if (t_rec.rec_sta != REC_STA_STOP) {
        task_record_stop();
    }
    led_idle();
    ocx_clear();
}

#pragma constseg="TASK_RECORD_CONST"
IAR_CONST char str_show_taskrecord[] = "task_record\n";
#pragma constseg=default

//录音任务
#pragma location="TASK_RECORD_SEG"
void task_record(void)
{
    task_record_enter();
    while (t_rec.rec_sta == REC_STA_RECORD) {
        u8 msg = get_msg();
        task_recording_event();
        task_recording_deal_msg(msg);
        task_recording_display();
        }
    task_record_exit();
}

