/****************************************************************************************************
* created by sunpeng 2017 all rights reserved!
****************************************************************************************************/

/* Includes ------------------------------------------------------------------*/
#include "include.h"
#include "delay.h"
#include "nrf_gpio.h"
#include "beep.h"
#include "Timer.h"

#if HW_VERSION == HW_VERSION_BC4J_V10
#include "nrf_delay.h"
#endif

/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
uint32_t ring_times_remain = 0;   		//蜂鸣器鸣响次数
#if HW_VOICE_TYPE == HW_VOICE_TYPE_SPEAKER
uint8_t g_jqsw_send_en_flag = false;		//单线协议发送使能标志
uint16_t g_notice_step_time_count = 0;	//提示音当前步骤计时 准备8*250us  数据长6*250us  数据短2*250us

JQSW_DATA_STEP_ENUM g_jqsw_step = JQSW_DATA_STEP_MIN;		//JQ8400 单线协议当前步骤

DATA_RECEIVE_VIA_NET_STRUCT JQCmdQue;

JQSW_DATA_SEND_CONTROL_STRUCT jqsw_ds_control;		//JQ单线协议发送数据控制

#endif

#define  ring_period_max  	50			//蜂鸣器半个周期翻转次数最大值
uint32_t ring_period_cnt = 0;   		//蜂鸣器鸣响周期计数
uint8_t  ring_period_status = 0;		//蜂鸣器翻转状态  1=鸣响阶段  0=停止鸣响阶段
uint8_t  beep_enable_Flag = true;		//使能蜂鸣器

/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/

//初始化蜂鸣器
void init_beep(void)
{
    //配置6个普通功能按钮输入
    nrf_gpio_cfg_output(BELL_PIN);
#if HW_VOICE_TYPE == HW_VOICE_TYPE_SPEAKER
	InitRollQueue(&JQCmdQue);
	init_dsc_offset(&jqsw_ds_control);
	nrf_gpio_pin_set(BELL_PIN);
#else
	nrf_gpio_pin_clear(BELL_PIN);
#endif
	
	ring_times_remain = 0;
	ring_period_cnt = 0;
	ring_period_status = 0;
	
#if ARCH_MODE == NRF51802_Peripheral_Mode
#else	
	init_beep_timer();		//初始化蜂鸣器专用定时器
#endif	
#if HW_VOICE_TYPE == HW_VOICE_TYPE_SPEAKER
	JQSW_SendCmd(JQSW_CMD_SelectFlash);
	JQSW_SetVolumn(SPEAKER_VOLUMN_MAX/3);		//设置扬声器声音到最大 SPEAKER_VOLUMN_MAX
	//JQSW_SendCmd(JQSW_CMD_Sleep);		//进入节电模式
#endif

}


//开始播放开机欢迎语音
void broadBootWelcomeVoice_timeout_cb(u16 timer_id, u16 times_count)
{
#if HW_VOICE_TYPE == HW_VOICE_TYPE_SPEAKER
//	ring_notice(MUSIC_NOTICE_TYPE_1, 1);  		//开机欢迎语音
#else
//	ring_notice(MUSIC_NOTICE_TYPE_fresh_start, 4);	//开机欢迎语音
#endif
}

//开启开机欢迎语音定时器
void start_BroadBootWelcomeVoice_timer(void)
{
	//开启开启开机欢迎语音定时器，4秒后提示
	start_callback_timer(4, CB_TIMER_ID_Misc, CB_TIMER_TYPE_Once, 1, broadBootWelcomeVoice_timeout_cb);
}

//允许蜂鸣器发声
void enable_ring(void)
{
	beep_enable_Flag = true;
#if HW_VOICE_TYPE == HW_VOICE_TYPE_SPEAKER
	nrf_gpio_pin_set(BELL_PIN);
#else
	nrf_gpio_pin_clear(BELL_PIN);
#endif
	enable_beep_timer();
}

//禁止蜂鸣器发声
void disable_ring(void)
{
	beep_enable_Flag = false;
#if HW_VOICE_TYPE == HW_VOICE_TYPE_SPEAKER
	nrf_gpio_pin_set(BELL_PIN);
#else
	nrf_gpio_pin_clear(BELL_PIN);
#endif
	disable_beep_timer();
}

//蜂鸣器发声 按次
//times		:	发声次数
void set_beep_times(uint16_t times)
{
	ring_times_remain = times;
}

#if HW_VOICE_TYPE == HW_VOICE_TYPE_SPEAKER
//发送到JQ8400上控制数据
void JQSW_SendData(uint8_t data)
{
	PutRollQueue(&JQCmdQue, &data, 1); 
}

//发送到JQ8400上控制指令
void JQSW_SendCmd(JQSW_CMD_ENUM cmd)
{
	JQSW_SendData((uint8_t)cmd); 
}

//发送最多5位数字到音乐模块
void JQSW_Send5BitNumberData(uint16_t data)
{
	if((data/10000) > 0)
	{
		JQSW_SendData(data/10000);
		data = data % 10000;
	}
	if((data/1000) > 0)
	{
		JQSW_SendData(data/1000);
		data = data % 1000;
	}
	if((data/100) > 0)
	{
		JQSW_SendData(data/100);
		data = data % 100;
	}
	if((data/10) > 0)
	{
		JQSW_SendData(data/10);
		data = data % 10;
	}
	
	JQSW_SendData(data);
}

//设置音乐模块音量
uint8_t JQSW_SetVolumn(uint8_t volumn)
{
	/**/
	if(volumn > 100)
	{
		return false;
	}
	
	JQSW_SendCmd(JQSW_CMD_ClearNumber);
	JQSW_Send5BitNumberData(volumn);
	JQSW_SendCmd(JQSW_CMD_SetVolumn);
	
	return true;
}

//生成并存储音乐模块发声指令
void generate_and_store_voice_cmd(MUSIC_NOTICE_TYPE_ENUM n_type)
{	
	JQSW_SendCmd(JQSW_CMD_Stop);
	JQSW_SendCmd(JQSW_CMD_ClearNumber);
	JQSW_Send5BitNumberData((uint16_t)n_type);
	JQSW_SendCmd(JQSW_CMD_SelectMusicAck);
	
	//设置准备开始传输指令
	g_jqsw_step = JQSW_DATA_STEP_START;
	g_jqsw_send_en_flag = true;
}

//多次发声全局存储声音类型
MUSIC_NOTICE_TYPE_ENUM multi_times_notice_type = MUSIC_NOTICE_TYPE_MIN;

//音乐模块发声超时，进入低功耗模式
void JQSW_speak_timeout_cb(u16 timer_id, u16 times_count)
{
	//扬声器超时进入低功耗模式
	JQSW_SendCmd(JQSW_CMD_Sleep);
	
	//多次发声
	if(times_count > 1)
	{
		generate_and_store_voice_cmd(multi_times_notice_type);
	}
}

//下发音乐模块发声任务
void set_speaker_task(MUSIC_NOTICE_TYPE_ENUM n_type, uint16_t times)
{	
	if(0 == times)
	{
		return;
	}
	
	if(times > 1)
	{
		multi_times_notice_type = n_type;
	}
	
	generate_and_store_voice_cmd(n_type);
	//开启定时3*times秒，定时进入低功耗模式
	start_callback_timer(5, CB_TIMER_ID_Misc, CB_TIMER_TYPE_Many, times, JQSW_speak_timeout_cb);

}

#else

//设置蜂鸣器周期及发声次数
//period	:	蜂鸣器周期
//times		:	提示次数
void set_beep_period_and_times(uint32_t period, uint16_t times)
{
	set_beep_timer_period(period);
	set_beep_times(times);
#if HW_VERSION == HW_VERSION_BC4J_V10
	nrf_gpio_pin_set(BELL_PIN);
#else
#endif
}

#endif

//响指定提示音
//n_type	:	提示音种类
//times		:	提示次数
void ring_notice(MUSIC_NOTICE_TYPE_ENUM n_type, uint16_t times)
{
	switch(n_type)
	{
#if HW_VOICE_TYPE == HW_VOICE_TYPE_BEEP
		case MUSIC_NOTICE_TYPE_fresh_start:
			set_beep_period_and_times(2200, times);	//3000
			break;
		case MUSIC_NOTICE_TYPE_step_failed:
			set_beep_period_and_times(850, times);	//850
			break;
		case MUSIC_NOTICE_TYPE_all_ok:
			set_beep_period_and_times(2600, times);	//2600
			break;
#endif
		
		case MUSIC_NOTICE_TYPE_step_ok:
#if HW_VOICE_TYPE == HW_VOICE_TYPE_SPEAKER
			set_speaker_task(MUSIC_NOTICE_TYPE_36, times);
#else
			set_beep_period_and_times(200, times);	//200
#endif
			break;
		case MUSIC_NOTICE_TYPE_game_over:
#if HW_VOICE_TYPE == HW_VOICE_TYPE_SPEAKER
			set_speaker_task(MUSIC_NOTICE_TYPE_7, times);
#else
			set_beep_period_and_times(1500, times);	//1500
#endif
			break;
		
#if HW_VOICE_TYPE == HW_VOICE_TYPE_SPEAKER
		case MUSIC_NOTICE_TYPE_1 : set_speaker_task(n_type, times); break;
		case MUSIC_NOTICE_TYPE_2 : 
			if(true == isAllowSystemOff_EN_Flag)		//允许关机
			{
				set_speaker_task(n_type, times); 	//关机提示音
			}
			break;
		case MUSIC_NOTICE_TYPE_3 : set_speaker_task(n_type, times); 
			if(true == isAllowSystemOff_EN_Flag)		//允许关机
			{
				set_speaker_task(n_type, times); 	//关机提示音
			}
			break;
		case MUSIC_NOTICE_TYPE_4 : set_speaker_task(n_type, times); break;
		case MUSIC_NOTICE_TYPE_5 : set_speaker_task(n_type, times); break;
		case MUSIC_NOTICE_TYPE_6 : set_speaker_task(n_type, times); break;
	    case MUSIC_NOTICE_TYPE_7 : set_speaker_task(n_type, times); break;
		case MUSIC_NOTICE_TYPE_8 : set_speaker_task(n_type, times); break;
		case MUSIC_NOTICE_TYPE_9 : set_speaker_task(n_type, times); break;
		case MUSIC_NOTICE_TYPE_10: set_speaker_task(n_type, times); break;
		case MUSIC_NOTICE_TYPE_11: set_speaker_task(n_type, times); break;
		case MUSIC_NOTICE_TYPE_12: set_speaker_task(n_type, times); break;
		case MUSIC_NOTICE_TYPE_13: set_speaker_task(n_type, times); break;
		case MUSIC_NOTICE_TYPE_14: set_speaker_task(n_type, times); break;
		case MUSIC_NOTICE_TYPE_15: set_speaker_task(n_type, times); break;
		case MUSIC_NOTICE_TYPE_16: set_speaker_task(n_type, times); break;
		case MUSIC_NOTICE_TYPE_17: set_speaker_task(n_type, times); break;
		case MUSIC_NOTICE_TYPE_18: set_speaker_task(n_type, times); break;
		case MUSIC_NOTICE_TYPE_19: set_speaker_task(n_type, times); break;
		case MUSIC_NOTICE_TYPE_20: set_speaker_task(n_type, times); break;
		case MUSIC_NOTICE_TYPE_21: set_speaker_task(n_type, times); break;
		case MUSIC_NOTICE_TYPE_22: set_speaker_task(n_type, times); break;
		case MUSIC_NOTICE_TYPE_23: set_speaker_task(n_type, times); break;
		case MUSIC_NOTICE_TYPE_24: set_speaker_task(n_type, times); break;
		case MUSIC_NOTICE_TYPE_25: set_speaker_task(n_type, times); break;
		case MUSIC_NOTICE_TYPE_26: set_speaker_task(n_type, times); break;
		case MUSIC_NOTICE_TYPE_27: set_speaker_task(n_type, times); break;
		case MUSIC_NOTICE_TYPE_28: set_speaker_task(n_type, times); break;
		case MUSIC_NOTICE_TYPE_29: set_speaker_task(n_type, times); break;
		case MUSIC_NOTICE_TYPE_30: set_speaker_task(n_type, times); break;
	    case MUSIC_NOTICE_TYPE_31: set_speaker_task(n_type, times); break;
		case MUSIC_NOTICE_TYPE_32: set_speaker_task(n_type, times); break;
		case MUSIC_NOTICE_TYPE_33: set_speaker_task(n_type, times); break;
		case MUSIC_NOTICE_TYPE_34: set_speaker_task(n_type, times); break;
		case MUSIC_NOTICE_TYPE_35: set_speaker_task(n_type, times); break;
#endif
		default:
			break;
	}
}

#if HW_VOICE_TYPE == HW_VOICE_TYPE_SPEAKER
//初始化数据发送控制数据结构
uint8_t init_dsc_offset(JQSW_DATA_SEND_CONTROL_STRUCT *dsc)
{
	dsc->bit_offset = 0;
	dsc->bit_to_send = 0x0;
	dsc->byte_to_send = 0x00;
	return true;
}

//后移数据发送控制数据结构一位
uint8_t shift_dsc_offset(JQSW_DATA_SEND_CONTROL_STRUCT *dsc)
{
	if(dsc->bit_offset > 8)
	{
		return false;
	}
	dsc->bit_offset++;
	dsc->bit_to_send = (dsc->byte_to_send >> (dsc->bit_offset-1)) & 0x01;
	return true;
}

//获取数据发送控制数据当前发送的bit
uint8_t get_dsc_bit_to_send(JQSW_DATA_SEND_CONTROL_STRUCT *dsc)
{
	return dsc->bit_to_send;
}

//获取数据发送控制数据当前发送的bit所在byte中的位置 offset
uint8_t get_dsc_bit_offset(JQSW_DATA_SEND_CONTROL_STRUCT *dsc)
{
	return dsc->bit_offset;
}

//u8 beep_toggle_flag = false;
#endif

//蜂鸣器定时检查及发声
void ring_beep_cycle(void)
{
	if(true == beep_enable_Flag)
	{
#if HW_VOICE_TYPE == HW_VOICE_TYPE_SPEAKER
		uint8_t is_waitting_flag = false;
		
		if(false == g_jqsw_send_en_flag)
		{
			return;
		}
		
		switch(g_jqsw_step)
		{
			case JQSW_DATA_STEP_START:		//开始信号，下降沿
				init_dsc_offset(&jqsw_ds_control);
				if(false == GetRollQueue(&JQCmdQue, &jqsw_ds_control.byte_to_send))
				{
					return;
				}
				nrf_gpio_pin_clear(BELL_PIN);
				g_notice_step_time_count = 16;		//引导码延时要求大于 2MS，建议采用 4MS 延时
				break;
			case JQSW_DATA_STEP_START_WAITTING:
				is_waitting_flag = true;
				break;
			case JQSW_DATA_STEP_DATA_BIT_FIRST:			
				nrf_gpio_pin_set(BELL_PIN);
				shift_dsc_offset(&jqsw_ds_control);
				if(1 == get_dsc_bit_to_send(&jqsw_ds_control))		//数据位为1 ， 则 高电平/低电平=3/1， 反之为1/3
				{
					g_notice_step_time_count = 6;
				}
				else
				{
					g_notice_step_time_count = 2;
				}
				break;
			case JQSW_DATA_STEP_DATA_BIT_FIRST_WAITTING:
				is_waitting_flag = true;
				break;
			case JQSW_DATA_STEP_DATA_BIT_LAST:
				nrf_gpio_pin_clear(BELL_PIN);
				if(1 == get_dsc_bit_to_send(&jqsw_ds_control))		//数据位为1 ， 则 高电平/低电平=3/1， 反之为1/3
				{
					g_notice_step_time_count = 2;
				}
				else
				{
					g_notice_step_time_count = 6;
				}
				break;
			case JQSW_DATA_STEP_DATA_BIT_LAST_WAITTING:
				is_waitting_flag = true;
				break;
			case JQSW_DATA_STEP_STOP:
				nrf_gpio_pin_set(BELL_PIN);
				g_notice_step_time_count = 40;		//两个字节之间延时建议在 10MS 以上
				break;
			case JQSW_DATA_STEP_STOP_WAITTING:
				is_waitting_flag = true;
				break;
			default:
				break;
		}
		
		if(true == is_waitting_flag)
		{
			g_notice_step_time_count--;
			if(0 == g_notice_step_time_count)
			{
				switch(g_jqsw_step)
				{
					case JQSW_DATA_STEP_DATA_BIT_LAST_WAITTING:
						if(get_dsc_bit_offset(&jqsw_ds_control) >= 8)
						{
							g_jqsw_step = JQSW_DATA_STEP_STOP;			//本字节所有位发送完成，调到结束
						}
						else
						{
							g_jqsw_step = JQSW_DATA_STEP_DATA_BIT_FIRST;	//继续发送剩余bit
						}
						break;
					case JQSW_DATA_STEP_STOP_WAITTING:
						if(GetRollQueueLen(&JQCmdQue) > 0)
						{
							g_jqsw_step = JQSW_DATA_STEP_START;
						}
						else
						{
							g_jqsw_step = JQSW_DATA_STEP_STOP;
							g_jqsw_send_en_flag = false;		//数据全部发送完成，禁止发送使能标志
						}
		
						break;
					default:
						g_jqsw_step++;
						break;
				}
			}
		}
		else
		{
			g_jqsw_step++;
		}
		
#else		
		ring_period_cnt++;
		/**/
		if(ring_period_cnt > ring_period_max)
		{
			ring_period_cnt = 0;
			if(1 == ring_period_status)
			{
				ring_period_status = 0;
				if(ring_times_remain > 0)
				{
					ring_times_remain--;
				}
				else
				{
#if HW_VERSION == HW_VERSION_BC4J_V10
					nrf_gpio_pin_clear(BELL_PIN);
#endif
					//beep_enable_Flag = false;
					disable_beep_timer();
				}
#if HW_VERSION != HW_VERSION_BC4J_V10
				nrf_gpio_pin_clear(BELL_PIN);
#endif
			}
			else
			{
				ring_period_status = 1;
			}
		}
		if(ring_times_remain > 0)
		{
			if(1 == ring_period_status)
			{
#if HW_VERSION != HW_VERSION_BC4J_V10
				nrf_gpio_pin_toggle(BELL_PIN);
#endif
			}
		}
#endif
	}	
}

#if HW_VOICE_TYPE == HW_VOICE_TYPE_SPEAKER
//定时检测是否需要将扬声器声音设置小于30%，以节省电量
void cycleCheckSetSpeakerVoiceLower(void)
{
	if(true == setSpeakerVoiceLower.isTrigedOnceFlag)
	{
		return;
	}
	if(true == setSpeakerVoiceLower.flag)
	{
		//设置扬声器声音小于30%，以节省电量
		JQSW_SetVolumn(SPEAKER_VOLUMN_MAX/5);
		setSpeakerVoiceLower.isTrigedOnceFlag = true;
	}
}
#endif

uint32_t set_period_cnt = 10;
//测试蜂鸣器
void test_beep(void)
{
#if HW_VOICE_TYPE == HW_VOICE_TYPE_SPEAKER
	
#else
	set_beep_period_and_times(set_period_cnt*100, 7);
#endif
	set_period_cnt++;
	if(set_period_cnt > 30)
	{
		set_period_cnt = 0;
	}
}
	

/*********************************************end of file*********************************************/

