语音芯片间隔播报

unsigned char bsp_IsAudioMsgEmpty(void)
{
    if (g_stAudioMsg.Read == g_stAudioMsg.Write)
    {
        return 0; // 队列为空
    }
    else
    {
        return 1; // 队列非空
    }
}

void n_single_play(unsigned char index)
{
    // DISABLE_INT();      /* ???��? */
    HOST_BUS_Init();

    // N_STOP();
    // N_RESET();

    HOST_Delay500uS();

    N_MULTI_PLAY(1, &index);
    // ENABLE_INT();       /* ???��? */
    I2C_LIKE_STOP();

    // HOST_CMD_INTERVAL();
    // TwoWire_WaitPlayEND();
    stSysParam.stCookingParam.voiceState = TRUE;
}

// 不调时间间隔的词
unsigned char nor_delay_index_arr[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
                                       22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
                                        155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168,
                                       169, 170, 173, 174, 175, 176, 177,  179, 180, 181, 182,
                                       188, 189, 190, 191, 197, 198, 199, 200, 201, 214, 215, 216};

// 可调播报时间间隔的词
unsigned char delay_index_arr[] = {152,178,41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59,
                                   60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78,
                                   79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97,
                                   98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113,
                                   114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129,
                                   130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145,
                                   146, 147, 148, 149, 150, 151, 153, 154, 171, 172, 183, 184, 185, 186, 187, 192,
                                   193, 194, 195, 196, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 217, 218};

// int size = sizeof(arr) / sizeof(arr[0]);
//  int result = searchNumber(arr, size, numberToSearch);
unsigned char searchNumber(unsigned char arr[], unsigned char size, unsigned char target)
{
    for (unsigned char i = 0; i < size; i++)
    {
        if (arr[i] == target)
        {
            return 1; // 找到目标数字,返回1
        }
    }
    return 0; // 没有找到目标数字,返回0
}

// 更新音频播放状态的函数
// 更新音频播放状态的函数
void update_audio_play_state(audio_params_t *audio_params)
{
    unsigned char size;
    unsigned char result;

    // 检查当前状态并执行相应的逻辑
    if (audio_params->audio_state == AUDIO_STATE_IDLE)
    {
        if (bsp_IsAudioMsgEmpty())
        {
            fsm_audio();
            memset((uint8_t *)&audio_params->index_buffer, 0, 8);
            memcpy((uint8_t *)&audio_params->index_buffer, &g_stParam.playBuffer, 8);

            // 初始化播放索引为0
            audio_params->current_index = 0;
            if (audio_params->index_buffer[audio_params->current_index])
            {
                // 开始播放第一个音频片段
                n_single_play(audio_params->index_buffer[audio_params->current_index]);
                // 改变状态为延时中
                audio_params->audio_state = AUDIO_STATE_IS_PLAYING;
                audio_params->ask_status_cnt = 0;
                audio_params->hlodTimer = 1; // 默认是100ms间隔
            }
        }
    }
    
    if (audio_params->audio_state == AUDIO_STATE_PLAYING)
    {
        // 增加当前播放索引
        audio_params->current_index++;
        if (audio_params->current_index < 8 && audio_params->index_buffer[audio_params->current_index])
        {
            // 继续播放下一个音频片段
            n_single_play(audio_params->index_buffer[audio_params->current_index]);
            // 改变状态为延时中
            audio_params->audio_state = AUDIO_STATE_IS_PLAYING;
            audio_params->ask_status_cnt = 0;

            // 间隔
            size = sizeof(nor_delay_index_arr) / sizeof(nor_delay_index_arr[0]);
            result = searchNumber(nor_delay_index_arr, size, audio_params->index_buffer[audio_params->current_index]);
            if (result)
            {
                audio_params->hlodTimer = 1;
            }
            else
            {
                size = sizeof(delay_index_arr) / sizeof(delay_index_arr[0]);
                result = searchNumber(delay_index_arr, size, audio_params->index_buffer[audio_params->current_index]);
                if (result)
                {
                    audio_params->hlodTimer = g_saveParam.voice_word_pause;
                }
            }
        }
        else
        {
            // 所有音频片段播放完毕,回到空闲状态
            audio_params->audio_state = AUDIO_STATE_IDLE;
            // 标记烹饪语音状态为已完成
            stSysParam.stCookingParam.voiceState = true;
        }
    }

    if (audio_params->audio_state == AUDIO_STATE_IS_PLAYING)
    {
        // 假设的条件判断,用于确定是否播放结束
        if (TwoWire_AskStatus())
        {
            // 清除状态计数器
            audio_params->ask_status_cnt = 0;
            // 标记烹饪语音状态为未播放
            stSysParam.stCookingParam.voiceState = FALSE;
            audio_params->audio_state = AUDIO_STATE_DELAYING;
            audio_params->word_pause_duration = 0;
        }
        else
        {
            // 增加状态计数器
            audio_params->ask_status_cnt++;
            // 标记烹饪语音状态为正在播放
            stSysParam.stCookingParam.voiceState = true;
        }

        // 1允许打断
        if (audio_params->allow_interruption == 0)
        {
            if (bsp_IsAudioMsgEmpty())
            {
                audio_params->audio_state = AUDIO_STATE_IDLE;
            }
        }
    }

    if (audio_params->audio_state == AUDIO_STATE_DELAYING)
    {
        audio_params->word_pause_duration++;
        if (audio_params->word_pause_duration >= audio_params->hlodTimer)
        {
            audio_params->audio_state = AUDIO_STATE_PLAYING;
        }

        // 1允许打断
        if (audio_params->allow_interruption == 0)
        {
            if (bsp_IsAudioMsgEmpty())
            {
                audio_params->audio_state = AUDIO_STATE_IDLE;
            }
        }
    }
}


int8_t Pro_Yuyin_UpdateDataHandle(uint8_t *inData, uint32_t dataLen)
{
    UINT8 *Addr = 0;
    static UINT32 u32StartAddr = 0;
    static UINT32 u32ISPSize = 0; // init parameter
    static UINT32 u32ISPSizeDone = 0;
    static UINT32 u32ISPADDR = 0;

    static UINT16 ISP_CHECKSUM_BYTES = 0;
    static UINT16 u16ISPChecksumFromFile = 0;
    // static char data_cnt = 0;       // 数据整合计数
    static unsigned char idata = 0; // 数据整合计数
    short i;
    uint8_t md5_calc[SSL_MAX_LEN]; // MD5 Calculate Fact

    if (NULL == inData)
    {
        return -1;
    }
    memcpy((uint8_t *)&pieceData, inData, dataLen);
    piecenum = exchangeBytes(pieceData.piecenum);
    piececount = exchangeBytes(pieceData.piececount);

    if (1 == piecenum)
    {
        GAgent_MD5Update(&nsp_romUpdate.ctx, &pieceData.piececontent[0], dataLen - 4);
        // memset(&ivoice_fw_pkt_t, 0, sizeof(voice_fw_pkt_t));
        // memcpy(&ivoice_fw_pkt_t, &gizwitsProtocol.protocolBuf[0], sizeof(voice_fw_pkt_t));
        g_saveParam.voice_fw_pkt.valid_flag = 1; // 数据包有效性标志,1-无效,2-有效(数据包经过检查是正确的)

        // ivoice_fw_pkt_t.voice_ver = pieceData.piececontent[4];             // 语音数据版本号:0~99
        // ivoice_fw_pkt_t.voice_type = (VoiceType)pieceData.piececontent[5]; // 语音类型编码:

        memset(g_au8Buf, 0, sizeof(g_au8Buf));
        Addr = (UINT8 *)&pieceData.piececontent[10];

        u32StartAddr = 10;
        memcpy((uint8_t *)&g_au8Buf, (uint8_t *)Addr, 22);
        u32FirstSegADDR = (g_au8Buf[18] << 24) + (g_au8Buf[19] << 16) + (g_au8Buf[20] << 8) + g_au8Buf[21]; // 得到第一个区块的位移
                                                                                                            // get 1st Segment Data Offset
        u32StartAddr = u32StartAddr + u32FirstSegADDR;
        Addr += u32FirstSegADDR;
        memcpy((uint8_t *)&g_au8Buf, (uint8_t *)Addr, 18);
        u32ISPADDR = (g_au8Buf[0] << 24) + (g_au8Buf[1] << 16) + (g_au8Buf[2] << 8) + g_au8Buf[3];     // 得到第一个区块的写入地址
        u32ISPReadADDR = u32ISPADDR;                                                                   // get 1st Segment ISP write address
        u32ISPSize = (g_au8Buf[4] << 24) + (g_au8Buf[5] << 16) + (g_au8Buf[6] << 8) + g_au8Buf[7];     // 得到第一个区块的写入长度
                                                                                                       // get 1st Segment ISP write size
        u16ISPChecksumFromFile = (g_au8Buf[8] << 8) + g_au8Buf[9];                                     // 得到第一个区块的checksum
                                                                                                       // get 1st Segment checksum
        u32NSP_ID = (g_au8Buf[10] << 24) + (g_au8Buf[11] << 16) + (g_au8Buf[12] << 8) + g_au8Buf[13];  // 得到product ID
                                                                                                       // get product ID
        u32CHIP_ID = (g_au8Buf[14] << 24) + (g_au8Buf[15] << 16) + (g_au8Buf[16] << 8) + g_au8Buf[17]; // 得到CHIP_ID
                                                                                                       // get CHIP_ID
        u32StartAddr += 10;
        u8RightCMD = N_ISP_WRITE_START(u32NSP_ID, u32CHIP_ID);
        if (u8RightCMD != 1)
        {
            return -1;
        }
        // 初始化队列
        initQueue(&q_voice_update);

        // 添加一些元素到队列中
        for (i = 0; i < (PIECE_MAX_LEN - u32StartAddr); i++)
        {
            idata = pieceData.piececontent[i + u32StartAddr]; // 丢弃增加的bin包判断数据
            enqueue(&q_voice_update, idata);                  // 将idata值添加到队列中
        }

        HOST_BUS_Init(); // IO 界面初始化
    }
    else
    {
        GAgent_MD5Update(&nsp_romUpdate.ctx, (uint8_t *)pieceData.piececontent, dataLen - 4);
        for (i = 0; i < (dataLen - 4); i++)
        {
            idata = pieceData.piececontent[i]; // 丢弃增加的bin包判断数据
            enqueue(&q_voice_update, idata);   // 将idata值添加到队列中
        }

        if (piecenum == piececount)
        {
            memset(md5_calc, 0, SSL_MAX_LEN);
            GAgent_MD5Final(&nsp_romUpdate.ctx, md5_calc);

            GIZWITS_LOG("MD5 Calculate Success , Will Check The MD5 ..\n ");

            if (0 != memcmp(romUpdate.update_param.ssl_data, md5_calc, SSL_MAX_LEN))
            {
                GIZWITS_LOG("Md5_Cacl Check Faild ,MCU OTA Faild\r\n ");
                return -2;
            }

            // memset(g_au8Buf, 0, sizeof(g_au8Buf));
            for (i = 0; i < (q_voice_update.size); i++)
            {
                dequeue(&q_voice_update, &idata);
                g_au8Buf[i] = idata;
            }

            __disable_irq(); // 关闭总中断
            HOST_BUS_Init(); // IO 界面初始化
            HOST_Delay500uS();

            if (u32ISPSizeDone < u32ISPSize) // 完成ISP写入过程,每次写入512字节
            {
                u32StartAddr += FLASH_PAGE_SIZE;
                ISP_BUFFER = g_au8Buf;
                N_ISP_WRITE_PAGE(u32ISPADDR, ISP_BUFFER); // ISP写入512字节
                u32ISPADDR += FLASH_PAGE_SIZE;
                u32ISPSizeDone += FLASH_PAGE_SIZE;
            }
            N_ISP_WRITE_END();                   // ISP写入完成
            N_ISP_CHECKSUM(&ISP_CHECKSUM_BYTES); // 得到ISP checksum

            __enable_irq(); // 开启总中断
            if (ISP_CHECKSUM_BYTES == u16ISPChecksumFromFile)
            {
                g_saveParam.voice_fw_pkt.valid_flag = 2;                          // 数据包有效性标志,1-无效,2-有效(数据包经过检查是正确的)
                g_saveParam.voice_fw_pkt.voice_ver = ivoice_fw_pkt_t.voice_ver;   // 语音数据版本号:0~99
                g_saveParam.voice_fw_pkt.voice_type = ivoice_fw_pkt_t.voice_type; // 语音类型编码:

                romUpdate.otaBusyModeFlag = 2;
                g_stParam.report_time = 0;
                currentDataPoint.valuer1[0] = g_saveParam.voice_fw_pkt.voice_type;
                FSM_WIFI_RT_ERR = TRUE;
                g_stParam.get_wifiStatus.types.con_route = TRUE;
                g_stParam.get_wifiStatus.types.con_m2m = TRUE;
                SaveParam(); // 将新参数写入Flash

                romUpdate.otaUpModeFlag = TRUE;
                romUpdate.otaTimeCnt = 5;
                return 1;
            }
        }
        else
        {
            //  检查队列中当前有多少数据
            if (q_voice_update.size >= 512)
            {
                memset(g_au8Buf, 0, sizeof(g_au8Buf));
                for (i = 0; i < 512; i++)
                {
                    dequeue(&q_voice_update, &idata);
                    g_au8Buf[i] = idata;
                }
                __disable_irq(); // 关闭总中断
                HOST_BUS_Init(); // IO 界面初始化
                HOST_Delay500uS();
                // N_WAKUP();                       // 唤醒
                if (u32ISPSizeDone < u32ISPSize) // 完成ISP写入过程,每次写入512字节
                {
                    ISP_BUFFER = g_au8Buf;
                    N_ISP_WRITE_PAGE(u32ISPADDR, ISP_BUFFER); // ISP写入512字节

                    u32ISPADDR += FLASH_PAGE_SIZE;
                    u32ISPSizeDone += FLASH_PAGE_SIZE;
                }
                __enable_irq(); // 开启总中断
            }
        }
    }

    return 0;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
资源包主要包含以下内容: ASP项目源码:每个资源包中都包含完整的ASP项目源码,这些源码采用了经典的ASP技术开发,结构清晰、注释详细,帮助用户轻松理解整个项目的逻辑和实现方式。通过这些源码,用户可以学习到ASP的基本语法、服务器端脚本编写方法、数据库操作、用户权限管理等关键技术。 数据库设计文件:为了方便用户更好地理解系统的后台逻辑,每个项目中都附带了完整的数据库设计文件。这些文件通常包括数据库结构图、数据表设计文档,以及示例数据SQL脚本。用户可以通过这些文件快速搭建项目所需的数据库环境,并了解各个数据表之间的关系和作用。 详细的开发文档:每个资源包都附有详细的开发文档,文档内容包括项目背景介绍、功能模块说明、系统流程图、用户界面设计以及关键代码解析等。这些文档为用户提供了深入的学习材料,使得即便是从零开始的开发者也能逐步掌握项目开发的全过程。 项目演示与使用指南:为帮助用户更好地理解和使用这些ASP项目,每个资源包中都包含项目的演示文件和使用指南。演示文件通常以视频或图文形式展示项目的主要功能和操作流程,使用指南则详细说明了如何配置开发环境、部署项目以及常见问题的解决方法。 毕业设计参考:对于正在准备毕业设计的学生来说,这些资源包是绝佳的参考材料。每个项目不仅功能完善、结构清晰,还符合常见的毕业设计要求和标准。通过这些项目,学生可以学习到如何从零开始构建一个完整的Web系统,并积累丰富的项目经验。
资源包主要包含以下内容: ASP项目源码:每个资源包中都包含完整的ASP项目源码,这些源码采用了经典的ASP技术开发,结构清晰、注释详细,帮助用户轻松理解整个项目的逻辑和实现方式。通过这些源码,用户可以学习到ASP的基本语法、服务器端脚本编写方法、数据库操作、用户权限管理等关键技术。 数据库设计文件:为了方便用户更好地理解系统的后台逻辑,每个项目中都附带了完整的数据库设计文件。这些文件通常包括数据库结构图、数据表设计文档,以及示例数据SQL脚本。用户可以通过这些文件快速搭建项目所需的数据库环境,并了解各个数据表之间的关系和作用。 详细的开发文档:每个资源包都附有详细的开发文档,文档内容包括项目背景介绍、功能模块说明、系统流程图、用户界面设计以及关键代码解析等。这些文档为用户提供了深入的学习材料,使得即便是从零开始的开发者也能逐步掌握项目开发的全过程。 项目演示与使用指南:为帮助用户更好地理解和使用这些ASP项目,每个资源包中都包含项目的演示文件和使用指南。演示文件通常以视频或图文形式展示项目的主要功能和操作流程,使用指南则详细说明了如何配置开发环境、部署项目以及常见问题的解决方法。 毕业设计参考:对于正在准备毕业设计的学生来说,这些资源包是绝佳的参考材料。每个项目不仅功能完善、结构清晰,还符合常见的毕业设计要求和标准。通过这些项目,学生可以学习到如何从零开始构建一个完整的Web系统,并积累丰富的项目经验。
资源包主要包含以下内容: ASP项目源码:每个资源包中都包含完整的ASP项目源码,这些源码采用了经典的ASP技术开发,结构清晰、注释详细,帮助用户轻松理解整个项目的逻辑和实现方式。通过这些源码,用户可以学习到ASP的基本语法、服务器端脚本编写方法、数据库操作、用户权限管理等关键技术。 数据库设计文件:为了方便用户更好地理解系统的后台逻辑,每个项目中都附带了完整的数据库设计文件。这些文件通常包括数据库结构图、数据表设计文档,以及示例数据SQL脚本。用户可以通过这些文件快速搭建项目所需的数据库环境,并了解各个数据表之间的关系和作用。 详细的开发文档:每个资源包都附有详细的开发文档,文档内容包括项目背景介绍、功能模块说明、系统流程图、用户界面设计以及关键代码解析等。这些文档为用户提供了深入的学习材料,使得即便是从零开始的开发者也能逐步掌握项目开发的全过程。 项目演示与使用指南:为帮助用户更好地理解和使用这些ASP项目,每个资源包中都包含项目的演示文件和使用指南。演示文件通常以视频或图文形式展示项目的主要功能和操作流程,使用指南则详细说明了如何配置开发环境、部署项目以及常见问题的解决方法。 毕业设计参考:对于正在准备毕业设计的学生来说,这些资源包是绝佳的参考材料。每个项目不仅功能完善、结构清晰,还符合常见的毕业设计要求和标准。通过这些项目,学生可以学习到如何从零开始构建一个完整的Web系统,并积累丰富的项目经验。
资源包主要包含以下内容: ASP项目源码:每个资源包中都包含完整的ASP项目源码,这些源码采用了经典的ASP技术开发,结构清晰、注释详细,帮助用户轻松理解整个项目的逻辑和实现方式。通过这些源码,用户可以学习到ASP的基本语法、服务器端脚本编写方法、数据库操作、用户权限管理等关键技术。 数据库设计文件:为了方便用户更好地理解系统的后台逻辑,每个项目中都附带了完整的数据库设计文件。这些文件通常包括数据库结构图、数据表设计文档,以及示例数据SQL脚本。用户可以通过这些文件快速搭建项目所需的数据库环境,并了解各个数据表之间的关系和作用。 详细的开发文档:每个资源包都附有详细的开发文档,文档内容包括项目背景介绍、功能模块说明、系统流程图、用户界面设计以及关键代码解析等。这些文档为用户提供了深入的学习材料,使得即便是从零开始的开发者也能逐步掌握项目开发的全过程。 项目演示与使用指南:为帮助用户更好地理解和使用这些ASP项目,每个资源包中都包含项目的演示文件和使用指南。演示文件通常以视频或图文形式展示项目的主要功能和操作流程,使用指南则详细说明了如何配置开发环境、部署项目以及常见问题的解决方法。 毕业设计参考:对于正在准备毕业设计的学生来说,这些资源包是绝佳的参考材料。每个项目不仅功能完善、结构清晰,还符合常见的毕业设计要求和标准。通过这些项目,学生可以学习到如何从零开始构建一个完整的Web系统,并积累丰富的项目经验。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值