PASII/CandeII_1.4/User/main.c

1517 lines
43 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*************************************************************************************************
**Filename:
**Version :
**Author :
**Date :
**Description:
**
*************************************************************************************************/
#include "mcu_bsp.h"
#include "lsm6d.h"
#include "lis2dh.h"
#include "ota.h"
#include "gpadc.h"
#include "delay.h"
#include "cjson.h"
#include <stdarg.h>
#include <stdlib.h>
#include <string.h>
#include "crc16.h"
#include "common.h"
#include "wdt.h"
#include "DebugLog.h"
#include "softtimer.h"
#include "app_timer.h"
#include "SYD_ble_service_service.h"
/*---------------------------------------------------------------*/
//变量定义
Tx_Buffer_t dtts_tx_buffer; // 存放发送给主机的数据
static struct gap_ble_addr dev_addr;
uint8_t work_led_count = 6;
/* 设置配置数组 */
static uint8_t Device_Name_Array[Device_Name_Len]= {Device_Name};
/* this is for change the byte to char*/
static char hex[] = "0123456789ABCDEF";
/**< GATT属性列表头,传入到协议栈中进行初始化*/
static struct gap_att_report_handle *g_report;
/* connection*/
uint8_t connect_flag=0;
uint8_t Adv_State = 0;
/* 延迟状态 */
static uint8_t latency_state = 0;
/* SPP延时计数*/
static uint16_t spp_delay_cnt=0;
uint8_t update_latency_mode=0;
/* 设置启动发送功能允许将数据notify到服务*/
uint8_t start_tx = 0;
uint8_t syd_nosleep_control=0;
int batteryPercentage =0; /**< 剩余电量百分比*/
/* adv data array*/
uint8_t ADV_DATA[] = {
0x02, /**< length*/
0x01, /**< AD Type: Flags*/
0x05, /**< LE Limited Discoverable Mode & BR/EDR Not Supported*/
0X0B, /**< length*/
0XFF, /**< AD Type: MANUFACTURER SPECIFIC DATA*/
0X4C, /**< Company Identifier (0x00)*/
0X76, /**< Company Identifier (0x00)*/
0X42, /**< Company Identifier (0x00)*/
0X75, /**< Company Identifier (0x42)*/
0X00, /**< for mac*/
0X00, /**< for mac*/
0X00, /**< for mac*/
0X00, /**< for mac*/
0X00, /**< for mac*/
0X00, /**< for mac*/
Device_Name_Len+1, /**< length*/
0x09, /**< AD Type: Complete local name*/
Device_Name /**< Device name*/
};
/* scan data array*/
uint8_t SCAN_DATA[]= {
0X05, /**< length*/
0X03, /**< AD Type: MANUFACTURER SPECIFIC DATA*/
0X16, /**< Company Identifier (0x00)*/
0X18, /**< Company Identifier (0x00)*/
0XE0,
0XFF,
0X04,
0X16,
0X04,
0X2A,
0X01, /**< 0X01 踏频0x02 码表0x03 灯04电池05电显*/
};
/*---------------------------------------------------------------*/
//外部变量调用声明
extern PAS_SENSOR_t PAS;
static void ble_init();
void ble_evt_callback(struct gap_ble_evt *p_evt);
static void ble_gatt_write(struct gap_att_write_evt evt);
static void ble_gatt_read(struct gap_att_read_evt evt);
static void setup_adv_data();
uint8_t str_cmp(uint8_t *p1,uint8_t *p2,uint8_t len);
void nvic_priority(void);
void rtc_event_handler(void);
void ota_manage(void);
void BLSetConnectionUpdate(uint8_t target);
static void timer_event_handler();
static void timer_1_callback(void);
uint8_t BLE_SendRPPData(uint8_t *buf, uint8_t len);
void pack_timer_event();
static void send_to_master(void);
void Connection_latency(void);
void cal_battery_value(uint16_t adc);
uint8_t BLE_NotifyBatteryLevel();
uint8_t get_battery_value();
static void rf_stop(void);
static void PowerDown(void);
void gpio_init(void);
void Charge_State_Judge(void);
void LED_State_Indicator(void);
void syd_nosleep(bool en,SYD_NOSLEEP_CONTROL condit);
void JsProtocol_Report(int16_t MasterValue,int16_t SlaveValue,int16_t FunCodeValue,
char* Key1,int16_t Value1,char* Key2,int16_t Value2);
/*---------------------------------------------------------------*/
//主函数
int main()
{
__disable_irq();
delay_ms(10);
/* 蓝牙初始化系统主时钟初始化64M,32K时钟初始化为LPO */
ble_init();
/*把串口优先级设置到最高*/
nvic_priority();
/* 根据需要重新设置系统主时钟为64M并校准*/
MCUClockSwitch(SYSTEM_CLOCK_64M_RCOSC);
RCOSCCalibration();
#ifdef USER_32K_CLOCK_RCOSC
ClockSwitch(SYSTEM_32K_CLOCK_RCOSC);
GAPBBDelayMS(500); //内部晶振首次校准的时候必须使用等待硬件复位完成
LPOCalibration(); //这是内部RC32k晶振的校准函数,经过该函数后定时器能够得到一个比较准确的值
#else
ClockSwitch(SYSTEM_32K_CLOCK_XOSC);
#endif
#ifdef _SYD_RTT_DEBUG_
DebugLogInit(); /**< 调试日志*/
#endif
UartEn(false);
#if ((1) && (defined(_DEBUG_) || defined(_SYD_RTT_DEBUG_)))
dbg_printf("SYD8811 GPIO test demo %s:%s\r\n", __DATE__ , __TIME__);
#endif
gpio_init();
/* software:timr0 blelib:timer3 */
SYD_Timer_Init(EVT_NUM, syd_sysTimer);
Timer_Evt_List();
Timer_Evt_Start(EVT_1S_WORK);
Timer_Evt_Start(EVT_1S_OTA);
Timer_Evt_Start(EVT_300MS_PACK);
Timer_Evt_Start(EVT_20S_BATTERY);
/*5 seconds wdt*/
#ifdef _WDT_
wdt_enable(128*5);
#endif
BSP_MCU_Config();
Lsm6dso_Init();
Timer2_Enable();
Lis2dh_Init();
StartAdv(); //开始广播
Adv_State = 1;
ReadFlashData(FLASH_INTERNAL_DATA_ADDR, sizeof(PAS.transpModes), (unsigned char*)&PAS.transpModes);
dbg_printf("transpModes = %d\r\n",PAS.transpModes);
__enable_irq();
get_battery_value(); //上电或者POWNDOWN唤醒时计算一次电量
while(1)
{
ble_sched_execute(); /*协议栈任务轮训*/
timer_event_handler();
Charge_State_Judge();
if(start_tx & 0x01)
{
send_to_master();
}
if(!(syd_nosleep_control & SYD_NOSLEEP_SW))
{
SystemSleep(); //浅度休眠,定时器中断唤醒
}
if(PAS.sleepState == 1)
{
PowerDown();
}
}
}
/*---------------------------------------------------------------*/
//充电状态检测
//高电平:非充电状态/充满
//低电平:正在充电
//注意: IO口输入反向
void Charge_State_Judge(void)
{
if((GPIO_Pin_Read(U32BIT(CHARGE_STATE_PIN)) & U32BIT(CHARGE_STATE_PIN))!= 0)
{
PAS.chargeState = 1;
if(PAS.transpModes == 1)
{
PAS.transpModes = 0;
PAS.exitTransmode = 1;
}
}
else
{
PAS.chargeState = 0;
}
}
/*********************************************************************
* Function : gpio_init
* Param in : none
* Param out: none
* Return : none
* Describe : 初始化IO参数
*/
void gpio_init(void)
{
uint8_t i;
uint32_t io_input=0,io_pull=0,io_output=0,io_outlow=0,io_invert=0;
#ifdef USER_32K_CLOCK_RCOSC
/* 如果使用内部时钟,时钟引脚上拉*/
PIN_CONFIG->PAD_INPUT_PULL_UP[0] = 0xff; //pull up
#else
/* 如果使用外部时钟,时钟引脚下拉*/
PIN_CONFIG->PAD_INPUT_PULL_UP[0] = 0xfc; //pull up gpio 0 1 32K xosc
#endif
/* 配置其他GPIO的引脚这里需要注意IO和PAD的关系*/
PIN_CONFIG->PAD_INPUT_PULL_UP[1] = 0xff; //pull up
PIN_CONFIG->PAD_INPUT_PULL_UP[2] = 0xff; //pull up
PIN_CONFIG->PAD_INPUT_PULL_UP[3] = 0xc7; //pull up pin29/pin28 SWD pen21/reset
PIN_CONFIG->PAD_INPUT_PULL_UP[4] = 0xff; //pull up
for(i=0;i<32;i++)
{
switch(i)
{
/* 外部时钟I0配置*/
#ifndef USER_32K_CLOCK_RCOSC
case GPIO_0:
case GPIO_1:
break;
#endif
case PEN_PIN:
io_output |=U32BIT(i);
io_outlow &=~U32BIT(i); //输出高
break;
case LIS2D_INT2:
io_input |=U32BIT(i);
io_pull |=U32BIT(i);
io_invert |=U32BIT(i);
break;
/**< RESET IO*/
case GPIO_21:
io_input |=U32BIT(i);
io_pull |=U32BIT(i);
break;
/**< 默认上拉输入*/
default:
io_input |=U32BIT(i);
io_pull |=U32BIT(i);
break;
}
}
/* 设置GPIO21为IO口模式而不是复位管脚*/
BBRFWrite(0x7f, 0x00);
BBRFWrite(0x1a, 0x40);
/* 默认输出IO配置*/
GPIO_Set_Output(io_output);
PIN_Pullup_Disable(T_QFN_48, io_output);
/* 默认输出高电平IO配置*/
GPIO_Pin_Set(io_output & (~io_outlow));
/* 默认输出低电平IO配置*/
GPIO_Pin_Clear(io_outlow);
/* 默认IO设置是上拉输入*/
GPIO_Set_Input(io_input,io_invert);
PIN_Pullup_Enable(T_QFN_48,io_pull);
}
/*********************************************************************
* Function : PowerDown
* Param in : none
* Param out: none
* Return : none
* Describe : PowerDown
*/
static void PowerDown(void)
{
struct gap_wakeup_config pw_cfg;
__disable_irq();
#ifdef _WDT_
wdt_disable();
#endif
LED_ON();
delay_ms(300);
LED_OFF();
Lsm6dso_Disable();
PEN_DISABLE();
CEN_DISABLE(); // 母线电压采样MOS关闭
pw_cfg.wakeup_type = POWERDOWN_WAKEUP;
pw_cfg.wdt_wakeup_en = (bool)false;
pw_cfg.rtc_wakeup_en = (bool)false;
pw_cfg.timer_wakeup_en = (bool)false;
pw_cfg.gpi_wakeup_en = (bool)true;
if(PAS.transpModes == 1)
{
pw_cfg.gpi_wakeup_cfg = U32BIT(CHARGE_STATE_PIN); //中断唤醒pin
EraseFlashData(FLASH_INTERNAL_DATA_ADDR,1);
WriteFlashData(FLASH_INTERNAL_DATA_ADDR,sizeof(PAS.transpModes), (unsigned char*)&PAS.transpModes);
}
else
{
pw_cfg.gpi_wakeup_cfg = U32BIT(LIS2D_INT2); //中断唤醒pin
if(PAS.exitTransmode)
{
PAS.exitTransmode = 0;
EraseFlashData(FLASH_INTERNAL_DATA_ADDR,1);
WriteFlashData(FLASH_INTERNAL_DATA_ADDR,sizeof(PAS.transpModes), (unsigned char*)&PAS.transpModes);
}
}
WakeupConfig(&pw_cfg);
SystemPowerDown();
delay_ms(5);
__enable_irq();
}
/*********************************************************************
* Function : work_timer_event
* Param in : none
* Param out: none
* Return : none
* Describe : work_timer_event
*/
static void work_timer_event(void)
{
/*****************判断是否进入POWERDOWN状态***********************/
if(connect_flag == 1)
{
if(PAS.RPM == 0)
{
PAS.sleepCnt++;
if((PAS.sleepCnt >= WORK_SLEEP_TIME)&&(PAS.sleepFlag==0)&&(ota_state == 0))
{
PAS.sleepCnt = 0;
PAS.sleepFlag = 1;
DisConnect(); //不要重复断开连接,否则软件定时器会死机
}
}
else
{
PAS.sleepCnt=0;
}
}
else
{
Timer2_Disable();
dtts_tx_buffer.header = dtts_tx_buffer.tail;
if((GPIO_Pin_Read(U32BIT(LIS2D_INT2)) & U32BIT(LIS2D_INT2))!= 0)
{
PAS.sleepCnt = 0;
}
else
{
PAS.sleepCnt++;
}
if((PAS.sleepCnt >= WORK_SLEEP_TIME)&&(ota_state == 0))
{
PAS.sleepFlag = 1; //准备休眠 关广播
}
if((PAS.sleepFlag == 1)&&(Adv_State==0))
{
PAS.sleepState = 1;
}
}
}
/*********************************************************************
* Function : battery_timer_event
* Param in : none
* Param out: none
* Return : none
* Describe : get battery event, it be called every 20s
*/
static void battery_timer_event(void)
{
static uint8_t count = 0;
count++;
if(count>=3)
{
count=0;
if((PAS.sleepCnt < (WORK_SLEEP_TIME - 10))&&(PAS.sleepFlag != 1)&&(PAS.sleepState != 1))
{
get_battery_value();
}
}
}
/*********************************************************************
* Function : LED_State_Indicator
* Param in : none
* Param out: none
* Return : none
* Describe : get LED_State_Indicator value
*/
void LED_State_Indicator(void)
{
/*****************工作状态指示灯***********************/
if(PAS.chargeState == 1)
{
LED_ON();
work_led_count = 0;
}
else
{
if(work_led_count > 0)
{
work_led_count--;
LED_TURN();
if(work_led_count==0)
{
LED_OFF();
}
}
else
{
LED_OFF();
}
}
}
/*********************************************************************
* Function : get_battery_value
* Param in : none
* Param out: none
* Return : none
* Describe : get battery value
*/
uint8_t get_battery_value()
{
GPADC_channel_sel(ADCGP_CH);
syd_nosleep((bool)true,SYD_NOSLEEP_ADC);
GPADC_start(cal_battery_value);
if(connect_flag)
{
BLE_NotifyBatteryLevel();
}
return 1;
}
/*********************************************************************
* Function : 计算电池的值
* Param in : none
* Param out: none
* Return : none
* Describe : calculate the battery value
*/
void cal_battery_value(uint16_t adc)
{
static uint8_t count,batteryPercenttemp[2];
#if ((1) && (defined(_DEBUG_) || defined(_SYD_RTT_DEBUG_)))
dbg_printf("battery adc:%04x ",adc);
#endif
if(0xffff != adc)
{
float batteryVoltage=0.0;
batteryVoltage=(float)adc*3.6/1024;
// PAS.batt_vol = batteryVoltage*100;
#if ((1) && (defined(_DEBUG_) || defined(_SYD_RTT_DEBUG_)))
dbg_printf("pin_vol:%4.3f ",batteryVoltage);
#endif
/* 转换为电池电压*/
batteryVoltage = batteryVoltage*4/3+0.04;
batteryPercentage = (batteryVoltage*1000-3000)/11.5+0.5;
if(batteryPercentage < 0)batteryPercentage=0;
if(batteryPercentage > 100)batteryPercentage=100;
count++;
if(count>=2)count=0;
batteryPercenttemp[count]=batteryPercentage;
if((batteryPercenttemp[0] == batteryPercenttemp[1])||(PAS.batt_level == 0))
{
PAS.batt_level = batteryPercentage;
}
#ifdef BATTERY_low_PROTECT
if(batteryVoltage<3.0)Battery_low=1;
else Battery_low=0;
#endif
#if ((1) && (defined(_DEBUG_) || defined(_SYD_RTT_DEBUG_)))
dbg_printf("bat_vol:%4.3f level:%d\r\n",batteryVoltage,batteryPercentage);
#endif
}
else
{
#if ((1) && (defined(_DEBUG_) || defined(_SYD_RTT_DEBUG_)))
dbg_printf("battery adc Err \r\n");
#endif
}
syd_nosleep((bool)false,SYD_NOSLEEP_ADC);
}
/*********************************************************************
* Function : syd_nosleep
* Param in : none
* Param out: none
* Return : none
* Describe : don't into sleep when read adc
*/
void syd_nosleep(bool en,SYD_NOSLEEP_CONTROL condit)
{
if(en)
{
syd_nosleep_control |=SYD_NOSLEEP_SW | condit;
}
else
{
syd_nosleep_control &=~condit;
if(!(syd_nosleep_control & 0xFFFE)) syd_nosleep_control &=~SYD_NOSLEEP_SW;
}
}
/*********************************************************************
* Function : BLE_NotifyBatteryLevel
* Param in : none
* Param out: none
* Return : none
* Describe : notify the battery level
*/
uint8_t BLE_NotifyBatteryLevel()
{
struct gap_att_report report;
report.primary =BLE_DTTS;
report.uuid = BLE_BATTERY_LEVEL_UUID;
report.hdl = BLE_BATTERY_LEVEL_VALUE_HANDLE;
report.value = BLE_GATT_NOTIFICATION;
return GATTDataSend(BLE_GATT_NOTIFICATION, &report, 1, &PAS.batt_level);
}
/*********************************************************************
* Function : ble_init
* Param in : none
* Param out: none
* Return : none
* Describe : BLE初始化
*/
static void ble_init()
{
struct gap_evt_callback evt;
struct smp_pairing_req sec_params;
struct gap_wakeup_config pw_cfg;
BleInit();
SetWinWideMinusCnt(1);
GetGATTReportHandle(&g_report);
/* security parameters */
sec_params.io = IO_NO_INPUT_OUTPUT;
sec_params.oob = OOB_AUTH_NOT_PRESENT;
sec_params.flags = AUTHREQ_BONDING;
sec_params.mitm = 0;
sec_params.max_enc_sz = 16;
sec_params.init_key = 0;
sec_params.rsp_key = (SMP_KEY_MASTER_IDEN |SMP_KEY_ADDR_INFO);
SetSecParams(&sec_params);
evt.evt_mask=(GAP_EVT_CONNECTION_SLEEP|GAP_EVT_CONNECTION_INTERVAL);
evt.p_callback=&ble_evt_callback;
SetEvtCallback(&evt);
/* Bond Manager (MAX:10) */
SetBondManagerIndex(0x00);
setup_adv_data();
/*
当POWERDOWN_WAKEUP时
PW_CTRL->DSLP_LPO_EN = true这些中断源才能唤醒并复位运行
如果是false就只有pin能唤醒并复位运行
*/
pw_cfg.wakeup_type = SLEEP_WAKEUP;
pw_cfg.wdt_wakeup_en = (bool)false;
pw_cfg.rtc_wakeup_en = (bool)false;
pw_cfg.timer_wakeup_en = (bool)true;
pw_cfg.gpi_wakeup_en = (bool)false;
pw_cfg.gpi_wakeup_cfg = U32BIT(LIS2D_INT2); //中断唤醒pin
WakeupConfig(&pw_cfg);
}
/*********************************************************************
* Function : ble_evt_callback
* Param in : none
* Param out: none
* Return : none
* Describe : handle the ble event
*/
void ble_evt_callback(struct gap_ble_evt *p_evt)
{
if(p_evt->evt_code == GAP_EVT_ATT_WRITE)
{
ble_gatt_write(p_evt->evt.att_write_evt);
}
else if(p_evt->evt_code == GAP_EVT_ATT_READ)
{
ble_gatt_read(p_evt->evt.att_read_evt);
}
else if(p_evt->evt_code == GAP_EVT_CONNECTED)
{
connect_flag = 1;
PAS.sleepCnt = 0;
PAS.sleepFlag = 0;
update_latency_mode = 0;
Timer_Evt_Start(EVT_2S); //修改连接参数
Timer2_Enable();
#if defined(_DEBUG_) || defined(_SYD_RTT_DEBUG_)
DBGHEXDUMP("Connected addr:",p_evt->evt.bond_dev_evt.addr,sizeof(p_evt->evt.bond_dev_evt.addr));
#endif
#ifdef _OTA_
ota_variable_clear(true);
#endif
}
else if(p_evt->evt_code == GAP_EVT_DISCONNECTED)
{
#if defined(_DEBUG_) || defined(_SYD_RTT_DEBUG_)
DBGPRINTF("Disconnected,reson:0x%02x\r\n", p_evt->evt.disconn_evt.reason);
#endif
start_tx &= ~0x01; //清零
connect_flag = 0;
PAS.sleepCnt = 0;
#ifdef _OTA_
if(Timer_Get_State(EVT_1S_OTA) && (ota_state!=3))
{
Timer_Evt_Stop(EVT_1S_OTA);
}
#endif
/* 成功断开连接之后功耗会加大10ua
同时启动广播*/
if((PAS.sleepFlag == 0)||(PAS.chargeState == 1))
{
setup_adv_data();
StartAdv();
Adv_State = 1;
#if defined(_DEBUG_) || defined(_SYD_RTT_DEBUG_)
DBGPRINTF(("restart adv @ disc!\r\n"));
#endif
}
else
{
rf_stop();
Adv_State = 0;
#if defined(_DEBUG_) || defined(_SYD_RTT_DEBUG_)
DBGPRINTF(("stop adv @ disc!\r\n"));
#endif
}
}
else if(p_evt->evt_code == GAP_EVT_ATT_HANDLE_CONFIGURE)
{
#if defined(_DEBUG_) || defined(_SYD_RTT_DEBUG_)
DBGPRINTF(("GAP_EVT_ATT_HANDLE_CONFIGURE= %2x,%2x,%2x\r\n"),
p_evt->evt.att_handle_config_evt.uuid,
p_evt->evt.att_handle_config_evt.hdl,
p_evt->evt.att_handle_config_evt.value);
#endif
if(p_evt->evt.att_handle_config_evt.uuid == BLE_DTTS)
{
if(p_evt->evt.att_handle_config_evt.value == BLE_GATT_NOTIFICATION)
{
switch (p_evt->evt.att_handle_config_evt.hdl)
{
case (BLE_RPP_VALUE_HANDLE+1):
{
start_tx |= 0x01;
dtts_tx_buffer.header = dtts_tx_buffer.tail;
#if defined(_DEBUG_) || defined(_SYD_RTT_DEBUG_)
DBGPRINTF(("RPP notify Enabled!\r\n"));
#endif
}
break;
case (BLE_CTL_VALUE_HANDLE+1):
{
start_tx |= 0x02;
dtts_tx_buffer.header = dtts_tx_buffer.tail;
#if defined(_DEBUG_) || defined(_SYD_RTT_DEBUG_)
DBGPRINTF(("CTL notify Enabled!\r\n"));
#endif
}
break;
case (BLE_BATTERY_LEVEL_VALUE_HANDLE+1):
{
start_tx |= 0x03;
dtts_tx_buffer.header = dtts_tx_buffer.tail;
#if defined(_DEBUG_) || defined(_SYD_RTT_DEBUG_)
DBGPRINTF(("BAT notify Enabled!\r\n"));
#endif
}
break;
default:
break;
}
}
else
{
switch (p_evt->evt.att_handle_config_evt.hdl)
{
case (BLE_RPP_VALUE_HANDLE+1):
{
start_tx &= ~0x01;
/* 允许硬件自由控制32Mhz晶振休眠的时候功耗很低*/
UartEn(false);
#if defined(_DEBUG_) || defined(_SYD_RTT_DEBUG_)
DBGPRINTF(("RPP notify Disabled!\r\n"));
#endif
}
break;
case (BLE_CTL_VALUE_HANDLE+1):
{
start_tx &= ~0x02;
#if defined(_DEBUG_) || defined(_SYD_RTT_DEBUG_)
DBGPRINTF(("CTL notify Disabled!\r\n"));
#endif
}
break;
case (BLE_BATTERY_LEVEL_VALUE_HANDLE+1):
{
start_tx &= ~0x03;
#if defined(_DEBUG_) || defined(_SYD_RTT_DEBUG_)
DBGPRINTF(("BAT notify Disabled!\r\n"));
#endif
}
break;
default:
break;
}
}
}
}
else if(p_evt->evt_code == GAP_EVT_L2CAP_UPDATE_RSP)
{
switch(p_evt->evt.l2cap_update_rsp_evt.result)
{
case CONN_PARAMS_ACCEPTED:
#if defined(_DEBUG_) || defined(_SYD_RTT_DEBUG_)
DBGPRINTF(("update rsp ACCEPTED\r\n"));
{
struct gap_link_params link_app;
GetLinkParameters(&link_app);
#if defined(_DEBUG_) || defined(_SYD_RTT_DEBUG_)
dbg_printf("interval:%x latency:%x\r\n",link_app.interval,link_app.latency);
#endif
}
#endif
break;
case CONN_PARAMS_REJECTED:
#if defined(_DEBUG_) || defined(_SYD_RTT_DEBUG_)
//DBGPRINTF(("update rsp REJECTED\r\n"));
#endif
break;
case CONN_PARAM_SMART_TIMEROUT:
#if defined(_DEBUG_) || defined(_SYD_RTT_DEBUG_)
//DBGPRINTF(("update rsp TIMEROUT\r\n"));
#endif
break;
case CONN_PARAM_SMART_SUCCEED:
#if defined(_DEBUG_) || defined(_SYD_RTT_DEBUG_)
//DBGPRINTF(("update rsp SUCCEED\r\n"));
#endif
break;
case CONN_PARAM_LATENCY_ENABLE:
#if defined(_DEBUG_) || defined(_SYD_RTT_DEBUG_)
// DBGPRINTF(("Enable latency\r\n"));
#endif
break;
case CONN_PARAM_LATENCY_DISABLE:
#if defined(_DEBUG_) || defined(_SYD_RTT_DEBUG_)
// DBGPRINTF(("Disable latency\r\n"));
#endif
break;
}
}
else if(p_evt->evt_code == GAP_EVT_CONN_UPDATE_COMP)
{
struct gap_link_params link;
GetLinkParameters(&link);
#if defined(_DEBUG_) || defined(_SYD_RTT_DEBUG_)
DBGPRINTF("CONN_UPDATE_COMP: %d, %d, %d\r\n", link.interval, link.latency, link.svto);
#endif
}
else if(p_evt->evt_code == GAP_EVT_ADV_END)
{
#if defined(_DEBUG_) || defined(_SYD_RTT_DEBUG_)
DBGPRINTF(("GAP_EVT_ADV_END\r\n"));
#endif
if((PAS.sleepFlag == 0)||(PAS.chargeState == 1))
{
StartAdv();
Adv_State = 1;
}
else
{
rf_stop();
Adv_State = 0;
}
#if defined(_DEBUG_) || defined(_SYD_RTT_DEBUG_)
DBGPRINTF(("restart adv\r\n"));
#endif
}
}
/*********************************************************************
* Function :
* Param in : none
* Param out: none
* Return : none
* Describe :
*/
static void rf_stop(void)
{
RFSleep();
}
/*********************************************************************
* Function : 发送指令
* Param in : none
* Param out: none
* Return : none
* Describe :
*/
uint8_t BLE_SendCMDData(uint8_t *buf, uint8_t len)
{
struct gap_att_report report;
report.primary = BLE_DTTS;
report.uuid = BLE_CTL_UUID;
report.hdl = BLE_CTL_VALUE_HANDLE;
report.value = BLE_GATT_NOTIFICATION;
return GATTDataSend(BLE_GATT_NOTIFICATION, &report, len, buf);
}
/*********************************************************************
* Function : ble_gatt_write
* Param in : none
* Param out: none
* Return : none
* Describe : GATT属性写入处理
*/
static void ble_gatt_write(struct gap_att_write_evt evt)
{
if(evt.uuid == BLE_SPP_UUID)
{
}
else if(evt.uuid ==BLE_CTL_UUID)
{
#if defined(_DEBUG_) || defined(_SYD_RTT_DEBUG_)
DBGHEXDUMP("BLE_CTL_UUID:",evt.data, evt.sz);
#endif
if(evt.sz >= 2&& evt.data[0] == '@' && evt.data[evt.sz-1] == '#')
{
/* 测试指令 */
if((evt.sz == 6) && str_cmp(evt.data,
(uint8_t *)"@TEST#", 6))
{
#if defined(_DEBUG_) || defined(_SYD_RTT_DEBUG_)
dbg_printf("@OK#\r\n");
#endif
}
else if((evt.sz == 5) && str_cmp(evt.data,
(uint8_t *)"@OFF#", 5))
{
uint8_t data[6]="@OK#\r\n";
BLE_SendCMDData(data,6);
PAS.transpModes = 1; //运输模式
PAS.sleepCnt = WORK_SLEEP_TIME; //运输模式,加快进入深度休眠模式
}
else if((evt.sz == 5) && str_cmp(evt.data,
(uint8_t *)"@CAL#", 5))
{
PAS.adjustFlag = 1;
#if defined(_DEBUG_) || defined(_SYD_RTT_DEBUG_)
DBGPRINTF("PAS.adjustFlag = %d\r\n",PAS.adjustFlag);
#endif
}
}
else
{
#if defined(_DEBUG_) || defined(_SYD_RTT_DEBUG_)
dbg_printf("@ERROR cmd#\r\n");
#endif
}
}
else if(evt.uuid== BLE_OTA_Read_Write_UUID)
{
#ifdef _OTA_
ota_cmd(evt.data, evt.sz);
#endif
}
}
/*********************************************************************
* Function : ble_gatt_read
* Param in : none
* Param out: none
* Return : none
* Describe : GATT属性读取处理
*/
static void ble_gatt_read(struct gap_att_read_evt evt)
{
/* 设备名称*/
if(evt.uuid == BLE_DEVICE_NAME_UUID)
{
uint8_t gatt_buf_sz = sizeof(Device_Name_Array);
SetGATTReadRsp(gatt_buf_sz, Device_Name_Array);
}
/* 制造商名称*/
else if(evt.uuid == BLE_MANUFACTURER_NAME_STRING_UUID)
{
SetGATTReadRsp(Manufacturer_Size, (uint8_t *)Manufacturer_Name);
}
/* 产品型号*/
else if(evt.uuid == BLE_MODEL_NUMBER_STRING_UUID)
{
SetGATTReadRsp(Model_Size, (uint8_t *)Model_Number);
}
/* 产品串号*/
else if(evt.uuid == BLE_SERIAL_NUMBER_STRING_UUID)
{
SetGATTReadRsp(Serial_Size, (uint8_t *)Serial_Number);
}
/* 硬件版本号*/
else if(evt.uuid == BLE_HARDWARE_REVISION_STRING_UUID)
{
SetGATTReadRsp(Hardware_Size, (uint8_t *)Hardware_Vesion);
}
/* 软件版本号*/
else if(evt.uuid == BLE_SOFTWARE_REVISION_STRING_UUID)
{
SetGATTReadRsp(Software_Size, (uint8_t *)Software_Vesion);
}
/* 电池电量*/
else if(evt.uuid == BLE_BATTERY_LEVEL_UUID)
{
// SetGATTReadRsp(1, (uint8_t *) &AD_Value.PowerScale);
}
/* OTA*/
else if(evt.uuid == BLE_OTA_Read_Write_UUID)
{
#ifdef _OTA_
uint8_t sz=0;
uint8_t rsp[sizeof(struct hci_evt)]= {0};
ota_rsp(rsp, &sz);
SetGATTReadRsp(sz, rsp);
#endif
}
}
/*********************************************************************
* Function : setup_adv_data
* Param in : none
* Param out: none
* Return : none
* Describe : 设置广播数据
*/
static void setup_adv_data()
{
struct gap_adv_params adv_params;
adv_params.type = ADV_IND;
/**< advertising channel : 37 & 38 & 39*/
adv_params.channel = 0x07;
/**< advertising interval : 1000ms (1600 * 0.625ms),这里需要注意的问题
就是设置的interval要是100的整数倍数这样时间才会比较准确,默认1600*/
adv_params.interval = 80;
adv_params.timeout = ADV_TIMEOUT; /**< timeout : 30s*/
/* 设置广播的参数*/
SetAdvParams(&adv_params);
/* 获取蓝牙的地址 */
GetDevAddr(&dev_addr);
ADV_DATA[9] = dev_addr.addr[5];
ADV_DATA[10] = dev_addr.addr[4];
ADV_DATA[11] = dev_addr.addr[3];
ADV_DATA[12] = dev_addr.addr[2];
ADV_DATA[13] = dev_addr.addr[1];
ADV_DATA[14] = dev_addr.addr[0];
/*the mac last 4 char to the adv name*/
ADV_DATA[25] = hex[(dev_addr.addr[1]>>4)&0X0F];
ADV_DATA[26] = hex[dev_addr.addr[1]&0X0F];
ADV_DATA[27] = hex[(dev_addr.addr[0]>>4)&0X0F];
ADV_DATA[28] = hex[dev_addr.addr[0]&0X0F];
Device_Name_Array[8] = ADV_DATA[25];
Device_Name_Array[9] = ADV_DATA[26];
Device_Name_Array[10]= ADV_DATA[27];
Device_Name_Array[11]= ADV_DATA[28];
/* set the adv data and scan data*/
SetAdvData(ADV_DATA, sizeof(ADV_DATA), SCAN_DATA, sizeof(SCAN_DATA));
*(uint8_t *)0x40020014 = 0x01; /*< 设置ADV_PITV为1降低功耗*/
}
/*********************************************************************
* Function : nvic_priority
* Param in : none
* Param out: none
* Return : none
* Describe : config teh nvic priority
*/
void nvic_priority(void)
{
NVIC_SetPriority(LLC_IRQn, 2);
NVIC_SetPriority(RTC_IRQn, 2);
NVIC_SetPriority(SW_IRQn, 2);
NVIC_SetPriority(I2C0_IRQn, 2);
NVIC_SetPriority(I2C1_IRQn, 2);
NVIC_SetPriority(UART0_IRQn, 2);
NVIC_SetPriority(UART1_IRQn, 2);
NVIC_SetPriority(TIMER0_IRQn, 3);
NVIC_SetPriority(TIMER1_IRQn, 2);
NVIC_SetPriority(TIMER2_IRQn, 2);
NVIC_SetPriority(TIMER3_IRQn, 2);
NVIC_SetPriority(GPIO_IRQn, 2);
NVIC_SetPriority(HID_IRQn, 2);
NVIC_SetPriority(SPIM_IRQn, 2);
NVIC_SetPriority(CAP_IRQn, 0);
NVIC_SetPriority(GPADC_IRQn, 2);
NVIC_SetPriority(LLC2_IRQn, 2);
NVIC_SetPriority(ISO7816_IRQn, 2);
NVIC_SetPriority(IR_Tx_IRQn, 2);
NVIC_SetPriority(TOUCH_IRQn, 2);
NVIC_SetPriority(HPWM_IRQn, 2);
NVIC_SetPriority(HTIMER_IRQn, 2);
NVIC_SetPriority(IR_Rx_IRQn, 2);
}
/*********************************************************************
* Function : RTC事件处理
* Param in : none
* Param out: none
* Return : none
* Describe : rtc时钟定时事件处理
*/
void rtc_event_handler(void)
{
/* 实时时钟处理*/
if(RTC_EVT)
{
#ifdef RTCEVT_185S
if(RTC_EVT & RTCEVT_185S)
{
#ifdef USER_32K_CLOCK_RCOSC
LPOCalibration();
#endif
#if defined(_DEBUG_) || defined(_SYD_RTT_DEBUG_)
DBGPRINTF(("RTCEVT_185S\r\n"));
#endif
RTC_EVT_Clr(RTCEVT_185S);
}
#endif
}
}
/*************************************************************************************************
* Function Name:
* Description : 设置连接延迟
* Arguments :
* Return Value :
*************************************************************************************************/
void Connection_latency(void)
{
update_latency_mode++;
if(update_latency_mode>=3)
{
latency_state=0;
/* low energy connect setting*/
BLSetConnectionUpdate(1);
Timer_Evt_Stop(EVT_2S);
}
}
/*********************************************************************
* Function : timer_event_handler
* Param in : none
* Param out: none
* Return : none
* Describe : 定时器事件处理
*/
static void timer_event_handler()
{
/* 定时器事件处理*/
if(TIMER_EVT)
{
#ifdef EVT_1S_OTA
if(TIMER_EVT&EVT_1S_OTA)
{
ota_manage(); /**< ota 过程管理 操作屏幕等*/
Timer_Evt_Clr(EVT_1S_OTA);
}
#endif
#ifdef EVT_2S
if(TIMER_EVT&EVT_2S)
{
Connection_latency(); /**< 连接参数相关设置*/
Timer_Evt_Clr(EVT_2S);
}
#endif
#ifdef EVT_1S_WORK
if(TIMER_EVT&EVT_1S_WORK)
{
work_timer_event();
Timer_Evt_Clr(EVT_1S_WORK);
}
#endif
#ifdef EVT_300MS_PACK
if(TIMER_EVT&EVT_300MS_PACK)
{
LED_State_Indicator();
#ifdef _WDT_
wdt_clear();
#endif
Timer_Evt_Clr(EVT_300MS_PACK);
}
#endif
#ifdef EVT_20S_BATTERY
if(TIMER_EVT&EVT_20S_BATTERY)
{
//计算电池电量
battery_timer_event();
Timer_Evt_Clr(EVT_20S_BATTERY);
}
#endif
}
}
/*********************************************************************
* Function : BLSetConnectionUpdate
* Param in : uint8_t target
* 0:ota
* 1:low energy
* Param out: none
* Return : none
* Describe : 更新连接参数
*/
void BLSetConnectionUpdate(uint8_t target)
{
struct gap_smart_update_params smart_params;
switch(target) {
/* 0:ota */
case 0:
/* connection parameters */
smart_params.updateitv_target=0x0010; /**< target connection interval (value * 1.25ms = 75 ms)*/
smart_params.updatesvto=0x00c8; /**< supervisory timeout (400 * 10 ms = 4s)*/
smart_params.updatelatency=0x0000;
break;
/* 1:low energy */
case 1:
/* connection parameters */
smart_params.updateitv_target=16; /**< target connection interval (value * 1.25ms = 75 ms)*/
smart_params.updatesvto=400; /**< supervisory timeout (value * 10 ms = 4s)*/
smart_params.updatelatency=1;
break;
}
smart_params.updatectrl=SMART_CONTROL_LATENCY | SMART_CONTROL_UPDATE;
smart_params.updateadj_num=MAX_UPDATE_ADJ_NUM;
gap_s_smart_update_latency(&smart_params);
#if defined(_DEBUG_) || defined(_SYD_RTT_DEBUG_)
dbg_printf("smart_params interval:%x latency:%x svto:%x\r\n",smart_params.updateitv_target,
smart_params.updatelatency,smart_params.updatesvto);
#endif
}
/*********************************************************************
* Function : ota_manage
* Param in : none
* Param out: none
* Return : none
* Describe : manage the ota operation
*/
void ota_manage(void)
{
#ifdef _OTA_
if(ota_state) {
switch(ota_state) {
case 1 :
#if defined(_DEBUG_) || defined(_SYD_RTT_DEBUG_)
dbg_printf("start FwErase\r\n");
#endif
CmdFwErase();
#if defined(_DEBUG_) || defined(_SYD_RTT_DEBUG_)
dbg_printf("OTA start\r\n");
#endif
ota_state =2;
ota_writecnt=0;
break;
case 2 :
ota_writecnt++;
if(ota_writecnt>0x20)
{
#if defined(_DEBUG_) || defined(_SYD_RTT_DEBUG_)
dbg_printf("OTA faile\r\n");
#endif
Timer_Evt_Stop(EVT_1S_OTA);
}
break;
case 3 :
ota_state=0;
Timer_Evt_Stop(EVT_1S_OTA);
#if defined(_DEBUG_) || defined(_SYD_RTT_DEBUG_)
dbg_printf("OTA finish\r\n");
#endif
delay_ms(1000);
#if defined(_DEBUG_) || defined(_SYD_RTT_DEBUG_)
dbg_printf("Start Reset 1000s\r\n");
#endif
SystemReset();
break;
default :
break;
}
}
#endif
}
/*************************************************************************************************
* Function Name:
* Description :
* Arguments : 将缓冲区数据发送到主机
* Return Value :
*************************************************************************************************/
static void send_to_master(void)
{
uint32_t len, header, tail;
header = dtts_tx_buffer.header;
tail = dtts_tx_buffer.tail;
/*有数据,处理数据*/
if(header != tail)
{
if(latency_state==0)
{
latency_state = 1;
spp_delay_cnt = 0;
timer_1_enable(32768/200, timer_1_callback); //5MS定时中断
}
}
else
{
return;
}
//caculate len
if(header >= tail)
{
len = header - tail;
}
else
{
len = header + MAX_RX_LENGTH - tail;
}
/* len bigger then 20, send data immediately*/
if(len>=PDULENTH)
{
for(; len>=PDULENTH; len-=PDULENTH)
{
uint8_t send_data[PDULENTH], i;
spp_delay_cnt = 0;
//memcpy PDULENTH byte
for(i=0; i<PDULENTH; i++)
{
send_data[i] = dtts_tx_buffer.data[tail++];
if(tail >= MAX_RX_LENGTH)
{
tail = 0;
}
}
//send
if(BLE_SendRPPData(send_data, PDULENTH))
{
dtts_tx_buffer.tail = tail;
}
else
{
break;
}
}
// if(len >= 1)
// {
// uint8_t send_data[PDULENTH], i;
//
// for(i=0; i< len; i++)
// {
// send_data[i] = dtts_tx_buffer.data[tail++];
// if(tail >= MAX_RX_LENGTH)
// {
// tail = 0;
// }
// }
// //send
// if(BLE_SendRPPData(send_data, len))
// {
// dtts_tx_buffer.tail = tail;
// }
// }
}
else if(len >= 1)
{
if(spp_delay_cnt >= 3)
{
uint8_t send_data[PDULENTH],i;
//memcpy len byte
for(i=0; i<len; i++)
{
send_data[i] = dtts_tx_buffer.data[tail++];
if(tail >= MAX_RX_LENGTH)
{
tail = 0;
}
}
//send
if(BLE_SendRPPData(send_data, len))
{
dtts_tx_buffer.tail = tail;
}
spp_delay_cnt = 0;
}
}
}
/*************************************************************************************************
* Function Name:
* Description :
* Arguments : 将串口数据发送到BLE服务
* Return Value :
*************************************************************************************************/
uint8_t BLE_SendRPPData(uint8_t *buf, uint8_t len)
{
if(start_tx & 0x01)
{
struct gap_att_report report;
report.primary = BLE_DTTS;
report.uuid = BLE_RPP_UUID;
report.hdl = BLE_RPP_VALUE_HANDLE;
report.value = BLE_GATT_NOTIFICATION;
return GATTDataSend(BLE_GATT_NOTIFICATION, &report, len, buf);
}
return 0;
}
/*************************************************************************************************
* Function Name:
* Description :
* Arguments : 定时器1的回调处理
* Return Value :
*************************************************************************************************/
static void timer_1_callback(void)
{
spp_delay_cnt++;
/* 经过三次回调spp缓冲区无数据后停止定时器*/
if((dtts_tx_buffer.header == dtts_tx_buffer.tail) && (spp_delay_cnt > 3))
{
latency_state = 0;
timer_1_disable();
}
}
/*************************************************************************************************
* Function Name:
* Description : json 数据上报
* Arguments :
* Return Value :
*************************************************************************************************/
void JsProtocol_Report(int16_t MasterValue,int16_t SlaveValue,int16_t FunCodeValue,
char* Key1,int16_t Value1,char* Key2,int16_t Value2)
{
int i=0;
cJSON* JsFrameTx_Report=NULL; //new一个响应的的json主体
cJSON* JsTx_Data=NULL; //new一个响应的的json主体
int16_t TxJs_Len; //保存json包长度
char* Tx_Pack;
char* pReport_Dfu;
int16_t pStr_Response_Index=0;
int16_t CRC16_Data;
/* 响应json包*/
JsFrameTx_Report=cJSON_CreateObject(); //申请内存创建帧json
cJSON_AddNumberToObject(JsFrameTx_Report,"M",MasterValue); //pack主机
cJSON_AddNumberToObject(JsFrameTx_Report,"S",SlaveValue); //pack从机
cJSON_AddNumberToObject(JsFrameTx_Report,"F",FunCodeValue); //pack功能码
JsTx_Data=cJSON_CreateObject(); //申请内存创建数据json
cJSON_AddItemToObject(JsFrameTx_Report, "D",JsTx_Data); //pack数据数组
cJSON_AddNumberToObject(JsTx_Data,Key1,Value1); //pack数据
cJSON_AddNumberToObject(JsTx_Data,Key2,Value2); //pack数据
/* change json to char */
Tx_Pack=cJSON_Print(JsFrameTx_Report); //申请内存json转char
cJSON_Minify(Tx_Pack); //瘦身
TxJs_Len=stringLength(Tx_Pack); //计算json长度
/* DFU pack */
pReport_Dfu=(char*)malloc(TxJs_Len*sizeof(char)+5); //申请内存pStr1
pReport_Dfu[pStr_Response_Index++]=0x7f;
pReport_Dfu[pStr_Response_Index++]=LSB_16(TxJs_Len); //packjson长度低
pReport_Dfu[pStr_Response_Index++]=MSB_16(TxJs_Len); //packjson长度高
memcpy(&pReport_Dfu[pStr_Response_Index],Tx_Pack,TxJs_Len);
pStr_Response_Index+=TxJs_Len;
CRC16_Data = crc16_ccitt( (uint8_t*)pReport_Dfu, pStr_Response_Index );
pReport_Dfu[pStr_Response_Index++] = LSB_16(CRC16_Data);
pReport_Dfu[pStr_Response_Index++] = MSB_16(CRC16_Data);
for(i=0; i<pStr_Response_Index; i++)
{
dtts_tx_buffer.data[dtts_tx_buffer.header]=pReport_Dfu[i];
dtts_tx_buffer.header++;
if(dtts_tx_buffer.header >= MAX_RX_LENGTH)
{
dtts_tx_buffer.header = 0;
}
}
free(pReport_Dfu); //销毁内存!!!
cJSON_free(Tx_Pack); //销毁链表!!!
cJSON_Delete(JsFrameTx_Report); //销毁内存!!!
}
/*************************************************************************************************
* Function Name:
* Description :
* Arguments : 打包数据并发送事件
* Return Value :
*************************************************************************************************/
void pack_timer_event()
{
if(start_tx & 0x01)
{
/* 打包数据到缓冲区 */
JsProtocol_Report(3,0,4,"41",PAS.RPM,"50",PAS.batt_level);
}
}
/*---------------------------------------------------------------*/