menu_1

menu.c


/*
 * menu.c
 *
 *  Created on: Apr 11, 2023
 *      Author: Administrator
 */

#include "menu.h"
#include "stdio.h"
#include "debug.h"
#include "str7565.h"
#include "app_message.h"
#include <string.h>
#include "main_task.h"
#include "breakpoint.h"
#include "multi_timer.h"
#include "ctrlvars.h"
#include "ff.h"

#define CAIDAN_ZHU 		(0)//菜单起始位置
#define CAIDAN_FU 		(X_col-48-4)//副菜单起始位置

uint8_t Index = 0;//索引
bool SetMode = FALSE;//mjt 0 正常模式  1 设置模式
bool MenuTwoSet = FALSE;//记录是否从二级菜单退回来

static void menu_1(uint8_t a, uint16_t keyms);

static void set_break(uint8_t a, uint16_t keyms);		/* 退出  */
static void set_reset(uint8_t a, uint16_t keyms);		/* 复位  */
static void set_mic_reset(uint8_t a, uint16_t keyms);		/* 无线话筒重新配对  */
static void set_info(uint8_t a, uint16_t keyms);		/* 信息  */

static void set_mode(uint8_t a, uint16_t keyms);		/* 模式  */
//static void set_location(uint8_t a, uint16_t keyms);	/* 位置  */
static void set_eqh(uint8_t a, uint16_t keyms);			/* EQ高音  */
static void set_eql(uint8_t a, uint16_t keyms);			/* EQ中音  */
static void set_mich(uint8_t a, uint16_t keyms);		/* EQ低音  */
static void set_micl(uint8_t a, uint16_t keyms);		/* sub低音  */
static void set_delay(uint8_t a, uint16_t keyms);		/* delay回声  */
static void set_reverb(uint8_t a, uint16_t keyms);		/* reverbGAIN  */
static void set_shunning(uint8_t a, uint16_t keyms);	/* 闪避  */
static void set_merge(uint8_t a, uint16_t keyms);		/* 立体声  */
static void set_contrast(uint8_t a, uint16_t keyms);	/* 显示对比度  */
static void set_bright(uint8_t a, uint16_t keyms);		/* 显示亮度  */

//static char *get_mode(void);
//static char *get_location(void);
//static char *get_eqh(void);
//static char *get_eql(void);
static char *get_mich(void);
static char *get_micl(void);
//static char *get_delay(void);
//static char *get_shunning(void);
static char *get_reverb(void);
static char *get_merge(void);
static char *get_contrast(void);
static char *get_bright(void);

static void file_menu(uint8_t a, uint16_t keyms);//文件菜单

KEY_INDEX_STRUCT Key_table[] =
{
    //当前,		下,             上,       确定,        内容,  		  函数,		volue
    {first0,	first1,     first0,     two0,       "    EXIT ",	(*menu_1),		NULL},//一级菜单
	{first1,	first2,     first0,     two1,       "  FOLDER ",	(*menu_1),		NULL},//一级菜单
    {first2,	first3,     first1,     two2,       "    MODE:",	(*menu_1),		(*get_mode)},//一级菜单
    {first3,	first4,     first2,     two3,       " MUSIC H:",	(*menu_1),		(*get_eqh)},//一级菜单
    {first4,	first5,     first3,     two4,    	" MUSIC L:", 	(*menu_1),		(*get_eql)},//一级菜单
    {first5,	first6,     first4,     two5,  		"   MIC H:", 	(*menu_1),		(*get_mich)},//一级菜单
    {first6,	first7,     first5,     two6,     	"   MIC L:", 	(*menu_1),		(*get_micl)},//一级菜单
    {first7,	first7_1,   first6,     two7,     	"    ECHO:", 	(*menu_1),		(*get_delay)},//一级菜单
    {first7_1,	first7_2,   first7,     two7_1,   	"  REVERB:", 	(*menu_1),		(*get_reverb)},//一级菜单
    {first7_2,	first7_3,   first7_1,   two7_2,   	"SHUNNING:", 	(*menu_1),		(*get_shunning)},//一级菜单
    {first7_3,	first8,     first7_2,   two7_3,		"  STEREO:", 	(*menu_1),		(*get_merge)},//一级菜单
    {first8,	first9,     first7_3,   two8,     	"CONTRAST:", 	(*menu_1),		(*get_contrast)},//一级菜单
    {first9,	first10,    first8,     two9,     	"  BRIGHT:", 	(*menu_1),		(*get_bright)},//一级菜单
    {first10,	first10_1,  first9,     two10,    	"   RESET ", 	(*menu_1),		NULL},//一级菜单
    {first10_1,	first11,    first10,    two10_1,    "     MIC ", 	(*menu_1),		NULL},//一级菜单
    {first11,	first12,    first10_1,  two11,      "    INFO ", 	(*menu_1),		NULL},//一级菜单
    {first12,	first12,    first11,    two0,       "    EXIT ", 	(*menu_1),		NULL},//一级菜单

    {two0,		two0,       two0,       first0,     " ",    		(*set_break),	NULL},//二级菜单//属于一级菜单的副菜单
    {two1,		two1,       two1,       two1,     	" ",    		(*file_menu),	NULL},//二级菜单
    {two2,		two2,       two2,       first2,     " ",    		(*set_mode),	NULL},//二级菜单
    {two3,		two3,       two3,       first3,     " ",    		(*set_eqh),		NULL},//二级菜单
    {two4,		two4,       two4,       first4,     " ",    		(*set_eql),		NULL},//二级菜单
    {two5,		two5,       two5,       first5,     " ",    		(*set_mich),	NULL},//二级菜单
    {two6,		two6,       two6,       first6,     " ",    		(*set_micl),	NULL},//二级菜单
    {two7,		two7,       two7,       first7,     " ",    		(*set_delay),	NULL},//二级菜单
    {two7_1,	two7_1,     two7_1,     first7_1,   " ",    		(*set_reverb),	NULL},//二级菜单
    {two7_2,	two7_2,     two7_2,     first7_2,   " ",    		(*set_shunning),NULL},//二级菜单
    {two7_3,	two7_3,     two7_3,     first7_3,   " ",    		(*set_merge),	NULL},//二级菜单
    {two8,		two8,       two8,       first8,     " ",    		(*set_contrast),NULL},//二级菜单
    {two9,		two9,       two9,       first9,     " ",    		(*set_bright),	NULL},//二级菜单
    {two10,		two10,      two10,      two10,    	" ",    		(*set_reset),	NULL},//二级菜单
    {two10_1,	two10_1,    two10_1,    two10_1,    " ",    		(*set_mic_reset),	NULL},//二级菜单
    {two11,		two11,      two11,      first11,    " ",    		(*set_info),	NULL},//二级菜单
    {two12,		two12,      two12,      first12,    " ",    		(*set_break),	NULL},//二级菜单
};
//==================================================
//extern bool snail_test(uint16_t FileBumber);

MENU_FOLDER_STRUCT menu1 = {
		.nowmouse = 0,
//		.lastmouse = 0,
		.nowindex = 0,
//		.lastindex = 0,
		.firstshow = 0,
		.length = 0,
		.depth = 0,
};//记录folder菜单全部内容

//------------------------------------------------------------------
typedef char * LTDataType;//假设结点的数据域类型为 char *

// 带哨兵位双向循环链表的结构体定义
typedef struct ListNode
{
	struct ListNode* prev;//前驱指针域:存放上一个结点的地址
	struct ListNode* next;//后继指针域:存放下一个结点的地址
	LTDataType data;//数据域
}LTNode;

//动态申请一个结点
LTNode* BuyListNode(LTDataType x)
{
	LTNode* node = (LTNode*)osPortMalloc(sizeof(LTNode));
	if (node == NULL)//如果malloc失败
	{
		DBG("malloc fail");
		return NULL;
	}
	//如果malloc成功
	//初始化一下,防止野指针,如果看到返回的是空指针,那逻辑可能有些错误
	node->next = NULL;
	node->prev = NULL;
	node->data = x;

	return node;
}

// 双向链表的初始化
LTNode* LTInit()
{
	static char a[2] = "--";
	LTNode* phead = BuyListNode(a);
	//自己指向自己
	phead->next = phead;
	phead->prev = phead;

	return phead;
}

// 双向链表在pos位置之前进行插入x
void LTInsert(LTNode* pos, LTDataType x)
{
//	assert(pos);//pos肯定不为空

	LTNode* prev = pos->prev;
	LTNode* newnode = BuyListNode(x);//创建一个需要插入的结点

	prev->next = newnode;
	newnode->prev = prev;

	newnode->next = pos;
	pos->prev = newnode;
}

// 双向链表的打印
void LTPrint(LTNode* phead)
{
//	assert(phead);//有哨兵位
	APP_DBG("<=>phead<=>");
	LTNode* cur = phead->next;//cur指向第一个要打印的结点
	while (cur != phead)//cur等于头结点时打印就结束了
	{
		APP_DBG("%s<=>", cur->data);
		cur = cur->next;
	}
	APP_DBG("\n");
}

// 双向链表删除pos位置的结点
void LTErase(LTNode* pos)
{
//	assert(pos);//pos肯定不为空

	LTNode* posprev = pos->prev;
	LTNode* posnext = pos->next;

	posprev->next = posnext;
	posnext->prev = posprev;

	osPortFree(pos->data);//mjt
	osPortFree(pos);
	pos = NULL;
	//这个置空其实已经没有意义了,形参的改变不会改变实参
}

 双向链表的尾插
//void LTPushBack(LTNode* phead, LTDataType x)
//{
//	assert(phead);//有哨兵位
//
//	//法一:(便于新手更好地理解双向链表的尾插)
//	//一步就可完成链表为空/不为空的尾插
//	//LTNode* newnode = BuyListNode(x);
//	//LTNode* tail = phead->prev;
//
//	//tail->next = newnode;
//	//newnode->prev = tail;
//	//newnode->next = phead;
//	//phead->prev = newnode;
//
//	//法二:函数复用(简单方便)
//	LTInsert(phead, x);
//}

// 双向链表的判空
bool LTEmpty(LTNode* phead)
{
//	assert(phead);

	return phead->next == phead;
	//两者相等就是空链表(返回真),两者不相等就不是空链表(返回假)
}

 双向链表的尾删
//void LTPopBack(LTNode* phead)
//{
//	assert(phead);//有哨兵位
//
//	//法一:(便于新手更好地理解双向链表的尾删)
//	//assert(!LTEmpty(phead));//判空
//
//	//LTNode* tail = phead->prev;
//	//LTNode* tailPrev = tail->prev;
//
//	//tailPrev->next = phead;
//	//phead->prev = tailPrev;
//	//free(tail);
//	//tail = NULL;
//
//	//法二:函数复用
//	LTErase(phead->prev);
//}

 双向链表头插
//void LTPushFront(LTNode* phead, LTDataType x)
//{
//	assert(phead);//有哨兵位
//
//	//LTNode* newnode = BuyListNode(x);//创建一个要插入的结点
//
//	//法一:只用phead和newnode两个指针(便于新手更好地理解双向链表的头插)
//	//newnode->next = phead->next;
//	//phead->next->prev = newnode;
//
//	//phead->next = newnode;
//	//newnode->prev = phead;
//
//	//法二:多用了first先记住第一个结点(便于新手更好地理解双向链表的头插)
//	//LTNode* first = phead->next;
//	//phead->next = newnode;
//	//newnode->prev = phead;
//
//	//newnode->next = first;
//	//first->prev = newnode;
//
//	//法三:函数复用(简单方便)
//	LTInsert(phead->next, x);
//}

// 双向链表头删
void LTPopFront(LTNode* phead)
{
//	assert(phead);//有哨兵位
//	assert(!LTEmpty(phead));//判空

	if(LTEmpty(phead)) return;

	//法一:(便于新手更好地理解双向链表的头删)
	//LTNode* head = phead->next;
	//LTNode* headnext = head->next;

	//phead->next = headnext;
	//headnext->prev = phead;

	//free(head);
	//head = NULL;

	//法二:函数复用(简单方便)
	LTErase(phead->next);
}

 双向链表查找值为x的结点
//LTNode* LTFind(LTNode* phead, LTDataType x)
//{
//	assert(phead);//有哨兵位
//
//	LTNode* cur = phead->next;
//	while (cur != phead)//让cur去遍历
//	{
//		if (cur->data == x)
//		{
//			return cur;
//		}
//		cur = cur->next;
//	}
//	return NULL;
//}

 双向链表的销毁
//void LTDestory(LTNode* phead)
//{
//	assert(phead);
//
//	LTNode* cur = phead->next;
//	while (cur != phead)
//	{
//		LTNode* curnext = cur->next;
//		free(cur->data);//mjt
//		free(cur);
//		cur = curnext;
//	}
//	free(phead);
//	phead = NULL;
//	//这个置空其实已经没有意义了,形参的改变不会改变实参
//	//我们为了保持接口的一致性,不传二级指针,选择在测试的时候置空
//}
//
 双向链表的修改,修改pos位置的值为x
//void LTModify(LTNode* pos, LTDataType x)
//{
//	assert(pos);//pos肯定不为空
//	pos->data = x;
//}
//
 双向链表删除值为x的结点
//void LTRemove(LTNode* phead, LTDataType x)
//{
//	assert(phead);//有哨兵位
//	LTNode* pos = phead->next;
//	while (pos != phead)
//	{
//		pos = LTFind(phead, x);
//		if (pos == NULL)//如果遍历完
//		{
//			return NULL;
//		}
//		LTErase(pos);
//		pos = pos->next;
//	}
//}
//
 双向链表计算结点总数(不计phead)
//int LTTotal(LTNode* phead)
//{
//	assert(phead);//有哨兵位
//
//	int count = 0;//count来计数
//	LTNode* cur = phead->next;//让cur去遍历
//	while (cur != phead)
//	{
//		count++;
//		cur = cur->next;
//	}
//	return count;
//}
//
 双向链表获取第i位置的结点
//LTNode* LTGet(LTNode* phead, int i)
//{
//	assert(phead);//有哨兵位
//
//	int length = LTTotal(phead);
//	LTNode* cur = phead->next;
//	if (i == 0)
//	{
//		return phead;
//	}
//	else if (i<0 || i>length)//位置不合法
//	{
//		return NULL;
//	}
//	else if (i <= (length / 2))//从表头开始遍历
//	{
//		cur = phead->next;
//		for (int count = 1; count < i; count++)
//		{
//			cur = cur->next;
//		}
//	}
//	else//从表尾开始遍历
//	{
//		cur = phead->prev;
//		for (int count = 1; count <= length - i; count++)
//		{
//			cur = cur->prev;
//		}
//	}
//	return cur;
//}
//
// 双向链表的清空
void LTClear(LTNode* phead)
{
//	assert(phead);//有哨兵位

	while (!LTEmpty(phead))//如果不为空就一直头删
	{
		LTPopFront(phead);
	}
}



/*mjt*/
LTNode* plist = NULL;

void node_add(char *data, int len)
{
	char* new_data = (char*)osPortMalloc(len+1);
	if (new_data == NULL)//如果malloc失败
	{
		DBG("malloc fail");
		return;
	}

	memset(new_data, 0, len+1);
    memcpy(new_data, data, len);

    LTInsert(plist, new_data);
}

void node_del(void)
{
//	taskENTER_CRITICAL();
	LTClear(plist);
//	taskEXIT_CRITICAL();
}

void menu_folder_int(void)
{
    plist = LTInit();

//    APP_DBG("=========test=========\n");
//	node_add("123", 3);
//	node_add("abc", 3);
//	LTPrint(plist);
//	node_del();
//	node_add("111", 3);
//	node_add("222", 3);
//	node_add("333", 3);
//	LTPrint(plist);
//	node_del();
}

//------------------------------------------------------------------
int traverse_folder(const TCHAR* path)
{
    FILINFO fno;
    DIR dir;
    FRESULT res;

    char sub_path[256];
    int len = 0;
    menu1.length = 0;

    res = f_opendir(&dir, path);
    if (res != FR_OK) return res;


    while (1)
    {
    	taskENTER_CRITICAL();
        res = f_readdir(&dir, &fno);
        taskEXIT_CRITICAL();

        if (res != FR_OK || fno.fname[0] == 0) break;

        if (fno.fattrib & AM_DIR) {
            if (strcmp(fno.fname, ".") == 0 || strcmp(fno.fname, "..") == 0) continue;
            if(strcmp(fno.fname, "System Volume Information") == 0) continue;//跳出隐藏文件夹

            len = sprintf(sub_path, "%s/%s", path, fno.fname);
            node_add(sub_path, len);
//            APP_DBG("%s\n", sub_path);

//            traverse_folder(sub_path);

            menu1.length++;
        } else {
            // 处理文件
            // fno.fname 是当前文件的名称
            // 可以在这里进行你的操作,比如打印文件名

        	len = sprintf(sub_path, "%s/%s", path, fno.fname);
            node_add(sub_path, len);
//            APP_DBG("%s\n", sub_path);

            menu1.length++;
        }

    }

    f_closedir(&dir);
    return FR_OK;
}

static char *LT_g(int index)
{
	int i;
	LTNode* cur = plist;//cur指向第一个要打印的结点

	for(i = 0; i < index; i++)
	{
		cur = cur->next;
	}
	return cur->data;
}

//输入索引 返回字符串首地址
static char *get_str(uint16_t index)
{
	static char *ret_break = "exit";
	static char *ret_error = " ";

	if(index == 0) return ret_break;
	if(index > menu1.length-1) return ret_error;

//	APP_DBG("[%d]-> %s\n", index, LT_g(index));

	char *ret = strrchr(LT_g(index), '/');

	return (ret+1);
}

// 文件夹进入下一层,或者退回上一层
//  n_r = 1 下一层 0 上一层    path 当前路径  2 当前层
static int file_in(char *path, int n_r)
{
	int i;
	int fileret = 0;
	char *now;//当前位置
	char *ret;//要删除的位置
    char file_path[256];

	if(n_r == 1)//下一层
	{
		menu1.depth++;

		sprintf(file_path, "%s", path);
	}
	else if(n_r == 2)//当前层
	{
		now = path;
		ret = strrchr(now, '/');
		memset(ret, 0x00, strlen(ret));
		sprintf(file_path, "%s", now);
	}
	else
	{
		menu1.depth--;

		now = path;
		ret = strrchr(now, '/');

//		APP_DBG("now1 = %s\n", now);
		memset(ret, 0x00, strlen(ret));
//		APP_DBG("now2 = %s\n", now);
		ret = strrchr(now, '/');
		memset(ret, 0x00, strlen(ret));
//		APP_DBG("now3 = %s\n", now);

		sprintf(file_path, "%s", now);
	}

	APP_DBG("new folder = %s\n", file_path);

	node_del();//释放内存

//	taskENTER_CRITICAL();
	fileret = traverse_folder(file_path);
//	taskEXIT_CRITICAL();

	APP_DBG("OPEN = %d\n", fileret);//读取文件

	menu1.length++;//加上一个返回的目录
	APP_DBG("folder len = %d", menu1.length);
	for(i = 0; i < menu1.length; i++) APP_DBG("[%d]-> %s\n", i, LT_g(i));//LOG

	return fileret;
}
static void file_menu_clear(void)
{
	menu1.nowmouse = 0;
	menu1.nowindex = 0;
	menu1.firstshow = 0;
}
static void file_menu(uint8_t a, uint16_t keyms)//文件菜单
{
	int i;
	int ret;

	switch(keyms)
	{
		case MSG_USER_UP:
			if(menu1.nowindex < menu1.length-1)menu1.nowindex++;

			if(menu1.nowmouse < MAX_LINE-1 && menu1.nowmouse < menu1.length-1){
				menu1.nowmouse++;
			}
			else {
				if (menu1.firstshow < menu1.length - MAX_LINE)menu1.firstshow++;
			}
			break;
		case MSG_USER_DOWN:
			if(menu1.nowindex > 0)menu1.nowindex--;

			if(menu1.nowmouse > 0){
				menu1.nowmouse--;
			}
			else {
				if(menu1.firstshow > 0)menu1.firstshow--;
			}
			break;
		case MSG_USER_ENTER:
			APP_DBG("===menu_enter===\n");
			if(!MenuTwoSet)//第一次进来
			{
				MenuTwoSet = TRUE;
				menu1.depth = 0;
				file_in(MEDIA_VOLUME_STR_U, 1);
			}
			else
			{
				if(menu1.nowindex == 0)//返回,要在这里判断是返回上一级目录 还是 退出文件管理
				{
					if(menu1.depth == 1)//退出文件管理
					{
						node_del();//释放内存
						Index = first1;
						menu_1(Index, 0);
						return;
					}
					else//返回上一层目录
					{
						file_in(LT_g(menu1.nowindex+1), 0);//+1避开链表头
					}
				}
				else//进入下一层目录
				{
					char *plast = LT_g(menu1.nowindex);
					ret = file_in(plast, 1);
					if(ret != 0)//失败
					{
						menu1.depth--;
						if(play_music(plast, menu1.depth))
						{
							set_break(NULL, MSG_NONE);
							return;
						}
						else
						{
							file_in(plast, 2);
						}
					}
					else
					{
						file_menu_clear();//进入下一层的时候要清除索引
					}
				}
			}
			break;
		default: break;
	}

	APP_DBG("Index = %d first = %d Mouse = %d\n", menu1.nowindex, menu1.firstshow, menu1.nowmouse);

    LCD_Clear();
    for (i = 0; i < MAX_LINE; i++)//更新显示
    {
        if (i == menu1.nowmouse) LCD_Show_Str_GB2312(CAIDAN_ZHU, i*16, get_str(menu1.firstshow+i), 1);//显示光标内容
        else LCD_Show_Str_GB2312(CAIDAN_ZHU, i*16, get_str(menu1.firstshow+i), 0);
    }
    LCD_Menu_Line(menu1.nowindex, menu1.length-1);
    LCD_Refresh();
}

//==================================================
MENU_DATA_STRUCT me1 = {
		.nowmouse = 0xFFFF,
		.lastmouse = 0xFFFF,
		.nowindex = 0xFFFF,
		.lastindex = 0xFFFF,
		.firstshow = first0,
};//记录一级菜单全部内容

void clean_menu_1(void)
{
	me1.nowmouse = 0xFFFF;
	me1.lastmouse = 0xFFFF;
	me1.nowindex = 0xFFFF;
	me1.lastindex = 0xFFFF;
	me1.firstshow = first0;
}

//写的第一版菜单,控制逻辑复杂了,能用,也懒得改了
//static void file_menu(uint8_t a, uint16_t keyms) 这个函数是后来写的,比较精简
void menu_1(uint8_t a, uint16_t keyms)
{
	int i;
	APP_DBG("%s\n", __FUNCTION__);//log

	if(MenuTwoSet)//二级菜单退回来不需要移动光标与菜单
	{
		MenuTwoSet = FALSE;

		LCD_Clear();
	    for (i = 0; i < MAX_LINE; i++)//更新显示
	    {
	        if (i == me1.nowmouse)
	        {
	        	LCD_ShowString(CAIDAN_ZHU, i*16, (uint8_t *)Key_table[me1.firstshow + i].str, 16, 1);
	        }
	        else
	        {
	        	LCD_ShowString(CAIDAN_ZHU, i*16, (uint8_t *)Key_table[me1.firstshow + i].str, 16, 0);
	        }
	        if(Key_table[me1.firstshow + i].volue_handle != NULL)
	        	LCD_ShowStr(CAIDAN_FU, i*16, 16, 0, "%s", (char *)(Key_table[me1.firstshow + i].volue_handle()));//显示当前对应的值 value
	    }
	    LCD_Menu_Line(me1.nowindex, first12);
	    LCD_Refresh();
		return;
	}

	me1.lastindex = me1.nowindex;
	me1.nowindex = a;

	//当本次索引等于上次索引代表已经加到列表最顶端或者最低端,此时不需要更新界面
	if (me1.nowindex == me1.lastindex)//界面没变化
		return;

	me1.lastmouse = me1.nowmouse;//设置光标
	switch (keyms)
    {
		//case MSG_USER_UP:
		case MSG_USER_DOWN:
				me1.nowmouse--;
			break;
		//case MSG_USER_DOWN:
		case MSG_USER_UP:
				me1.nowmouse++;
			break;
		case MSG_USER_ENTER:
			me1.nowmouse = me1.nowindex;
			break;
		default:
			break;
    }
	if (me1.nowmouse < 0) me1.nowmouse = 0;
	if (me1.nowmouse >= MAX_LINE - 1) me1.nowmouse = MAX_LINE - 1;

//	APP_DBG("Index = %d Msg = %d Mouse = %d\n", me1.nowindex, keyms, me1.nowmouse);

    if(me1.lastmouse == me1.nowmouse)//设置界面
    {
        if (me1.nowmouse == MAX_LINE - 1)//++++
        {
            me1.firstshow++;
        }
        else if (me1.nowmouse == 0)//---
        {
            me1.firstshow--;
        }
    }

    LCD_Clear();
    for (i = 0; i < MAX_LINE; i++)//更新显示
    {
        if (i == me1.nowmouse)
        {
        	LCD_ShowString(CAIDAN_ZHU, i*16, (uint8_t *)Key_table[me1.firstshow + i].str, 16, 1);
        }
        else
        {
        	LCD_ShowString(CAIDAN_ZHU, i*16, (uint8_t *)Key_table[me1.firstshow + i].str, 16, 0);
        }
        if(Key_table[me1.firstshow + i].volue_handle != NULL)
        	LCD_ShowStr(CAIDAN_FU, i*16, 16, 0, "%s", (char *)(Key_table[me1.firstshow + i].volue_handle()));//显示当前对应的值 value
    }
    LCD_Menu_Line(me1.nowindex, first12);
    LCD_Refresh();
}

//更新副菜单
static void menutwo_updis(void)
{
#ifdef CFG_FUNC_BREAKPOINT_EN
	BackupInfoUpdata(BACKUP_SYS_INFO);
#endif
	MenuTwoSet = TRUE;
    LCD_ShowString(CAIDAN_ZHU, (first0 + me1.nowmouse)*16, (uint8_t *)Key_table[first0 + me1.nowindex].str, 16, 0);

    LCD_ShowString(CAIDAN_FU, (first0 + me1.nowmouse)*16, (uint8_t *)"      ", 16, 0);//clearn
    LCD_ShowStr(CAIDAN_FU, (first0 + me1.nowmouse)*16, 16, 1,"%s", (char *)(Key_table[first0 + me1.nowindex].volue_handle()));
    LCD_Refresh();
}

int8_t volume_count = VOLUME_INIT_REST;//显示主音量-33+23 = -10
//---------------------mode----------------------
int8_t mode_count = 0;
char *mode[MODE_MAX] = {
	"MUSIC",
	"DJ",
	"LIVE",
	"SPEECH",
};
static void set_mode(uint8_t a, uint16_t keyms)
{
#if 0
	switch (keyms)
    {
		case MSG_USER_UP:
			mode_count++;
			if(mode_count > MODE_MAX-1)mode_count = 0;
			break;
		case MSG_USER_DOWN:
			mode_count--;
			if(mode_count < 0) mode_count = MODE_MAX-1;
			break;
		default:
			break;
    }
#else
	switch (keyms)
    {
		case MSG_USER_UP:
			mainAppCt.EqMode++;
			if(mainAppCt.EqMode > MODE_MAX-1)mainAppCt.EqMode = 0;
			break;
		case MSG_USER_DOWN:
			mainAppCt.EqMode--;
			if(mainAppCt.EqMode < 0 || mainAppCt.EqMode > MODE_MAX) mainAppCt.EqMode = MODE_MAX-1;
			break;
		default:
			break;
    }
#endif
	APP_DBG("%s = %d\n", __FUNCTION__, mainAppCt.EqMode);//log
	//ADAU1701_Mode_Set(mode_count);
    menutwo_updis();
}

char *get_mode(void)
{
	APP_DBG("%s\n", __FUNCTION__);//log
	return mode[mainAppCt.EqMode];
}

------------------location----------------------
//int8_t location_count = 0;
//char *location[LOCATION_MAX] = {
//	"NORMAL",
//	"MONTOR",
//};
//static void set_location(uint8_t a, uint16_t keyms)
//{
//	switch (keyms)
//    {
//		case MSG_USER_UP:
//			location_count++;
//			if(location_count > LOCATION_MAX-1)	location_count = 0;
//			break;
//		case MSG_USER_DOWN:
//			location_count--;
//			if(location_count < 0)	location_count = LOCATION_MAX-1;
//			break;
//		default:
//			break;
//    }
//	APP_DBG("%s = %d\n", __FUNCTION__, location_count);//log
//	//ADAU1701_LOCATION(location_count);
//    menutwo_updis();
//}
//
//static char *get_location(void)
//{
//	APP_DBG("%s\n", __FUNCTION__);//log
//	return location[location_count];
//}

//------------------EQHIGH----------------------
char eqh[5+1] = "0dB";

static void set_eqh(uint8_t a, uint16_t keyms)
{
	switch (keyms)
    {
		case MSG_USER_UP:
			if(mainAppCt.MusicTrebStep < 24)// +-12DB
			{
				mainAppCt.MusicTrebStep++;
			}
			break;
		case MSG_USER_DOWN:
			if(mainAppCt.MusicTrebStep)
			{
				mainAppCt.MusicTrebStep--;
			}
			break;
		default:
			break;
    }

	APP_DBG("%s = %d\n", __FUNCTION__, mainAppCt.MusicTrebStep);//log
//	sprintf(eqh, "%ddB", mainAppCt.MusicTrebStep-7);
	MusicBassTrebAjust(mainAppCt.MusicBassStep, mainAppCt.MusicTrebStep);

    menutwo_updis();
}

char *get_eqh(void)
{
	APP_DBG("%s\n", __FUNCTION__);//log
	sprintf(eqh, "%ddB", mainAppCt.MusicTrebStep-12);
	return eqh;
}

//------------------EQLOW----------------------
char eql[6+1] = "0dB";

static void set_eql(uint8_t a, uint16_t keyms)
{
	APP_DBG("%s\n", __FUNCTION__);//log
	switch (keyms)
    {
		case MSG_USER_UP:
			if(mainAppCt.MusicBassStep < 24)// +-12DB
			{
				mainAppCt.MusicBassStep++;
			}
			break;
		case MSG_USER_DOWN:
			if(mainAppCt.MusicBassStep)
			{
				mainAppCt.MusicBassStep--;
			}
			break;
		default:
			break;
    }

	APP_DBG("%s = %d\n", __FUNCTION__, mainAppCt.MusicBassStep);//log
//	sprintf(eql, "%ddB", mainAppCt.MusicBassStep-7);
	MusicBassTrebAjust(mainAppCt.MusicBassStep, mainAppCt.MusicTrebStep);

    menutwo_updis();
}

char *get_eql(void)
{
	APP_DBG("%s\n", __FUNCTION__);//log
	sprintf(eql, "%ddB", mainAppCt.MusicBassStep-12);
	return eql;
}

//------------------MICHIGH----------------------
char mich[5+1] = "0dB";

static void set_mich(uint8_t a, uint16_t keyms)
{
	APP_DBG("%s\n", __FUNCTION__);//log

	switch (keyms)
    {
		case MSG_USER_UP:
			if(mainAppCt.MicTrebStep < (24))// +-6DB
			{
				mainAppCt.MicTrebStep++;
			}
			break;
		case MSG_USER_DOWN:
			if(mainAppCt.MicTrebStep)// +-6DB
			{
				mainAppCt.MicTrebStep--;
			}
			break;
		default:
			break;
    }

	APP_DBG("%s = %d\n", __FUNCTION__, mainAppCt.MicTrebStep);//log
//	sprintf(mich, "%ddB", mainAppCt.MicTrebStep-7);
	MicBassTrebAjust(mainAppCt.MicBassStep, mainAppCt.MicTrebStep);

    menutwo_updis();
}

static char *get_mich(void)
{
	APP_DBG("%s\n", __FUNCTION__);//log
	sprintf(mich, "%ddB", mainAppCt.MicTrebStep-12);
	return mich;
}

//------------------MICLOW----------------------
char micl[5+1] = "0dB";

static void set_micl(uint8_t a, uint16_t keyms)
{
	switch (keyms)
    {
		case MSG_USER_UP:
			if(mainAppCt.MicBassStep < 24)// +-6DB
			{
				mainAppCt.MicBassStep++;
			}
			break;
		case MSG_USER_DOWN:
			if(mainAppCt.MicBassStep)// +-6DB
			{
				mainAppCt.MicBassStep--;
			}
			break;
		default:
			break;
    }

	APP_DBG("%s = %d\n", __FUNCTION__, mainAppCt.MicBassStep);//log
//	sprintf(micl, "%ddB", mainAppCt.MicBassStep-7);
	MicBassTrebAjust(mainAppCt.MicBassStep, mainAppCt.MicTrebStep);

    menutwo_updis();
}

static char *get_micl(void)
{
	APP_DBG("%s\n", __FUNCTION__);//log
	sprintf(micl, "%ddB", mainAppCt.MicBassStep-12);
	return micl;
}

//------------------DELAY----------------------
char delay[7+1] = "OFF";//-16.0ms

static void set_delay(uint8_t a, uint16_t keyms)
{
	switch (keyms)
    {
		case MSG_USER_UP:
			if(mainAppCt.EchoStep < 16) mainAppCt.EchoStep++;
			break;
		case MSG_USER_DOWN:
			if(mainAppCt.EchoStep > 0) mainAppCt.EchoStep--;
			break;
		default:
			break;
    }
//	if(mainAppCt.EchoStep == 0)
//		sprintf(delay, "OFF");
//	else
//		sprintf(delay, "%d\n", mainAppCt.EchoStep);

//	if(mainAppCt.EchoStep == 0){
//		gCtrlVars.echo_unit.enable = FALSE;
//		DBG("---------> mic_echo_control_unit.enable = FALSE \n");
//		EffectUpdataMsg();
//	}else if(mainAppCt.EchoStep == 1){
//		gCtrlVars.echo_unit.enable = TRUE;
//		DBG("---------> mic_echo_control_unit.enable = TRUE \n");
//		EffectUpdataMsg();
//	}

	APP_DBG("MicEchoStep = %d\n", mainAppCt.EchoStep);

	EchoStepSet(mainAppCt.EchoStep);

    menutwo_updis();
}

char *get_delay(void)
{
	APP_DBG("%s\n", __FUNCTION__);//log
	if(mainAppCt.EchoStep == 0)
		sprintf(delay, "OFF");
	else
		sprintf(delay, "%d\n", mainAppCt.EchoStep);
	return delay;
}

//------------------REVERB----------------------
char reverb[7+1] = "OFF";//-16.0ms

static void set_reverb(uint8_t a, uint16_t keyms)
{
	switch (keyms)
    {
		case MSG_USER_UP:
			if(mainAppCt.ReverbStep < MAX_MIC_REVB_STEP) mainAppCt.ReverbStep++;
			break;
		case MSG_USER_DOWN:
			if(mainAppCt.ReverbStep > 0) mainAppCt.ReverbStep--;
			break;
		default:
			break;
    }

//	if(mainAppCt.ReverbStep == 0){
//		gCtrlVars.reverb_unit.enable = FALSE;
//		DBG("---------> mic_reverb_gain_control_unit.enable = FALSE \n");
//		EffectUpdataMsg();
//	}else if(mainAppCt.ReverbStep == 1){
//		gCtrlVars.reverb_unit.enable = TRUE;
//		DBG("---------> mic_reverb_gain_control_unit.enable = TRUE \n");
//		EffectUpdataMsg();
//	}

	gCtrlVars.mic_reverb_gain_control_unit.gain = mainAppCt.ReverbStep * 128;

	APP_DBG("ReverbStep = %d\n", mainAppCt.ReverbStep);

//	ReverbStepSet(mainAppCt.ReverbStep);

    menutwo_updis();
}

char *get_reverb(void)
{
	APP_DBG("%s\n", __FUNCTION__);//log
	if(mainAppCt.ReverbStep == 0)
		sprintf(reverb, "OFF");
	else
		sprintf(reverb, "%d\n", mainAppCt.ReverbStep);
	return reverb;
}

//------------------闪避----------------------
char shunning[7+1] = "OFF";//-16.0ms
uint8_t user_shunning;
static void set_shunning(uint8_t a, uint16_t keyms)
{
	switch (keyms)
    {
		case MSG_USER_UP:
		case MSG_USER_DOWN:
			user_shunning = !user_shunning;
			break;
		default:
			break;
    }

//	if(gCtrlVars.ShunningMode) sprintf(shunning, "%s\n", "ON");
//	else sprintf(shunning, "%s\n", "OFF");

	APP_DBG("ShunningMode = %d\n", user_shunning);

    menutwo_updis();
}

char *get_shunning(void)
{
	APP_DBG("%s\n", __FUNCTION__);//log
	if(user_shunning) sprintf(shunning, "%s\n", "ON");
	else sprintf(shunning, "%s\n", "OFF");
	return shunning;
}
//------------------立体声----------------------
char merge[7+1] = "OFF";//-16.0ms
extern bool audio_merge;
static void set_merge(uint8_t a, uint16_t keyms)
{
	switch (keyms)
    {
		case MSG_USER_UP:
		case MSG_USER_DOWN:
			audio_merge = !audio_merge;
			break;
		default:
			break;
    }

//	if(audio_merge) sprintf(merge, "%s\n", "ON");
//	else sprintf(merge, "%s\n", "OFF");

	APP_DBG("audio_merge = %d\n", audio_merge);

    menutwo_updis();
}

static char *get_merge(void)
{
	APP_DBG("%s\n", __FUNCTION__);//log
	if(audio_merge) sprintf(merge, "%s\n", "ON");
	else sprintf(merge, "%s\n", "OFF");
	return merge;
}
//------------------contrast对比度----------------------
// 30 -   160 比较合适
uint8_t contrast_count = CONTRAST_RET;
char contrast[4+1] = "25";
static void set_contrast(uint8_t a, uint16_t keyms)
{
	switch (keyms)
    {
		case MSG_USER_UP:
			if(contrast_count < CONTRAST_MAX)	contrast_count++;
			break;
		case MSG_USER_DOWN:
			if(contrast_count > CONTRAST_MIN)	contrast_count--;
			break;
		default:
			break;
    }
//	sprintf(contrast, "%d", contrast_count);
	APP_DBG("%s = %d\n", __FUNCTION__, contrast_count*5);//log

	LCD_Contrast(contrast_count);//可设置范围 0x00~0xFF
    menutwo_updis();
}

static char *get_contrast(void)
{
	APP_DBG("%s\n", __FUNCTION__);//log
	sprintf(contrast, "%d", contrast_count);
	return contrast;
}
//------------------bright亮度----------------------
// 30 -   160 比较合适
uint8_t bright_count;
char bright[4+1] = "100%";//-16.0ms
static void set_bright(uint8_t a, uint16_t keyms)
{
	switch (keyms)
    {
		case MSG_USER_UP:
			if(bright_count < BRIGHT_MAX)	bright_count+=5;
			break;
		case MSG_USER_DOWN:
			if(bright_count > 0)	bright_count-=5;
			break;
		default:
			break;
    }
//	sprintf(bright, "%d%%", bright_count);
	APP_DBG("%s = %d\n", __FUNCTION__, bright_count);//log

	LCD_Backlight(bright_count);

    menutwo_updis();
}

static char *get_bright(void)
{
	APP_DBG("%s\n", __FUNCTION__);//log
	sprintf(bright, "%d%%", bright_count);
	return bright;
}

//------------------break----------------------
static void set_break(uint8_t a, uint16_t keyms)//退出设置模式
{
	APP_DBG("%s\n", __FUNCTION__);//log

	file_menu_clear();

	clean_menu_1();//清楚记录的信息,方便下次进入
//	LCD_Clear();
//	LCD_Refresh();
	LCD_Up_Data();
	SetMode = FALSE;
	MenuTwoSet = FALSE;
}
//-------------------------------rest-----------------------------------
#define SET_RESET_TIME  (500)
Timer SetRestTimerHander;

void SetResetTimerCb(void)
{
	APP_DBG("%s\n", __FUNCTION__);//log
	extern void NVIC_SystemReset(void);
	NVIC_SystemReset();
//	extern void ROM_SysReset(void);
//	ROM_SysReset();
}
static void reset_reset(void)
{
	APP_DBG("restrestrestrest:%s\n", __FUNCTION__);//log

	mainAppCt.EqMode = 0;
	mainAppCt.MainVolume = CFG_PARA_SYS_VOLUME_DEFAULT;
	mainAppCt.MusicVolume = CFG_PARA_SYS_VOLUME_DEFAULT;
	mainAppCt.MicVolume = 32;
	mainAppCt.MusicTrebStep = 12;
	mainAppCt.MusicBassStep = 12;
	mainAppCt.MicTrebStep = 12;
	mainAppCt.MicBassStep = 12;
	mainAppCt.EchoStep = 0;
	mainAppCt.ReverbStep = 0;
	user_shunning = 0;
	audio_merge = 0;

//	gCtrlVars.echo_unit.enable = FALSE;
//	gCtrlVars.reverb_unit.enable = FALSE;
//	EffectUpdataMsg();

	contrast_count = CONTRAST_RET;
	bright_count = 100;

#ifdef CFG_FUNC_BREAKPOINT_EN
	BackupInfoUpdata(BACKUP_SYS_INFO);
#endif

//	MessageContext	msgSend;
//	msgSend.msgId = MSG_BT_RST;
//	MessageSend(mainAppCt.msgHandle, &msgSend);

	BtTwsDeviceDisconnect();

	BtDisconnectCtrl();
//	BTHciDisconnectCmd(btManager.btDdbLastAddr);

	ClearBtManagerReg();
	BtDdb_Erase();
	BtDdb_Erase_BtConfig();
	showmain.btconnect = FALSE;//mjt

#if 1 //檫掉蓝牙名字
	//#include "bt_ddb_flash.h"
	//#include "spi_flash.h"
	//SpiFlashErase(SECTOR_ERASE, (BTDB_CONFIG_ADDR/4096), 1);
	SpiFlashErase(1, (0x1FF000/4096), 1);
#endif

	Audio_Display_Init();
	LCD_Backlight(bright_count);
	LCD_Contrast(contrast_count);//可设置范围 0x00~0xFF

#if 0//重启有噪音
	typedef void (*fun)();
	fun jump_fun;
	jump_fun = (fun)0;
	jump_fun();
	while(1);
#endif

//	software_timer_init(&SetRestTimerHander, SetResetTimerCb, SET_RESET_TIME, 0);
//	software_timer_start(&SetRestTimerHander);
//	while(1);

	set_break(0, MSG_USER_ENTER);
}

static uint8_t reset_counter = 0;//用来选择 确定 取消
static void set_reset(uint8_t a, uint16_t keyms)
{
	int i, j;
	APP_DBG("%s\n", __FUNCTION__);//log

	switch (keyms)
    {
		case MSG_USER_UP:
		case MSG_USER_DOWN:
			reset_counter++;
			break;
		case MSG_USER_ENTER:
			if(reset_counter > 0)//防止第一次确定进来的时候触发
			{
				if(reset_counter % 2)
				{
					APP_DBG("yyyyyyyyyyyyyyy\n");//log
					reset_counter = 0;
					LCD_Clear();
					LCD_Refresh();
					reset_reset();
					return;
				}
				else
				{
					APP_DBG("nnnnnnnnnnnnnnn\n");//log
					reset_counter = 0;
					Index = first10;
					menu_1(Index, 0);
					return;
				}
			}
			else
			{
				reset_counter++;
			}
			break;
		default:
			break;
    }

	MenuTwoSet = TRUE;
	/* 清除 */
	for(i = 16; i < X_col-16; i++)
	{
		for(j = 8; j < Y_col-8; j++) LCD_ClearPoint(i, j);
	}
	/* 画框 */
	LCD_DrawLine(0+16, 		8, 			X_col-16, 	8);
	LCD_DrawLine(0+16, 		Y_col-8,	X_col-16, 	Y_col-8);
	LCD_DrawLine(0+16, 		8, 			0+16, 		Y_col-8);
	LCD_DrawLine(X_col-16, 	8, 			X_col-16, 	Y_col-7);

	LCD_ShowString(16+2, 12, (uint8_t *)"confirm factory", 12, 0);
	LCD_ShowString(16+3, 12*2, (uint8_t *)"mode?", 12, 0);
	if(reset_counter % 2)
	{
		LCD_ShowString(64-36, 12*3+3, (uint8_t *)"YES", 12, 1);
		LCD_ShowString(64+24, 12*3+3, (uint8_t *)"NO", 12, 0);
	}
	else
	{
		LCD_ShowString(64-36, 12*3+3, (uint8_t *)"YES", 12, 0);
		LCD_ShowString(64+24, 12*3+3, (uint8_t *)"NO", 12, 1);
	}

	LCD_Refresh();
}
//------------------------无线话筒重新配对--------------------------------

static Timer micTimerHander;
static void micTimerCb(void)
{
	MIC_CLEAR(1);
}
static void mic_clear(void)
{
	APP_DBG("%s\n", __FUNCTION__);//log

	MIC_CLEAR(0);

	software_timer_init(&micTimerHander, micTimerCb, 50, 0);
	software_timer_start(&micTimerHander);
}

static uint8_t mic_counter = 0;//用来选择 确定 取消
static void set_mic_reset(uint8_t a, uint16_t keyms)
{
	int i, j;
	APP_DBG("%s\n", __FUNCTION__);//log

	switch (keyms)
    {
		case MSG_USER_UP:
		case MSG_USER_DOWN:
			mic_counter++;
			break;
		case MSG_USER_ENTER:
			if(mic_counter > 0)//防止第一次确定进来的时候触发
			{
				if(mic_counter % 2)
				{
					APP_DBG("yyyyyyyyyyyyyyy\n");//log
					mic_counter = 0;
					mic_clear();
					Index = first10_1;
					menu_1(Index, 0);
					return;
				}
				else
				{
					APP_DBG("nnnnnnnnnnnnnnnn\n");//log
					mic_counter = 0;
					Index = first10_1;
					menu_1(Index, 0);
					return;
				}
			}
			else
			{
				mic_counter++;
			}
			break;
		default:
			break;
    }

	MenuTwoSet = TRUE;
	/* 清除 */
	for(i = 16; i < X_col-16; i++)
	{
		for(j = 8; j < Y_col-8; j++) LCD_ClearPoint(i, j);
	}
	/* 画框 */
	LCD_DrawLine(0+16, 		8, 			X_col-16, 	8);
	LCD_DrawLine(0+16, 		Y_col-8,	X_col-16, 	Y_col-8);
	LCD_DrawLine(0+16, 		8, 			0+16, 		Y_col-8);
	LCD_DrawLine(X_col-16, 	8, 			X_col-16, 	Y_col-7);

	LCD_ShowString(16+2, 12, (uint8_t *)" Wireless mic", 12, 0);
	LCD_ShowString(16+3, 12*2, (uint8_t *)" re pairing?", 12, 0);

	if(mic_counter % 2)
	{
		LCD_ShowString(64-36, 12*3+3, (uint8_t *)"YES", 12, 1);
		LCD_ShowString(64+24, 12*3+3, (uint8_t *)"NO", 12, 0);
	}
	else
	{
		LCD_ShowString(64-36, 12*3+3, (uint8_t *)"YES", 12, 0);
		LCD_ShowString(64+24, 12*3+3, (uint8_t *)"NO", 12, 1);
	}

	LCD_Refresh();
}
//------------------------info信息-------------------------------
static void set_info(uint8_t a, uint16_t keyms)
{
	int i, j;
	APP_DBG("%s\n", __FUNCTION__);//log

	MenuTwoSet = TRUE;
	/* 清除 */
	for(i = 16; i < X_col-16; i++)
	{
		for(j = 8; j < Y_col-8; j++) LCD_ClearPoint(i, j);
	}
	/* 画框 */
	LCD_DrawLine(0+16, 		8, 			X_col-16, 	8);
	LCD_DrawLine(0+16, 		Y_col-8,	X_col-16, 	Y_col-8);
	LCD_DrawLine(0+16, 		8, 			0+16, 		Y_col-8);
	LCD_DrawLine(X_col-16, 	8, 			X_col-16, 	Y_col-7);
	/* 显示 */
	LCD_ShowString(16+12, 	16,		(uint8_t *)"   DSP   ", 16, 0);//12个字符
	//LCD_ShowString(16+8,	32,		(uint8_t *)"  V1.0.0 ", 16, 0);//12个字符
	LCD_ShowStr(16+8, 32, 16, 0, " V1.%d.%d ", CFG_SDK_MINOR_VERSION, CFG_SDK_PATCH_VERSION);

	LCD_Refresh();
}

//------------------------timer-------------------------------
#define SET_AUTO_BREAK_TIME  (10000)
Timer SetAutoBreakTimerHander;

void SetAutoBreakTimerCb(void)
{
	APP_DBG(">>%s\n", __FUNCTION__);//log
	reset_counter = 0;
	mic_counter = 0;
	if(SetMode)
	{
		set_break(0, MSG_USER_ENTER);
	}
}

void SetAutoBreak(void)
{
//	APP_DBG(">>%s\n", __FUNCTION__);//log
//	software_timer_init(&SetAutoBreakTimerHander, SetAutoBreakTimerCb, SET_AUTO_BREAK_TIME, 0);
//	software_timer_start(&SetAutoBreakTimerHander);
}

//------------------init--------------------------------
void Audio_Display_Init(void)
{
	sprintf(eqh, "%ddB", mainAppCt.MusicTrebStep-7);
	sprintf(eql, "%ddB", mainAppCt.MusicBassStep-7);
	sprintf(mich, "%ddB", mainAppCt.MicTrebStep-7);
	sprintf(micl, "%ddB", mainAppCt.MicBassStep-7);

	if(mainAppCt.EchoStep == 0) sprintf(delay, "OFF");
	else sprintf(delay, "%d\n", mainAppCt.EchoStep);

	if(user_shunning) sprintf(shunning, "%s\n", "ON");
	else sprintf(shunning, "%s\n", "OFF");

	if(audio_merge) sprintf(merge, "%s\n", "ON");
	else sprintf(merge, "%s\n", "OFF");

	LCD_Contrast(contrast_count);//可设置范围 0x00~0xFF
	sprintf(contrast, "%d", contrast_count);

	LCD_Backlight(bright_count);
	sprintf(bright, "%d%%", bright_count);

	MusicBassTrebAjust(mainAppCt.MusicBassStep, mainAppCt.MusicTrebStep);
	MicBassTrebAjust(mainAppCt.MicTrebStep, mainAppCt.MicBassStep);
	EchoStepSet(mainAppCt.EchoStep);
	gCtrlVars.mic_reverb_gain_control_unit.gain = mainAppCt.ReverbStep * 128;

	AudioMusicVolSet(mainAppCt.MusicVolume);
//	AudioMicVolDown();
}

menu.h

/*
 * menu.h
 *
 *  Created on: May 30, 2023
 *      Author: Administrator
 */

#ifndef BT_AUDIO_APP_SRC_DISPLAY_MENU_H_
#define BT_AUDIO_APP_SRC_DISPLAY_MENU_H_

#include "type.h"

#define MAX_LINE (4) //屏幕显示3行

typedef enum// 菜单索引
{
    first0,//一级菜单
    first1,//一级菜单
    first2,//一级菜单
    first3,//一级菜单
    first4,//一级菜单
    first5,//一级菜单
    first6,//一级菜单
    first7,//一级菜单
    first7_1,//一级菜单
    first7_2,//一级菜单
    first7_3,//一级菜单
	first8,//一级菜单
	first9,//一级菜单
	first10,//一级菜单
	first10_1,//一级菜单
	first11,//一级菜单
	first12,//一级菜单

    two0,//二级菜单
	two1,//二级菜单
	two2,//二级菜单
	two3,//二级菜单
	two4,//二级菜单
	two5,//二级菜单
	two6,//二级菜单
	two7,//二级菜单
	two7_1,//二级菜单
	two7_2,//二级菜单
	two7_3,//二级菜单
	two8,//二级菜单
	two9,//二级菜单
	two10,//二级菜单
	two10_1,//二级菜单
	two11,//二级菜单
	two12,//二级菜单

    MENU_NUM, // 菜单页总数
}MENU_INDEX_LIST;

typedef struct {
    uint8_t current_index;	//存放当前界面的索引号;
    uint8_t down_index;		//存放按下“down(向下)”键时需要跳转到的索引号;
    uint8_t up_index;		//存放按下“up(向上)”键时需要跳转到的索引号;
    uint8_t enter_index;	//存放按下“enter(进入)”键时需要跳转的索引号;
    //char* str;		    //存放当前索引值对应的字符串;
    char str[20];		    //存放当前索引值对应的字符串;
    void (*operate)(uint8_t, uint16_t);	//函数指针变量,存放当前索引号下需要执行的函数的入口地址。
    char *(*volue_handle)(void);			//音效对应的具体值
}KEY_INDEX_STRUCT;


typedef struct {
	uint16_t firstshow;	//第一行显示的位置
	int16_t nowmouse;	//光标显示的位置
	int16_t lastmouse;	//光标上一次显示的位置
	uint16_t nowindex;	//索引
	uint16_t lastindex;	//上次索引
}MENU_DATA_STRUCT;

/* 文件夹 */
typedef struct {
	int firstshow;	//第一行显示的位置
	int nowmouse;	//光标显示的位置
	int nowindex;	//索引
	int length;		//当前文件夹的文件个数
	int depth;		//文件夹的深度
}MENU_FOLDER_STRUCT;

extern uint8_t Index;//索引
extern bool SetMode;
extern KEY_INDEX_STRUCT Key_table[];

//-------------------------
void ADAU1701_Set_Init(void);

#define VOLUME_INIT_REST 30   //初始化 复位 后的音量 -66+33 = 33
#define VOLUME_MAX 	70//-60 --- 10
extern int8_t volume_count;
#define MODE_MAX 	4
extern int8_t mode_count;
#define LOCATION_MAX 	2
//extern int8_t location_count;
//#define EQH_MAX 	12
//extern int8_t eqh_count;
//#define EQM_MAX 	12
//extern int8_t eqm_count;
//#define EQL_MAX 	12
//extern int8_t eql_count;
//#define SUB_MAX 	5
//extern int8_t sub_count;
//#define DELAY_MAX 	160
//extern uint8_t delay_count;
#define CONTRAST_MAX 	50	//最大值
#define CONTRAST_MIN 	10	//最小值
#define CONTRAST_RET 	25 	//默认值
extern uint8_t contrast_count;
#define BRIGHT_MAX 	100
extern uint8_t user_shunning;
extern uint8_t bright_count;
//-------------------------
char *get_mode(void);
char *get_eqh(void);
char *get_eql(void);
char *get_delay(void);
char *get_shunning(void);

void SetAutoBreak(void);

#endif /* BT_AUDIO_APP_SRC_DISPLAY_MENU_H_ */

main_task.c


//各模式下的通用消息处理, 共有的提示音在此处理,因此要求调用次API前,确保APP running状态。避免解码器没准备好。
void CommonMsgProccess(uint16_t Msg)
{
	MessageContext	msgSend;
#ifdef CFG_FUNC_DISPLAY_EN
	MessageContext	msgSend;
#endif
	switch(Msg)
	{
	//---------------------------------------------mjt
//	case MSG_USER_CHECK_MIC1:
//		if(MIC1_READ()) showmain.mic1 = TRUE;
//		else showmain.mic1 = FALSE;
//		//LCD_Up_Data();//100MS刷新
//		APP_DBG("showmain.mic1 = %d\n", showmain.mic1);
//		break;
//	case MSG_USER_CHECK_MIC2:
//		if(MIC2_READ()) showmain.mic2 = TRUE;
//		else showmain.mic2 = FALSE;
//		//LCD_Up_Data();//100MS刷新
//		APP_DBG("showmain.mic2 = %d\n", showmain.mic2);
//		break;
	case MSG_USER_UP:
		//APP_DBG("MSG_USER_UP\n");
		if(SetMode)
		{
			if(IsTimeOut(&menuTimer) || IsTimeOut(&menuTimer))//IsTimeOut函数需要先检测一次才触发,所以这里判断两次
			{
				SetAutoBreak();
				Index = Key_table[Index].down_index;
				(Key_table[Index].operate)(Index, Msg);//更新显示
				TimeOutSet(&menuTimer, MENU_TIMER_OUT);
			}
		}
		else
		{
			if(IsTimeOut(&menuTimer) || IsTimeOut(&menuTimer))//IsTimeOut函数需要先检测一次才触发,所以这里判断两次
			{
//				MainVolUp();
				AudioMusicVolUp();
//				AudioMicVolUp();

				LCD_Up_Data();
				TimeOutSet(&menuTimer, MENU_TIMER_OUT);
			}
		}
		break;
	case MSG_USER_DOWN:
		//APP_DBG("MSG_USER_DOWN\n");
		if(SetMode)
		{
			if(IsTimeOut(&menuTimer) || IsTimeOut(&menuTimer))//IsTimeOut函数需要先检测一次才触发,所以这里判断两次
			{
				SetAutoBreak();
				Index = Key_table[Index].up_index;
				(Key_table[Index].operate)(Index, Msg);//更新显示
				TimeOutSet(&menuTimer, MENU_TIMER_OUT);
			}
		}
		else
		{
			if(IsTimeOut(&menuTimer) || IsTimeOut(&menuTimer))//IsTimeOut函数需要先检测一次才触发,所以这里判断两次
			{
//				MainVolDown();
				AudioMusicVolDown();
//				AudioMicVolDown();

				LCD_Up_Data();
				TimeOutSet(&menuTimer, MENU_TIMER_OUT);
			}
		}
		break;
	case MSG_USER_ENTER:
		//APP_DBG("MSG_USER_ENTER\n");
		if(SetMode)//是否在设置模式
		{
			if(IsTimeOut(&menuTimer) || IsTimeOut(&menuTimer))//IsTimeOut函数需要先检测一次才触发,所以这里判断两次
			{
				SetAutoBreak();
				Index = Key_table[Index].enter_index;
				(Key_table[Index].operate)(Index, Msg);//更新显示
				TimeOutSet(&menuTimer, MENU_TIMER_OUT);
			}
		}
		else
		{
			SetAutoBreak();
			SetMode = TRUE;
			Index = 0;//从第0个开始显示
			(Key_table[Index].operate)(Index, Msg);//更新显示
		}
		break;
//---------------------------------------------
        case MSG_MENU://菜单键
            APP_DBG("menu key\n");
            AudioPlayerMenu();
            break;
    }
}

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值