//------------------------------------------------------------------------------
// 模块名称：main
// 文件名称：main
// 版本名称：V1.0
// 文件说明：旋转样品杆主文件
// 日期时间：2018年8月16日21点38分
// 文件作者：Jackie Chan
// 修改记录：
//    版本号  日期        作者  说明
//    V1.0    2018.08.16  J.C   正式发布
//
// 公司名称：多场低温科技有限公司
//
//------------------------------------------------------------------------------

#include "bsp.h"    /* 底层硬件驱动 */
uint8_t Flag_100ms = 0;
extern DIGITIAL_TUBE_T g_tTube;
extern MOTO_T g_tMoto;
#define IS_ZERO_BUF_VALID()  (g_RxBuf[1]=='z' && \
                              g_RxBuf[2]==',' && g_RxBuf[4]==',' && \
                             (g_RxBuf[3]=='1' || g_RxBuf[3]=='0'))
#define IS_MF_VALID  (g_RxBuf[1]=='M' && g_RxBuf[2]=='F')
static void Delay_ms(uint16_t us)
{
	uint16_t i;

	/*　
		CPU主频168MHz时，在内部Flash运行, MDK工程不优化。用台式示波器观测波形。
		循环次数为5时，SCL频率 = 1.78MHz (读耗时: 92ms, 读写正常，但是用示波器探头碰上就读写失败。时序接近临界)
		循环次数为10时，SCL频率 = 1.1MHz (读耗时: 138ms, 读速度: 118724B/s)
		循环次数为30时，SCL频率 = 440KHz， SCL高电平时间1.0us，SCL低电平时间1.2us

		上拉电阻选择2.2K欧时，SCL上升沿时间约0.5us，如果选4.7K欧，则上升沿约1us

		实际应用选择400KHz左右的速率即可
	*/
	for (i = 0; i < (300*us); i++);
}
void key1_long_task(void);
void key1_task(void);
void key2_task(void);
void uart_msg_idle(void);
// #include "bsp_adc.h"
// #include "delay.h"
		   
//初始化ADC
//这里我们仅以规则通道为例
//我们默认将开启通道0~3																	   
void  Adc_Init(void)
{ 	
	ADC_InitTypeDef ADC_InitStructure; 
	GPIO_InitTypeDef GPIO_InitStructure;

	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA |RCC_APB2Periph_ADC1, ENABLE );	  //使能ADC1通道时钟
 

	RCC_ADCCLKConfig(RCC_PCLK2_Div6);   //设置ADC分频因子6 72M/6=12,ADC最大时间不能超过14M

	//PA1 作为模拟通道输入引脚                         
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1|GPIO_Pin_2;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;		//模拟输入引脚
	GPIO_Init(GPIOA, &GPIO_InitStructure);	

	ADC_DeInit(ADC1);  //复位ADC1,将外设 ADC1 的全部寄存器重设为缺省值

	ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;	//ADC工作模式:ADC1和ADC2工作在独立模式
	ADC_InitStructure.ADC_ScanConvMode = DISABLE;	//模数转换工作在单通道模式
	ADC_InitStructure.ADC_ContinuousConvMode = DISABLE;	//模数转换工作在单次转换模式
	ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;	//转换由软件而不是外部触发启动
	ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;	//ADC数据右对齐
	ADC_InitStructure.ADC_NbrOfChannel = 1;	//顺序进行规则转换的ADC通道的数目
	ADC_Init(ADC1, &ADC_InitStructure);	//根据ADC_InitStruct中指定的参数初始化外设ADCx的寄存器   

  
	ADC_Cmd(ADC1, ENABLE);	//使能指定的ADC1
	
	ADC_ResetCalibration(ADC1);	//使能复位校准  
	 
	while(ADC_GetResetCalibrationStatus(ADC1));	//等待复位校准结束
	
	ADC_StartCalibration(ADC1);	 //开启AD校准
 
	while(ADC_GetCalibrationStatus(ADC1));	 //等待校准结束
 
//	ADC_SoftwareStartConvCmd(ADC1, ENABLE);		//使能指定的ADC1的软件转换启动功能

}				  
//获得ADC值
//ch:通道值 0~3  ADC_Channel_1
u16 Get_Adc(u8 ch)   
{
  	//设置指定ADC的规则组通道，一个序列，采样时间
	ADC_RegularChannelConfig(ADC1, ch, 1, ADC_SampleTime_239Cycles5 );	//ADC1,ADC通道,采样时间为239.5周期	  			    
  
	ADC_SoftwareStartConvCmd(ADC1, ENABLE);		//使能指定的ADC1的软件转换启动功能	
	 
	while(!ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC ));//等待转换结束

	return ADC_GetConversionValue(ADC1);	//返回最近一次ADC1规则组的转换结果
}

u16 Get_Adc_Average(u8 ch,u8 times)
{
	u32 temp_val=0;
	u8 t;
	for(t=0;t<times;t++)
	{
		temp_val+=Get_Adc(ch);
		Delay_ms(5);
	}
	return temp_val/times;
}

u16 get_key4_adc(void)
{
	u16 key4_adc = 0;
	u16 ad_value;
	
	ad_value = Get_Adc_Average(ADC_Channel_1,10);
		
//	electric_quantity_percent = ((ad_value*3.3/4096.0)-1.846)*100/0.52;
//	key4_adc = (ad_value*3.3/4096.0);
	
	key4_adc = ad_value;
	if(key4_adc > 2100)
	{
		key4_adc = 2;//前进
	}
	else if(key4_adc <= 1100)
	{
		key4_adc = 1;//后退
	}
	else if((key4_adc > 1100)&&(key4_adc <= 2100))
	{
	  key4_adc = 0;//后退
	}
	return key4_adc;
}
u16 get_key5_adc(void)
{
	u16 key5_adc = 0;
	u16 ad_value;
	
	ad_value = Get_Adc_Average(ADC_Channel_2,10);
		
//	electric_quantity_percent = ((ad_value*3.3/4096.0)-1.846)*100/0.52;
	key5_adc = (ad_value*3.3/4096.0);
	
	if(key5_adc >= 2800)
	{
		key5_adc = 1;//前进
	}
	else if(key5_adc <= 600)
	{
		key5_adc = 2;//后退
	}
	else if((key5_adc > 600)&&(key5_adc < 2800))
	{
	  key5_adc = 0;//后退
	}
	return key5_adc;
}

void motor_dir(uint32_t freq, uint8_t _dir, int32_t _stpes) 
{
      // [r,1,1500,108288]
//      freq = get_run_freq();
//      pulse = get_pulse();
  if(g_tTube.state == WORK)
  {	
	 if(_dir == 1)
      {
        _dir = 1;
				 g_tMoto.sv_pulse = g_tMoto.sv_pulse+100;
      }
      else if(_dir == 0)
      {
        _dir = 0;
        g_tMoto.sv_pulse = g_tMoto.sv_pulse-100;
      }  
      
      if(g_tMoto.pv_pulse<g_tMoto.sv_pulse)
			{
				if (g_tMoto.sv_pulse > 55600)
				{
					g_tMoto.sv_pulse = 55600;
				}
				else if(g_tMoto.sv_pulse <= 55600)
				{	
           MOTO_Start(freq, 0, 100); 
				}					
      }
      else if(g_tMoto.pv_pulse>g_tMoto.sv_pulse)
      {
       if (g_tMoto.sv_pulse < -1600)
				{
					g_tMoto.sv_pulse = -1600;
				}
				else if(g_tMoto.sv_pulse >= -1600)
				{	
           MOTO_Start(freq, 1, 100);
				}					
      }
		}
}
int main(void)
{
  uint8_t ucKeyCode;	
  uint32_t freq = 1500;
	uint16_t motor_move1 = 0;
	uint16_t motor_move2 = 0;
  bsp_Init(); /* 硬件初始化 */
  Adc_Init(); //ADC初始化
  BEEP_Start(freq, 20, 1, 1);
	
	 //g_tTube.state = WORK;
   // MOTO_Stop();
    //g_tMoto.CurrentStep = 0;

  /* 主程序大循环 */
  while (1)
  {
    bsp_Idle(); /* CPU空闲时执行的函数，在 bsp.c */
    uart_msg_idle();
     if(Flag_100ms == 1)
		 {
				Flag_100ms = 0;
			  motor_move1 = get_key4_adc();
			  motor_move2 = get_key5_adc();
			  if(motor_move1 == 1)//key4
				{
						motor_move1 = 0;
					//前进
					motor_dir(1500, 0, 3000);
				}
				else  if(motor_move1 == 2)
				{
					motor_move1 = 0;
					//后退
					motor_dir(1500, 1, 3000);
				}
		 }			 
    /* 处理按键事件 */
    ucKeyCode = bsp_GetKey();
    
    if (ucKeyCode > 0)
    {
      /* 有键按下 */
      switch (ucKeyCode)//key6
      {
        case KEY_DOWN_K6: //key6 短按
        {
          BEEP_KeyTone();       // 按键提示音
           key1_long_task(); // 短按按键一仅用来切换数码管显示角度还是脉冲数
          break;  
        }
        
        case KEY_DOWN_K1:  //Key1 短按
        {
          BEEP_KeyTone();       // 按键提示音
           bsp_ToogleDispMode();          // K1按键用来做零点搜索时候的限位
          break;	
        }
				 case KEY_DOWN_K2:  //Key2 短按
        {
          BEEP_KeyTone();       // 按键提示音
 
          key2_task();          // K2按键用来做零点搜索时候的限位
          break;						
        }
        
       
        case KEY_LONG_K1://
        {
          //BEEP_Start(freq, 5, 5, 3);  // 长按K1发出三声嘀嘀声
          key1_long_task();                // 
          break;
        }     
 
				 
     
        default:
          break;
      }
    }
    
  }
}

void key1_long_task(void)
{                              // 转速：10度每秒
 if(IsKeyDown2())
  {
    BEEP_Start(1500, 5, 5, 3); 
   	                         // 如果已经在零点了，发出提醒，不转动，位置归零
  }
  if(g_tTube.state == IDLE)
  {
    g_tTube.state = SEARCH; // 上电后，长按K1进入搜索零点模式
    if(g_tTube.disp_mode == MODE_PULSE)
    {
      bsp_drv8880_config_dir(DIR_CW);
      MOTO_Start(1504, 1, 67680); // 67680个脉冲，无限位防护最大旋转1.25圈
    }                             // 转速：10度每秒
    else if(g_tTube.disp_mode == MODE_ANGLE)
    {
      bsp_drv8880_config_dir(DIR_CCW);
      MOTO_Start(1504,1, 67680); // 67680个脉冲，无限位防护最大旋转1.25圈
    }
	}
 else if(g_tTube.state == WORK &&  g_tMoto.CurrentStep != 0)
	 {
    g_tTube.state = SEARCH; // 上电后，长按K1进入搜索零点模式
    if(g_tTube.disp_mode == MODE_PULSE)
    {
      bsp_drv8880_config_dir(DIR_CW);
      MOTO_Start(1504, 1, 67680); // 67680个脉冲，无限位防护最大旋转1.25圈
    }                             // 转速：10度每秒
    else if(g_tTube.disp_mode == MODE_ANGLE)
    {
      bsp_drv8880_config_dir(DIR_CCW);
      MOTO_Start(1504,1, 67680); // 67680个脉冲，无限位防护最大旋转1.25圈
    }
	}
  // 转速：10度每秒
}

void key2_task(void)
{
  DISABLE_INT();
  if(g_tTube.state == SEARCH)
  {
    g_tTube.state = WORK;
    MOTO_Stop();
    g_tMoto.CurrentStep = 0;
  }
  ENABLE_INT();
}

uint32_t get_run_freq(void) // [r,1,1500,108288]
{
  uint32_t i=0;
  i += (g_RxBuf[5]-'0')*1000;
  i += (g_RxBuf[6]-'0')*100;
  i += (g_RxBuf[7]-'0')*10;
  i += (g_RxBuf[8]-'0')*1;
  return i;
}

uint32_t get_zero_freq(void)  // [z,1,1500]
{
  uint32_t i=0;
  i += (g_RxBuf[5]-'0')*1000;
  i += (g_RxBuf[6]-'0')*100;
  i += (g_RxBuf[7]-'0')*10;
  i += (g_RxBuf[8]-'0')*1;
  return i;
}

uint32_t get_pulse(void)
{
  uint32_t i=0;
  i += (g_RxBuf[10]-'0')*100000;
  i += (g_RxBuf[11]-'0')*10000;
  i += (g_RxBuf[12]-'0')*1000;
  i += (g_RxBuf[13]-'0')*100;
  i += (g_RxBuf[14]-'0')*10;
  i += (g_RxBuf[15]-'0')*1;
  return i;
}

void search_zero(uint8_t dir,uint32_t freq)
{
  if(g_tMoto.Running == 1) // 如果电机在运动中，先停止电机
  {
    MOTO_Stop();
  }
  
                               // 转速：10度每秒
 if(IsKeyDown2())
  {
    BEEP_Start(1500, 5, 5, 3); 
   	                         // 如果已经在零点了，发出提醒，不转动，位置归零
  }
  if(g_tTube.state == IDLE)
  {
    g_tTube.state = SEARCH; // 上电后，长按K1进入搜索零点模式
    if(g_tTube.disp_mode == MODE_PULSE)
    {
      bsp_drv8880_config_dir(DIR_CW);
      MOTO_Start(1504, 1, 67680); // 67680个脉冲，无限位防护最大旋转1.25圈
    }                             // 转速：10度每秒
    else if(g_tTube.disp_mode == MODE_ANGLE)
    {
      bsp_drv8880_config_dir(DIR_CCW);
      MOTO_Start(1504,1, 67680); // 67680个脉冲，无限位防护最大旋转1.25圈
    }
	}
 else if(g_tTube.state == WORK &&  g_tMoto.CurrentStep != 0)
	 {
    g_tTube.state = SEARCH; // 上电后，长按K1进入搜索零点模式
    if(g_tTube.disp_mode == MODE_PULSE)
    {
      bsp_drv8880_config_dir(DIR_CW);
      MOTO_Start(1504, 1, 67680); // 67680个脉冲，无限位防护最大旋转1.25圈
    }                             // 转速：10度每秒
    else if(g_tTube.disp_mode == MODE_ANGLE)
    {
      bsp_drv8880_config_dir(DIR_CCW);
      MOTO_Start(1504,1, 67680); // 67680个脉冲，无限位防护最大旋转1.25圈
    }
	}
  // 转速：10度每秒

}




void send_sv_2_uart(void)
{
  if(g_tMoto.pv_pulse>=0)
  {
    printf("[w,1,%06d]",g_tMoto.pv_pulse);
  }
  else
  {
    printf("[w,0,%06d]",-g_tMoto.pv_pulse);
  }
}

void print_sys_info(void)
{
  printf("\r\n");
  printf("----------------------------->\r\n");
  printf("-> 设备名称：旋转样品杆控制器\r\n");
  printf("-> software verson: V1.1\r\n");
  printf("-> compile time: %s\r\n",__TIME__);
  printf("-> compile date: %s\r\n",__DATE__);
  printf("-> [多场低温科技有限公司]\r\n");
  printf("------------------------------\r\n");
  printf("->可用命令：\r\n");
  printf("1. [s]  // 停止电机转动\r\n");
  printf("2. [?]  // 读取当前位置脉冲数量\r\n");
  printf("3. [MF] // 打印系统信息\r\n");
  printf("4. [z,1,1500] // 零点搜索命令,1为顺时针转动，0为逆时针转动，1500为脉冲频率\r\n");
  printf("5. [r,1,1500,108288] // 转动命令，1为顺时针转动，0为逆时针转动，1500为脉冲频率，108288为要转动的脉冲\r\n");
  printf("<-----------------------------\r\n");
}

void uart_msg_idle(void)
{
  uint8_t n=0;
  uint32_t freq=0;
  uint32_t pulse=0;
  uint8_t _dir=0;
  
  if(g_ucRxRcvNewFlag)
  {
    g_ucRxRcvNewFlag = 0;
    
    n = strlen((char*)g_RxBuf);
    if(n==3)
    {
      switch(g_RxBuf[1])
      {
        //case '?': printf("%d\r\n",g_tTube.pulse); break;       
        //case '?': printf("[w,1,054050]"); break;
        case '?': send_sv_2_uart(); break;
        case 's': MOTO_Stop(); break;
        //case 'z': search_zero(1); break;
        default: break;
      }
    }
    else if(n==4)
    {
      if(IS_MF_VALID)
      {
        print_sys_info();
      }
    }
    else if(n==10) // [z,1,1500]
    {
      freq = get_zero_freq();
      if(IS_ZERO_BUF_VALID() && freq<=1504)
      {
        if(g_RxBuf[3]=='1')
        {
          search_zero(1,freq); // 顺时针搜索
        }
        else
        {
          search_zero(0,freq); // 逆时针搜索
        }
      }
      else
      {
        BEEP_Start(1500, 5, 5, 3);
      }
    }
    else if((n==17)&&(g_RxBuf[1]=='r'))
    {
      // [r,1,1500,108288]
      freq = get_run_freq();
      pulse = get_pulse();
      g_tMoto.sv_pulse = pulse;
      
      if(g_RxBuf[3]=='1')
      {
        _dir = 1;
				g_tMoto.sv_pulse = -g_tMoto.sv_pulse;
      }
      else if(g_RxBuf[3]=='0')
      {
        _dir = 0;
        
      }
      else
      {
        BEEP_Start(1500, 5, 5, 3);
        return ;
      }
      
      if(g_tMoto.pv_pulse<g_tMoto.sv_pulse)
      {
        //MOTO_Start(freq, _dir, 123);
        MOTO_Start(freq, 0, 123);
      }
      else if(g_tMoto.pv_pulse>g_tMoto.sv_pulse)
      {
        //MOTO_Start(freq, _dir, 123);
        MOTO_Start(freq, 1, 123);
      }
      else
      {
        BEEP_Start(1500, 5, 5, 3);
      }
    }
    else
    {
      BEEP_Start(1500, 5, 5, 3);
    }
  }
}

//-------------------------------- End of file ---------------------------------
