From 4b7665af5c21b817dbf4ae593730dabee31b3670 Mon Sep 17 00:00:00 2001 From: pvvx Date: Mon, 16 Jan 2023 01:49:42 +0300 Subject: [PATCH] add test ext_adv --- LR_v99.bin | Bin 77748 -> 76340 bytes src/app.c | 21 ++++--- src/app.h | 8 ++- src/app_att.c | 50 +++++++++------- src/app_config.h | 12 +++- src/ble.c | 142 ++++++++++++++++++++++++++++++++++++++++---- src/ble.h | 9 ++- src/cmd_parser.c | 11 ++-- src/custom_beacon.c | 4 +- src/epd_cgg1_2022.c | 2 +- src/ha_ble_beacon.c | 4 +- src/i2c.c | 16 ++--- src/mi_beacon.c | 25 ++++---- src/mi_beacon.h | 12 ++++ src/rds_count.c | 75 +++++++++++++++++++---- src/sensor.h | 3 +- src/sensors.c | 48 +++++++++------ 17 files changed, 328 insertions(+), 114 deletions(-) diff --git a/LR_v99.bin b/LR_v99.bin index c7767777f0c36980551e7efbe9b667cce90a90a9..f11ad08103046c0d00d48c3bac82bd0fa0f405ed 100644 GIT binary patch delta 18178 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 delta 19921 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,'.','0'+(VERSION&0x0f)}; // static const u8 my_ManStr[] = {"miaomiaoce.com"}; #elif DEVICE_TYPE == DEVICE_LYWSD03MMC static const u8 my_ModelStr[] = {"LYWSD03MMC"}; -static const u8 my_SerialStr[] = {"F1.0-CFMK-LB-ZCXTJ--"}; +static const u8 my_SerialStr[] = {"F1.0-CFMK-LB-ZCXTJ--"}; // B1.5 "F2.0-CFMK-LB-JHBD---", B1.9 "F1.0-CFMK-LB-FLD----" static const u8 my_FirmStr[] = {"github.com/pvvx"}; // "1.0.0_0109" RAM u8 my_HardStr[4];// = {"B1.4"}; static const u8 my_SoftStr[] = {'V','0'+(VERSION>>4),'.','0'+(VERSION&0x0f)}; // "0109" @@ -123,9 +123,9 @@ static const u8 my_ManStr[] = {"Qingping Technology (Beijing) Co., Ltd."}; //------------------ #endif // USE_DEVICE_INFO_CHR_UUID -RAM gap_periConnectParams_t my_periConnParameters = {8, 40, 0, 1000}; +RAM gap_periConnectParams_t my_periConnParameters = {CON_INERVAL_LAT, CON_INERVAL_LAT, 0, 8000}; -static u16 serviceChangeVal = 0; +static u32 serviceChangeVal = 0; // uint16 1..65535 "Start of Affected Attribute Handle Range", uint16 1..65535 "End of Affected Attribute Handle Range" static u16 serviceChangeCCC = 0; //////////////////////// Battery ///////////////////////////////////////////////// @@ -172,7 +172,11 @@ static const u8 my_appearanceCharVal[5] = { U16_LO(GATT_UUID_APPEARANCE), U16_HI(GATT_UUID_APPEARANCE) }; static const u8 my_periConnParamCharVal[5] = { +#ifdef CHG_CONN_PARAM + CHAR_PROP_READ | CHAR_PROP_WRITE, +#else CHAR_PROP_READ, +#endif U16_LO(CONN_PARAM_DP_H), U16_HI(CONN_PARAM_DP_H), U16_LO(GATT_UUID_PERI_CONN_PARAM), U16_HI(GATT_UUID_PERI_CONN_PARAM) }; @@ -321,7 +325,11 @@ RAM attribute_t my_Attributes[] = { {0,ATT_PERMISSIONS_READ,2,sizeof(my_appearanceCharVal),(u8*)(&my_characterUUID),(u8*)(my_appearanceCharVal), 0}, {0,ATT_PERMISSIONS_READ,2,sizeof(my_appearance),(u8*)(&my_appearanceUIID),(u8*)(&my_appearance), 0}, {0,ATT_PERMISSIONS_READ,2,sizeof(my_periConnParamCharVal),(u8*)(&my_characterUUID),(u8*)(my_periConnParamCharVal), 0}, +#ifdef CHG_CONN_PARAM + {0,ATT_PERMISSIONS_RDWR,2,sizeof(my_periConnParameters),(u8*)(&my_periConnParamUUID),(u8*)(&my_periConnParameters), 0, chgConnParameters}, +#else {0,ATT_PERMISSIONS_READ,2,sizeof(my_periConnParameters),(u8*)(&my_periConnParamUUID),(u8*)(&my_periConnParameters), 0}, +#endif // 0008 - 000b gatt {4,ATT_PERMISSIONS_READ,2,2,(u8*)(&my_primaryServiceUUID), (u8*)(&my_gattServiceUUID), 0}, {0,ATT_PERMISSIONS_READ,2,sizeof(my_serviceChangeCharVal),(u8*)(&my_characterUUID),(u8*)(my_serviceChangeCharVal), 0}, @@ -374,7 +382,7 @@ RAM attribute_t my_Attributes[] = { {4,ATT_PERMISSIONS_READ, 2,16,(u8*)(&my_primaryServiceUUID),(u8*)(&my_OtaServiceUUID), 0}, {0,ATT_PERMISSIONS_READ,2,sizeof(my_OtaCharVal),(u8*)(&my_characterUUID),(u8*)(my_OtaCharVal), 0}, //prop {0,ATT_PERMISSIONS_RDWR,16,sizeof(my_OtaData),(u8*)(&my_OtaUUID),(&my_OtaData), &otaWritePre, &otaRead}, //value - {0,ATT_PERMISSIONS_READ,2,sizeof (my_OtaName),(u8*)(&userdesc_UUID),(u8*)(my_OtaName), 0}, + {0,ATT_PERMISSIONS_READ,2,sizeof(my_OtaName),(u8*)(&userdesc_UUID),(u8*)(my_OtaName), 0}, ////////////////////////////////////// RxTx //////////////////////////////////////////////////// // 002B - 002E RxTx Communication {4,ATT_PERMISSIONS_READ,2,2,(u8*)(&my_primaryServiceUUID), (u8*)(&my_RxTx_ServiceUUID), 0}, @@ -390,33 +398,33 @@ RAM attribute_t my_Attributes[] = { {0,ATT_PERMISSIONS_AUTHOR_READ, 2, 1,(u8*)(&my_characterUUID), (u8*)(&mi_auth_prop), 0}, //prop {0,ATT_PERMISSIONS_AUTHOR_RDWR, 2, sizeof(mi_auth_buf),(u8*)(&mi_auth_uuid), (u8*)(mi_auth_buf), 0, 0}, //value - {0,ATT_PERMISSIONS_AUTHOR_READ, 2, sizeof (mi_auth_str),(u8*)(&userdesc_UUID), (u8*)(mi_auth_str), 0}, // Authentication + {0,ATT_PERMISSIONS_AUTHOR_READ, 2, sizeof(mi_auth_str),(u8*)(&userdesc_UUID), (u8*)(mi_auth_str), 0}, // Authentication {0,ATT_PERMISSIONS_AUTHOR_RDWR, 2, sizeof(mi_auth_ccc),(u8*)(&clientCharacterCfgUUID), (u8*)(&mi_auth_ccc), 0}, //value {0,ATT_PERMISSIONS_AUTHOR_READ, 2, 1,(u8*)(&my_characterUUID), (u8*)(&mi_ota_ctrl_prop), 0}, //prop {0,ATT_PERMISSIONS_AUTHOR_RDWR, 2, sizeof(mi_ota_ctrl_buf),(u8*)(&mi_ota_ctrl_uuid), (u8*)(mi_ota_ctrl_buf), 0, 0}, //value - {0,ATT_PERMISSIONS_AUTHOR_READ, 2, sizeof (mi_ota_ctrl_str),(u8*)(&userdesc_UUID), (u8*)(mi_ota_ctrl_str), 0}, // ota_ctrl + {0,ATT_PERMISSIONS_AUTHOR_READ, 2, sizeof(mi_ota_ctrl_str),(u8*)(&userdesc_UUID), (u8*)(mi_ota_ctrl_str), 0}, // ota_ctrl {0,ATT_PERMISSIONS_AUTHOR_RDWR, 2, sizeof(mi_ota_ctrl_ccc),(u8*)(&clientCharacterCfgUUID), (u8*)(mi_ota_ctrl_ccc), 0}, //value {0,ATT_PERMISSIONS_AUTHOR_READ, 2, 1,(u8*)(&my_characterUUID), (u8*)(&mi_ota_data_prop), 0}, //prop {0,ATT_PERMISSIONS_AUTHOR_RDWR, 2, sizeof(mi_ota_data_buf),(u8*)(&mi_ota_data_uuid), (mi_ota_data_buf), 0, 0}, //value - {0,ATT_PERMISSIONS_AUTHOR_READ, 2, sizeof (mi_ota_data_str),(u8*)(&userdesc_UUID), (u8*)(mi_ota_data_str), 0}, // ota_data + {0,ATT_PERMISSIONS_AUTHOR_READ, 2, sizeof(mi_ota_data_str),(u8*)(&userdesc_UUID), (u8*)(mi_ota_data_str), 0}, // ota_data {0,ATT_PERMISSIONS_AUTHOR_RDWR, 2, sizeof(mi_ota_data_ccc),(u8*)(&clientCharacterCfgUUID), (u8*)(mi_ota_data_ccc), 0}, //value {0,ATT_PERMISSIONS_AUTHOR_READ, 2, 1,(u8*)(&my_characterUUID), (u8*)(&mi_standard_prop), 0}, //prop {0,ATT_PERMISSIONS_AUTHOR_RDWR, 2, sizeof(mi_standard_buf),(u8*)(&mi_standard_uuid), (u8*)(mi_standard_buf), 0, 0}, //value - {0,ATT_PERMISSIONS_AUTHOR_READ, 2, sizeof (mi_standard_str),(u8*)(&userdesc_UUID), (u8*)(mi_standard_str), 0}, // standard + {0,ATT_PERMISSIONS_AUTHOR_READ, 2, sizeof(mi_standard_str),(u8*)(&userdesc_UUID), (u8*)(mi_standard_str), 0}, // standard {0,ATT_PERMISSIONS_AUTHOR_RDWR, 2, sizeof(mi_standard_ccc),(u8*)(&clientCharacterCfgUUID), (u8*)(mi_standard_ccc), 0}, //value /////////////////////////////////// Mi STDIO Service /////////////////////////////////// {9,ATT_PERMISSIONS_AUTHOR_READ, 2,16,(u8*)(&my_primaryServiceUUID), (u8*)(&mi_primary_stdio_uuid), 0}, // 0x6D,0x69,0x2E,0x6D,0x69,0x6F,0x74,0x2E,0x62,0x6C,0x65,0x00,0x00,0x01,0x00,0x00 {0,ATT_PERMISSIONS_AUTHOR_READ, 2, 1,(u8*)(&my_characterUUID), (u8*)(&mi_stdio_rx_prop), 0}, //prop {0,ATT_PERMISSIONS_AUTHOR_RDWR, 16,sizeof(mi_stdio_rx_buf),(u8*)(&mi_stdio_rx_uuid), (u8*)(mi_stdio_rx_buf), 0, 0}, //value 0x6D,0x69,0x2E,0x6D,0x69,0x6F,0x74,0x2E,0x62,0x6C,0x65,0x00,0x01,0x01,0x00,0x00 - {0,ATT_PERMISSIONS_AUTHOR_READ, 2, sizeof (mi_stdio_rx_str),(u8*)(&userdesc_UUID), (u8*)(mi_stdio_rx_str), 0}, // STDIO_RX + {0,ATT_PERMISSIONS_AUTHOR_READ, 2, sizeof(mi_stdio_rx_str),(u8*)(&userdesc_UUID), (u8*)(mi_stdio_rx_str), 0}, // STDIO_RX {0,ATT_PERMISSIONS_AUTHOR_RDWR, 2, sizeof(mi_stdio_rx_ccc),(u8*)(&clientCharacterCfgUUID), (u8*)(mi_stdio_rx_ccc), 0}, //value {0,ATT_PERMISSIONS_AUTHOR_READ, 2, 1,(u8*)(&my_characterUUID), (u8*)(&mi_stdio_tx_prop), 0}, //prop {0,ATT_PERMISSIONS_AUTHOR_RDWR, 16, sizeof(mi_stdio_tx_buf),(u8*)(&mi_stdio_tx_uuid), (u8*)(mi_stdio_tx_buf), 0, 0}, //value 0x6D,0x69,0x2E,0x6D,0x69,0x6F,0x74,0x2E,0x62,0x6C,0x65,0x00,0x02,0x01,0x00,0x00 - {0,ATT_PERMISSIONS_AUTHOR_READ, 2, sizeof (mi_stdio_tx_str),(u8*)(&userdesc_UUID), (u8*)(mi_stdio_tx_str), 0}, // STDIO_TX + {0,ATT_PERMISSIONS_AUTHOR_READ, 2, sizeof(mi_stdio_tx_str),(u8*)(&userdesc_UUID), (u8*)(mi_stdio_tx_str), 0}, // STDIO_TX {0,ATT_PERMISSIONS_AUTHOR_RDWR, 2, sizeof(mi_stdio_tx_ccc),(u8*)(&clientCharacterCfgUUID), (u8*)(mi_stdio_tx_ccc), 0}, //value #else // USE_MIHOME_SERVICE //Mi 0x95FE diff --git a/src/app_config.h b/src/app_config.h index de405a5f..f218b582 100644 --- a/src/app_config.h +++ b/src/app_config.h @@ -10,7 +10,7 @@ extern "C" { #define DEVICE_LYWSD03MMC 0x055B // LCD display LYWSD03MMC #define DEVICE_MHO_C401 0x0387 // E-Ink display MHO-C401 #define DEVICE_CGG1 0x0B48 // E-Ink display CGG1-M "Qingping Temp & RH Monitor" -#define DEVICE_CGG1_ver 2022 // =2022 - CGG1-M version 2022 or = 0 - CGG1-M version 2020,2021 +#define DEVICE_CGG1_ver 2022 // =2022 - CGG1-M version 2022, or = 0 - CGG1-M version 2020,2021 #define DEVICE_CGDK2 0x066F // LCD display "Qingping Temp & RH Monitor Lite" #ifndef DEVICE_TYPE @@ -18,12 +18,18 @@ extern "C" { #endif #define BLE_SECURITY_ENABLE 1 // = 1 support pin-code +#define BLE_EXT_ADV 0 // = 1 support extension advertise (Test Only!) #define USE_CLOCK 1 // = 1 display clock, = 0 smile blinking #define USE_TIME_ADJUST 1 // = 1 time correction enabled #define USE_FLASH_MEMO 1 // = 1 flash logger enable #define USE_TRIGGER_OUT 1 // = 1 use trigger out (GPIO_PA5) +#if BLE_EXT_ADV +#define USE_WK_RDS_COUNTER 0 // пока не поддерживается в ext_adv +#else #define USE_WK_RDS_COUNTER USE_TRIGGER_OUT // = 1 wake up when the reed switch is triggered + pulse counter +#endif + #define USE_SECURITY_BEACON 1 // = 1 support encryption beacon (bindkey) #define USE_HA_BLE_BEACON 1 // = 1 https://github.com/custom-components/ble_monitor/issues/548 @@ -390,7 +396,7 @@ extern "C" { #endif // DEVICE_TYPE == ? #if UART_PRINT_DEBUG_ENABLE -#define PRINT_BAUD_RATE 1500000 // real 1000000 +#define PRINT_BAUD_RATE 1500000 // real ~1000000 #define DEBUG_INFO_TX_PIN GPIO_PA7 // SWS #define PA7_DATA_OUT 1 #define PA7_OUTPUT_ENABLE 1 @@ -437,6 +443,8 @@ enum{ #define BLE_HOST_SMP_ENABLE BLE_SECURITY_ENABLE +//#define CHG_CONN_PARAM // test + #include "vendor/common/default_config.h" #if defined(__cplusplus) diff --git a/src/ble.c b/src/ble.c index 178607de..9e89482e 100644 --- a/src/ble.c +++ b/src/ble.c @@ -28,6 +28,21 @@ void bls_set_advertise_prepare(void *p); // add ll_adv.h RAM uint8_t ble_connected; // bit 0 - connected, bit 1 - conn_param_update, bit 2 - paring success, bit 7 - reset of disconnect +#if (BLE_EXT_ADV) // support extension advertise + +#define APP_ADV_SETS_NUMBER 1 // Number of Supported Advertising Sets +#define APP_MAX_LENGTH_ADV_DATA 64 // Maximum Advertising Data Length, (if legacy ADV, max length 31 bytes is enough) +#define APP_MAX_LENGTH_SCAN_RESPONSE_DATA 31 // Maximum Scan Response Data Length, (if legacy ADV, max length 31 bytes is enough) + +RAM u8 app_adv_set_param[ADV_SET_PARAM_LENGTH * APP_ADV_SETS_NUMBER]; // struct ll_ext_adv_t +RAM u8 app_primary_adv_pkt[MAX_LENGTH_PRIMARY_ADV_PKT * APP_ADV_SETS_NUMBER]; +RAM u8 app_secondary_adv_pkt[MAX_LENGTH_SECOND_ADV_PKT * APP_ADV_SETS_NUMBER]; +RAM u8 app_advData[APP_MAX_LENGTH_ADV_DATA * APP_ADV_SETS_NUMBER]; +RAM u8 app_scanRspData[APP_MAX_LENGTH_SCAN_RESPONSE_DATA * APP_ADV_SETS_NUMBER]; +RAM u8 ext_adv_init; // flag ext_adv init +#endif + + uint8_t send_buf[SEND_BUFFER_SIZE]; RAM uint8_t blt_rxfifo_b[64 * 8] = { 0 }; @@ -74,26 +89,50 @@ void ble_disconnect_callback(uint8_t e, uint8_t *p, int n) { tx_measures = 0xff; else tx_measures = 0; +#if (BLE_EXT_ADV) + if (ext_adv_init) { // support extension advertise + //blc_ll_setExtAdvEnable_1(BLC_ADV_ENABLE, 1, ADV_HANDLE0, 0 , 0); + //ev_adv_timeout(0,0,0); + } +#endif } void ble_connect_callback(uint8_t e, uint8_t *p, int n) { (void) e; (void) p; (void) n; // bls_l2cap_setMinimalUpdateReqSendingTime_after_connCreate(1000); ble_connected = 1; + my_periConnParameters.latency = cfg.connect_latency; if (cfg.connect_latency) { my_periConnParameters.intervalMin = CON_INERVAL_LAT; // 16*1.25 = 20 ms my_periConnParameters.intervalMax = CON_INERVAL_LAT; // 16*1.25 = 20 ms } - my_periConnParameters.latency = cfg.connect_latency; my_periConnParameters.timeout = connection_timeout; bls_l2cap_requestConnParamUpdate(my_periConnParameters.intervalMin, my_periConnParameters.intervalMax, my_periConnParameters.latency, my_periConnParameters.timeout); } +#ifdef CHG_CONN_PARAM +int chgConnParameters(void * p) { + rf_packet_att_data_t *req = (rf_packet_att_data_t*) p; + gap_periConnectParams_t * q = (gap_periConnectParams_t *)&req->dat; + if (req->l2cap - 3 == sizeof(my_periConnParameters) + && q->intervalMin >= 7 + && q->intervalMax >= q->intervalMin + && q->timeout > ((q->intervalMax >> 2) + 1)) { + if (q->intervalMax != q->intervalMin) + q->latency = 0; + memcpy(&my_periConnParameters, q, sizeof(my_periConnParameters)); + bls_l2cap_requestConnParamUpdate(q->intervalMin, q->intervalMax, q->latency, q->timeout); + //bls_pm_setManualLatency(q->latency); + } + return 0; +} +#endif + int app_conn_param_update_response(u8 id, u16 result) { if (result == CONN_PARAM_UPDATE_ACCEPT) ble_connected |= 2; else if (result == CONN_PARAM_UPDATE_REJECT) { - // bls_l2cap_requestConnParamUpdate(160, 200, 0, 250); // (200 ms, 250 ms, 0, 2.5 s) + // bls_l2cap_requestConnParamUpdate(160, 200, 0, 2500); // (200 ms, 250 ms, 0, 2.5 s) } return 0; } @@ -135,6 +174,16 @@ int app_advertise_prepare_handler(rf_packet_adv_t * p) { return 1; // = 1 ready to send ADV packet, = 0 not send ADV } +#if (BLE_EXT_ADV) +extern void * ll_module_adv_cb; +_attribute_ram_code_ int _blt_ext_adv_proc (void) { +// ll_ext_adv_t *p = (ll_ext_adv_t *)app_adv_set_param; + blta.adv_duraton_en = 0; + app_advertise_prepare_handler(0); + return blt_ext_adv_proc(); +} +#endif + _attribute_ram_code_ int RxTxWrite(void * p) { cmd_parser(p); return 0; @@ -150,12 +199,42 @@ _attribute_ram_code_ void user_set_rf_power(u8 e, u8 *p, int n) { * blt_event_callback_t(): */ void ev_adv_timeout(u8 e, u8 *p, int n) { (void) e; (void) p; (void) n; - bls_ll_setAdvParam(adv_interval, adv_interval + 10, +#if (BLE_EXT_ADV) + if (ext_adv_init) { // extension advertise + if(ble_connected) + return; + //adv_set: Extended, Connectable_scannable + blc_ll_setExtAdvParam(ADV_HANDLE0, + (cfg.flg2.longrange)? ADV_EVT_PROP_EXTENDED_CONNECTABLE_UNDIRECTED : ADV_EVT_PROP_LEGACY_CONNECTABLE_SCANNABLE_UNDIRECTED, + adv_interval, adv_interval + 10, + BLT_ENABLE_ADV_ALL, // primary advertising channel map + OWN_ADDRESS_PUBLIC, // own address type + BLE_ADDR_PUBLIC, // peer address type + NULL, // * peer address + ADV_FP_NONE, // advertising filter policy + TX_POWER_0dBm, // TODO: advertising TX power cfg.rf_tx_power + (cfg.flg2.longrange)? BLE_PHY_CODED : BLE_PHY_1M, // primary advertising channel PHY type + 0, // secondary advertising minimum skip number + (cfg.flg2.longrange)? BLE_PHY_CODED : BLE_PHY_1M, // secondary advertising channel PHY type + ADV_SID_0, + 1); // scan response notify enable ? + + blc_ll_setExtScanRspData(ADV_HANDLE0, DATA_OPER_COMPLETE, DATA_FRAGM_ALLOWED, + ble_name[0]+1, (uint8_t *) ble_name); + // debug!!! Fix CodedPHY channel? + // blc_ll_setAuxAdvChnIdxByCustomers(20); // auxiliary data channel, must be range of 0~36 + + bls_ll_setScanRspData((uint8_t *) ble_name, ble_name[0]+1); + blc_ll_setExtAdvEnable_1(BLC_ADV_ENABLE, 1, ADV_HANDLE0, 0 , 0); + } else +#endif + { + bls_ll_setAdvParam(adv_interval, adv_interval + 10, ADV_TYPE_CONNECTABLE_UNDIRECTED, OWN_ADDRESS_PUBLIC, 0, NULL, BLT_ENABLE_ADV_ALL, ADV_FP_NONE); - // set_adv_data(); - bls_ll_setScanRspData((uint8_t *) ble_name, ble_name[0]+1); - bls_ll_setAdvEnable(BLC_ADV_ENABLE); //ADV enable + bls_ll_setScanRspData((uint8_t *) ble_name, ble_name[0]+1); + bls_ll_setAdvEnable(BLC_ADV_ENABLE); //ADV enable + } } #if BLE_SECURITY_ENABLE @@ -257,15 +336,36 @@ __attribute__((optimize("-Os"))) void init_ble(void) { blc_ll_initConnection_module(); // connection module must for BLE slave/master blc_ll_initSlaveRole_module(); // slave module: must for BLE slave, blc_ll_initPowerManagement_module(); //pm module: optional - if (cfg.flg2.bt5hgy) { // 2MPhy - blc_ll_init2MPhyCodedPhy_feature(); // mandatory for 2M/Coded PHY - //bls_app_registerEventCallback (BLT_EV_FLAG_PHY_UPDATE, &callback_phy_update_complete_event); - blc_ll_setDefaultPhy(PHY_TRX_PREFER, PHY_PREFER_1M, PHY_PREFER_1M); - //blc_ll_setDefaultPhy(PHY_TRX_PREFER, BLE_PHY_CODED, BLE_PHY_CODED); + if (cfg.flg2.bt5phy) { // 1M, 2M, LongRange PHY + blc_ll_init2MPhyCodedPhy_feature(); //if use 2M or Coded PHY + // set Default Connection Coding blc_ll_setDefaultConnCodingIndication(CODED_PHY_PREFER_S8); - } - if (cfg.flg2.chalg2) // ChannelSelectionAlgorithm 2 + //blc_ll_setDefaultPhy(PHY_TRX_PREFER, BLE_PHY_CODED, BLE_PHY_CODED); + // set Default Connection Coding +#if (BLE_EXT_ADV) + if(cfg.flg2.ext_adv && cfg.flg2.longrange) + blc_ll_setDefaultPhy(PHY_TRX_PREFER, BLE_PHY_CODED, BLE_PHY_CODED); + else +#endif + blc_ll_setDefaultPhy(PHY_TRX_PREFER, PHY_PREFER_1M, PHY_PREFER_1M); blc_ll_initChannelSelectionAlgorithm_2_feature(); + //bls_app_registerEventCallback (BLT_EV_FLAG_PHY_UPDATE, &callback_phy_update_complete_event); + } +#if (BLE_EXT_ADV) + if (cfg.flg2.ext_adv) { // support extension advertise + // init buffers ext adv + // and ll_module_adv_cb = blt_ext_adv_proc; pFunc_ll_SetAdv_Enable = ll_setExtAdv_Enable; + blc_ll_initExtendedAdvertising_module(app_adv_set_param, app_primary_adv_pkt, APP_ADV_SETS_NUMBER); + blc_ll_initExtSecondaryAdvPacketBuffer(app_secondary_adv_pkt, MAX_LENGTH_SECOND_ADV_PKT); + blc_ll_initExtAdvDataBuffer(app_advData, APP_MAX_LENGTH_ADV_DATA); + blc_ll_initExtScanRspDataBuffer(app_scanRspData, APP_MAX_LENGTH_SCAN_RESPONSE_DATA); + // if Coded PHY is used, this API set default S2/S8 mode for Extended ADV + blc_ll_setDefaultExtAdvCodingIndication(ADV_HANDLE0, CODED_PHY_PREFER_S8); + ll_module_adv_cb = _blt_ext_adv_proc; + ext_adv_init = 1; + } else + ext_adv_init = 0; +#endif ////// Host Initialization ////////// blc_gap_peripheral_init(); my_att_init(); //gatt initialization @@ -390,6 +490,22 @@ void set_adv_data(void) { } } adv_buf.data_size = adv_buf.data[0] + 1; + +#if (BLE_EXT_ADV) + if (ext_adv_init) { // support extension advertise + memcpy(&adv_buf.data[adv_buf.data_size], ble_name, ble_name[0] + 1); + u8 *p; + u8 size = adv_buf.data_size + ble_name[0] + 1; + if (cfg.flg2.adv_flags) { + p = adv_buf.flag; + size += sizeof(adv_buf.flag); + } else { + p = adv_buf.data; + } + blc_ll_setExtAdvData(ADV_HANDLE0, DATA_OPER_COMPLETE, DATA_FRAGM_ALLOWED, size, p); + return; + } +#endif if (cfg.flg2.adv_flags) { bls_ll_setAdvData((u8 *)&adv_buf.flag, adv_buf.data_size + sizeof(adv_buf.flag)); } else { diff --git a/src/ble.h b/src/ble.h index 92a33f52..37a295e1 100644 --- a/src/ble.h +++ b/src/ble.h @@ -12,8 +12,12 @@ extern uint8_t ota_is_working; extern uint8_t ble_connected; // bit 0 - connected, bit 1 - conn_param_update, bit 2 - paring success, bit 7 - reset device on disconnect //extern uint32_t adv_send_count; - +#if (BLE_EXT_ADV) +#define ADV_BUFFER_SIZE (62-3) +extern u8 ext_adv_init; // flag ext_adv init +#else #define ADV_BUFFER_SIZE (31-3) +#endif typedef struct _adv_buf_t { uint32_t send_count; // count & id advertise, = beacon_nonce.cnt32 uint16_t old_measured_count; // old measured_data.count @@ -197,6 +201,9 @@ void ble_send_trg_flg(void); void send_memo_blk(void); #endif int otaWritePre(void * p); +#ifdef CHG_CONN_PARAM +int chgConnParameters(void * p); +#endif int RxTxWrite(void * p); void ev_adv_timeout(u8 e, u8 *p, int n); void set_pvvx_adv_data(void); diff --git a/src/cmd_parser.c b/src/cmd_parser.c index 0a4a6838..1c697c32 100644 --- a/src/cmd_parser.c +++ b/src/cmd_parser.c @@ -292,7 +292,7 @@ __attribute__((optimize("-Os"))) void cmd_parser(void * p) { ble_send_ext(); } else if (cmd == CMD_ID_CFG || cmd == CMD_ID_CFG_NS) { // Get/set config if (--len > sizeof(cfg)) len = sizeof(cfg); - u8 x = ((u8 *)&cfg.flg2)[0]; + u8 tmp = ((volatile u8 *)&cfg.flg2)[0]; if (len) { memcpy(&cfg, &req->dat[1], len); } @@ -301,14 +301,15 @@ __attribute__((optimize("-Os"))) void cmd_parser(void * p) { ev_adv_timeout(0, 0, 0); if (cmd != CMD_ID_CFG_NS) { // Get/set config (not save to Flash) flash_write_cfg(&cfg, EEP_ID_CFG, sizeof(cfg)); - x ^= ((u8 *)&cfg.flg2)[0]; - if(x & 0x60) // (cfg.flg2.bt5hgy || cfg.flg2.chalg2) + if((tmp ^ ((volatile u8 *)&cfg.flg2)[0]) & MASK_FLG2_REBOOT) { // (cfg.flg2.bt5phy || cfg.flg2.ext_adv) ble_connected |= 0x80; // reset device on disconnect + } } ble_send_cfg(); } else if (cmd == CMD_ID_CFG_DEF) { // Set default config - if (cfg.flg2.bt5hgy || cfg.flg2.chalg2) + if((((u8 *)&cfg.flg2)[0] ^ ((u8 *)&def_cfg.flg2)[0]) & MASK_FLG2_REBOOT) { // (cfg.flg2.bt5phy || cfg.flg2.ext_adv) ble_connected |= 0x80; // reset device on disconnect + } memcpy(&cfg, &def_cfg, sizeof(cfg)); test_config(); set_hw_version(); @@ -492,7 +493,7 @@ __attribute__((optimize("-Os"))) void cmd_parser(void * p) { } #endif } else if (cmd == CMD_ID_MTU && len > 1) { // Request Mtu Size Exchange - if (req->dat[1] > ATT_MTU_SIZE) + if (req->dat[1] >= ATT_MTU_SIZE) send_buf[1] = blc_att_requestMtuSizeExchange(BLS_CONN_HANDLE, req->dat[1]); else send_buf[1] = 0xff; diff --git a/src/custom_beacon.c b/src/custom_beacon.c index 2fb78d47..0799d2c9 100644 --- a/src/custom_beacon.c +++ b/src/custom_beacon.c @@ -154,7 +154,7 @@ typedef struct __attribute__((packed)) _adv_event_t { ext_adv_cnt_t cnt; } adv_event_t, * padv_event_t; - +#if USE_WK_RDS_COUNTER void atc_event_beacon(void){ padv_event_t p = (padv_event_t)&adv_buf.data; p->dig.size = sizeof(p->dig) - sizeof(p->dig.size); @@ -190,6 +190,6 @@ void pvvx_encrypt_event_beacon(uint8_t n){ void atc_encrypt_event_beacon(void){ atc_event_beacon(); } - +#endif // USE_WK_RDS_COUNTER #endif // USE_SECURITY_BEACON #endif // USE_TRIGGER_OUT diff --git a/src/epd_cgg1_2022.c b/src/epd_cgg1_2022.c index 09b07bba..35606203 100644 --- a/src/epd_cgg1_2022.c +++ b/src/epd_cgg1_2022.c @@ -423,4 +423,4 @@ _attribute_ram_code_ __attribute__((optimize("-Os"))) int task_lcd(void) { return stage_lcd; } -#endif // DEVICE_TYPE == DEVICE_MHO_C401 +#endif // ((DEVICE_TYPE == DEVICE_CGG1) && (DEVICE_CGG1_ver == 2022)) diff --git a/src/ha_ble_beacon.c b/src/ha_ble_beacon.c index 3efa025d..ec7e0654 100644 --- a/src/ha_ble_beacon.c +++ b/src/ha_ble_beacon.c @@ -94,7 +94,7 @@ void ha_ble_encrypt_data_beacon(void) { } } -#if USE_TRIGGER_OUT +#if USE_TRIGGER_OUT && USE_WK_RDS_COUNTER _attribute_ram_code_ __attribute__((optimize("-Os"))) void ha_ble_encrypt_event_beacon(uint8_t n) { uint8_t buf[20]; @@ -153,7 +153,7 @@ void ha_ble_data_beacon(void) { } } -#if USE_TRIGGER_OUT +#if USE_TRIGGER_OUT && USE_WK_RDS_COUNTER _attribute_ram_code_ __attribute__((optimize("-Os"))) void ha_ble_event_beacon(uint8_t n) { padv_ha_ble_ns_ev1_t p = (padv_ha_ble_ns_ev1_t)&adv_buf.data; diff --git a/src/i2c.c b/src/i2c.c index b57e831f..9e69bbfb 100644 --- a/src/i2c.c +++ b/src/i2c.c @@ -7,9 +7,12 @@ _attribute_ram_code_ void init_i2c(void){ i2c_gpio_set(I2C_GROUP); // I2C_GPIO_GROUP_C0C1, I2C_GPIO_GROUP_C2C3, I2C_GPIO_GROUP_B6D7, I2C_GPIO_GROUP_A3A4 + + // i2c clock = system_clock/(4*DivClock) // i2c_master_init(0x78, (uint8_t)(CLOCK_SYS_CLOCK_HZ/(4*750000)) ); - reg_i2c_speed = (uint8_t)(CLOCK_SYS_CLOCK_HZ/(4*750000)); //i2c clock = system_clock/(4*DivClock) - //reg_i2c_id = ?; //slave address + // SHTC3 Max. SCL clock frequency 1 MHz + reg_i2c_speed = (uint8_t)(CLOCK_SYS_CLOCK_HZ/(4*750000)); // 750 kHz + //reg_i2c_id = slave address reg_i2c_mode |= FLD_I2C_MASTER_EN; //enable master mode reg_i2c_mode &= ~FLD_I2C_HOLD_MASTER; // Disable clock stretching for Sensor @@ -17,15 +20,6 @@ _attribute_ram_code_ void init_i2c(void){ reg_spi_sp &= ~FLD_SPI_ENABLE; //force PADs act as I2C; i2c and spi share the hardware of IC } -/* -void send_i2c(uint8_t device_id, uint8_t *buffer, int dataLen){ - if((reg_clk_en0 & FLD_CLK0_I2C_EN)==0) - init_i2c(); - i2c_set_id(device_id); - i2c_write_series(0, 0, (uint8_t*)buffer,dataLen); -} -*/ - int scan_i2c_addr(int address) { if ((reg_clk_en0 & FLD_CLK0_I2C_EN)==0) init_i2c(); diff --git a/src/mi_beacon.c b/src/mi_beacon.c index abec075e..c1f2a77e 100644 --- a/src/mi_beacon.c +++ b/src/mi_beacon.c @@ -55,7 +55,7 @@ RAM mib_summ_data_t mib_summ_data; /* Initializing data for mi beacon */ void mi_beacon_init(void) { memcpy(beacon_nonce.mac, mac_public, 6); - beacon_nonce.pid = DEVICE_TYPE; + beacon_nonce.pid = XIAOMI_DID; } /* Averaging measurements */ @@ -145,14 +145,14 @@ void mi_encrypt_data_beacon(void) { *pmic++ = beacon_nonce.ext_cnt[1]; *pmic++ = beacon_nonce.ext_cnt[2]; uint8_t aad = 0x11; - aes_ccm_encrypt_and_tag((const unsigned char *)&bindkey, - (uint8_t*)&beacon_nonce, sizeof(beacon_nonce), - &aad, sizeof(aad), - (uint8_t *)&data, data.size + sizeof(p->data.id) + sizeof(p->data.size), // + size data head - (uint8_t *)&p->data, - pmic, 4); + aes_ccm_encrypt_and_tag((const unsigned char *)&bindkey, // указатель на ключ, аналог от MiHome + (uint8_t*)&beacon_nonce, sizeof(beacon_nonce), // MAC и всякие ID устройства, 32-х битный счетчик + &aad, sizeof(aad), // add = 0x11 + (uint8_t *)&data, data.size + sizeof(p->data.id) + sizeof(p->data.size), // + size data head, указатель на шифруемые данные + (uint8_t *)&p->data, // указатель куда писать результат + pmic, 4); // указатель куда писать типа подпись-"контрольную сумму" шифра } - +#if USE_WK_RDS_COUNTER void mi_encrypt_event_beacon(uint8_t n) { padv_mi_cr_ev1_t p = (padv_mi_cr_ev1_t)&adv_buf.data; uint8_t * pmic; @@ -169,7 +169,7 @@ void mi_encrypt_event_beacon(uint8_t n) { #else p->head.fctrl.word = 0x5848; // 0x5848 version = 5, encrypted, no MACInclude, ObjectInclude, AuthMode 2 #endif - p->head.dev_id = DEVICE_TYPE; + p->head.dev_id = XIAOMI_DID; p->head.counter = (uint8_t)adv_buf.send_count; if (n == RDS_SWITCH) { p->head.size = sizeof(adv_mi_cr_ev1_t) - sizeof(p->head.size); @@ -199,6 +199,7 @@ void mi_encrypt_event_beacon(uint8_t n) { (uint8_t *)&p->data, pmic, 4); } +#endif // USE_WK_RDS_COUNTER #endif // USE_SECURITY_BEACON /* Create mi beacon packet */ @@ -219,7 +220,7 @@ void mi_data_beacon(void) { #else p->head.fctrl.word = 0x5850; // 0x5850 version = 5, not encrypted, MACInclude, ObjectInclude, AuthMode 2 #endif - p->head.dev_id = DEVICE_TYPE; + p->head.dev_id = XIAOMI_DID; if (adv_buf.call_count < cfg.measure_interval) { p->data.id = XIAOMI_DATA_ID_TempAndHumidity; p->data.size = 4; @@ -236,7 +237,7 @@ void mi_data_beacon(void) { p->head.size = p->data.size + sizeof(p->head) - sizeof(p->head.size) + sizeof(p->MAC) + sizeof(p->data.id) + sizeof(p->data.size); } -#if USE_TRIGGER_OUT +#if USE_TRIGGER_OUT && USE_WK_RDS_COUNTER /* Create mi event beacon packet */ __attribute__((optimize("-Os"))) void mi_event_beacon(uint8_t n){ @@ -254,7 +255,7 @@ void mi_event_beacon(uint8_t n){ #else p->head.fctrl.word = 0x5840; // 0x5840 version = 5, not encrypted, no MACInclude, ObjectInclude, AuthMode 2 #endif - p->head.dev_id = DEVICE_TYPE; + p->head.dev_id = XIAOMI_DID; p->head.counter = (uint8_t)adv_buf.send_count; if (n == RDS_SWITCH) { p->head.size = sizeof(adv_mi_ev1_t) - sizeof(p->head.size); diff --git a/src/mi_beacon.h b/src/mi_beacon.h index 6521d49c..9cd71a80 100644 --- a/src/mi_beacon.h +++ b/src/mi_beacon.h @@ -34,6 +34,18 @@ enum { XIAOMI_DEV_ID_MJYD02YL = 0x07F6 }XIAOMI_DEV_ID; +#if DEVICE_TYPE == DEVICE_LYWSD03MMC +#define XIAOMI_DID XIAOMI_DEV_ID_LYWSD03MMC // 0x055B LCD display LYWSD03MMC +#elif DEVICE_TYPE == DEVICE_MHO_C401 +#define XIAOMI_DID XIAOMI_DEV_ID_MHO_C401 // 0x0387 E-Ink display MHO-C401 +#elif DEVICE_TYPE == DEVICE_CGG1 +#define XIAOMI_DID XIAOMI_DEV_ID_CGG1_ENCRYPTED // 0x0B48 E-Ink display CGG1-M "Qingping Temp & RH Monitor" +#elif DEVICE_TYPE == DEVICE_CGDK2 +#define XIAOMI_DID XIAOMI_DEV_ID_CGDK2 // 0x066F LCD display "Qingping Temp & RH Monitor Lite" +#else +#define XIAOMI_DID XIAOMI_DEV_ID_LYWSD03MMC +#endif + enum { // mijia ble version 5, General events XIAOMI_DATA_EV_Base =0x0000, XIAOMI_DATA_EV_Connect =0x0001, diff --git a/src/rds_count.c b/src/rds_count.c index da753122..09be5037 100644 --- a/src/rds_count.c +++ b/src/rds_count.c @@ -92,23 +92,72 @@ void set_rds_adv_data(void) { } } adv_buf.update_count = 0; // refresh adv_buf.data in next set_adv_data() +#if (BLE_EXT_ADV) +#if 0 // Not Work! SDK only 1 ext_adv... + if (ext_adv_init) { // support extension advertise + blc_ll_setExtAdvData(ADV_HANDLE0, DATA_OPER_COMPLETE, DATA_FRAGM_ALLOWED, + adv_buf.data_size, (u8 *)&adv_buf.data); + } else +#endif +#endif bls_ll_setAdvData((u8 *)&adv_buf.data, adv_buf.data_size); } _attribute_ram_code_ static void start_ext_adv(void) { - bls_ll_setAdvEnable(BLC_ADV_DISABLE); // adv disable - bls_ll_setAdvParam(EXT_ADV_INTERVAL, EXT_ADV_INTERVAL, -#if 1 - ADV_TYPE_NONCONNECTABLE_UNDIRECTED, OWN_ADDRESS_PUBLIC, 0, NULL, -#else - ADV_TYPE_CONNECTABLE_UNDIRECTED, OWN_ADDRESS_PUBLIC, 0, NULL, -#endif - BLT_ENABLE_ADV_ALL, ADV_FP_NONE); - set_rds_adv_data(); - adv_buf.data_size = 0; // flag adv_buf.send_count++ - bls_ll_setAdvDuration(EXT_ADV_INTERVAL*(EXT_ADV_COUNT-1)*625+33, 1); - blta.adv_interval = 0; // system tick - bls_ll_setAdvEnable(BLC_ADV_ENABLE); // adv enable + +#if (BLE_EXT_ADV) +#if 0 // Not Work! SDK only 1 ext_adv... + if (ext_adv_init) { // support extension advertise + blc_ll_setExtAdvEnable_1(BLC_ADV_DISABLE, 1, ADV_HANDLE0, 0, 0); + //blc_ll_removeAdvSet(ADV_HANDLE0); + //blc_ll_clearAdvSets(); + //adv_set: Extended, Connectable_scannable + blc_ll_setExtAdvParam(ADV_HANDLE0, + ADV_EVT_PROP_LEGACY_CONNECTABLE_SCANNABLE_UNDIRECTED, + EXT_ADV_INTERVAL, EXT_ADV_INTERVAL, + BLT_ENABLE_ADV_ALL, // primary advertising channel map + OWN_ADDRESS_PUBLIC, // own address type + BLE_ADDR_PUBLIC, // peer address type + NULL, // * peer address + ADV_FP_NONE, // advertising filter policy + TX_POWER_0dBm, // TODO: advertising TX power cfg.rf_tx_power + BLE_PHY_1M, // primary advertising channel PHY type + 0, // secondary advertising minimum skip number + BLE_PHY_CODED, // primary advertising channel PHY type + ADV_SID_0, + 0); // scan response notify enable ? + + blc_ll_setExtScanRspData(ADV_HANDLE0, DATA_OPER_COMPLETE, DATA_FRAGM_ALLOWED, + ble_name[0]+1, (uint8_t *) ble_name); + + set_rds_adv_data(); + adv_buf.data_size = 0; // flag adv_buf.send_count++ in app_advertise_prepare_handler() + + // if Coded PHY is used, this API set default S2/S8 mode for Extended ADV + //blc_ll_setDefaultExtAdvCodingIndication(ADV_HANDLE0, CODED_PHY_PREFER_S8); + + // debug!!! + //blc_ll_setAuxAdvChnIdxByCustomers(20); // auxiliary data channel, must be range of 0~36 + + blta.adv_duraton_en = EXT_ADV_COUNT-2; + blta.adv_interval = 0; // system tick + // Time = N * 10 ms, Time Range: 10 ms to 655,350 ms + blc_ll_setExtAdvEnable_1(BLC_ADV_ENABLE, 1, ADV_HANDLE0, (EXT_ADV_INTERVAL*(EXT_ADV_COUNT-1)*625+35)/10000 , EXT_ADV_COUNT); + } else + +#endif +#endif + { + bls_ll_setAdvEnable(BLC_ADV_DISABLE); // adv disable + bls_ll_setAdvParam(EXT_ADV_INTERVAL, EXT_ADV_INTERVAL, + ADV_TYPE_NONCONNECTABLE_UNDIRECTED, OWN_ADDRESS_PUBLIC, 0, NULL, + BLT_ENABLE_ADV_ALL, ADV_FP_NONE); + set_rds_adv_data(); + adv_buf.data_size = 0; // flag adv_buf.send_count++ + bls_ll_setAdvDuration(EXT_ADV_INTERVAL*(EXT_ADV_COUNT-1)*625+33, 1); + blta.adv_interval = 0; // system tick + bls_ll_setAdvEnable(BLC_ADV_ENABLE); // adv enable + } } _attribute_ram_code_ void rds_suspend(void) { diff --git a/src/sensor.h b/src/sensor.h index b2e0d71c..6c2879dc 100644 --- a/src/sensor.h +++ b/src/sensor.h @@ -11,11 +11,10 @@ extern volatile uint32_t timer_measure_cb; // time start measure extern uint8_t sensor_i2c_addr; -void init_sensor(); +void init_sensor(void); void start_measure_sensor_deep_sleep(void); void start_measure_sensor_low_power(void); int read_sensor_cb(void); -void soft_reset_sensor(void); void sensor_go_sleep(void); diff --git a/src/sensors.c b/src/sensors.c index d9139544..bddcc449 100644 --- a/src/sensors.c +++ b/src/sensors.c @@ -54,31 +54,45 @@ static _attribute_ram_code_ void send_sensor_byte(uint8_t cmd) { while (reg_i2c_status & FLD_I2C_CMD_BUSY); } -void soft_reset_sensor(void) { +_attribute_ram_code_ void sensor_go_sleep(void) { + if (sensor_i2c_addr == (SHTC3_I2C_ADDR << 1)) + send_sensor_word(SHTC3_GO_SLEEP); // Sleep command of the sensor +} + +static void soft_reset_sensor(void) { if (sensor_i2c_addr == (SHTC3_I2C_ADDR << 1)) { send_sensor_word(SHTC3_SOFT_RESET); // Soft reset command sleep_us(SHTC3_SOFT_RESET_us); // 240 us - send_sensor_word(SHTC3_GO_SLEEP); // Sleep command of the sensor } else if ((sensor_i2c_addr) == SHT4x_I2C_ADDR << 1) { send_sensor_byte(SHT4x_SOFT_RESET); // Soft reset command sleep_us(SHT4x_SOFT_RESET_us); // max 1 ms } } -void init_sensor() { +static int check_sensor(void) { if ((sensor_i2c_addr = (uint8_t) scan_i2c_addr(SHTC3_I2C_ADDR << 1)) != 0) { - //send_sensor_word(SHTC3_WAKEUP); // Wake-up command of the sensor - //sleep_us(SHTC3_WAKEUP_us); // 240 us cfg.hw_cfg.shtc3 = 1; // = 1 - sensor SHTC3 - soft_reset_sensor(); - return; - } - cfg.hw_cfg.shtc3 = 0; // = 0 - sensor SHT4x or ? - if ((sensor_i2c_addr = (uint8_t) scan_i2c_addr(SHT4x_I2C_ADDR << 1)) != 0) { - soft_reset_sensor(); - return; + } else { + sensor_i2c_addr = (uint8_t) scan_i2c_addr(SHT4x_I2C_ADDR << 1); + cfg.hw_cfg.shtc3 = 0; // = 0 - sensor SHT4x or ? } + soft_reset_sensor(); // no i2c sensor ? sensor_i2c_addr = 0 + return sensor_i2c_addr; +} + +void init_sensor(void) { + // SMBus ALERT + sensor_i2c_addr = 0; + send_sensor_byte(0x80); + // Reset command using the general call address + send_sensor_byte(0x06); + sleep_us(SHTC3_WAKEUP_us); // 240 us + // Wake-up command of the SHTC3 sensor + sensor_i2c_addr = SHTC3_I2C_ADDR << 1; + send_sensor_word(SHTC3_WAKEUP); + sleep_us(SHTC3_WAKEUP_us); // 240 us + check_sensor(); } _attribute_ram_code_ __attribute__((optimize("-Os"))) int read_sensor_cb(void) { @@ -93,7 +107,8 @@ _attribute_ram_code_ __attribute__((optimize("-Os"))) int read_sensor_cb(void) { reg_i2c_speed = (uint8_t)(CLOCK_SYS_CLOCK_HZ/(4*750000)); #endif if (sensor_i2c_addr == 0) { - init_sensor(); + if(check_sensor()) + sensor_go_sleep(); return 0; } reg_i2c_id = sensor_i2c_addr | FLD_I2C_WRITE_READ_BIT; @@ -147,6 +162,7 @@ _attribute_ram_code_ __attribute__((optimize("-Os"))) int read_sensor_cb(void) { if (measured_data.humi < 0) measured_data.humi = 0; else if (measured_data.humi > 9999) measured_data.humi = 9999; measured_data.count++; + // sensor_go_sleep(); // Sleep command of the sensor if (sensor_i2c_addr == (SHTC3_I2C_ADDR << 1)) send_sensor_word(SHTC3_GO_SLEEP); // Sleep command of the sensor return 1; @@ -154,6 +170,7 @@ _attribute_ram_code_ __attribute__((optimize("-Os"))) int read_sensor_cb(void) { } } while (i--); soft_reset_sensor(); + sensor_go_sleep(); return 0; } @@ -183,8 +200,3 @@ _attribute_ram_code_ void start_measure_sensor_low_power(void) { sleep_us(SHT4x_MEASURE_LO_us); // 1700 us } } - -_attribute_ram_code_ void sensor_go_sleep(void) { - if (sensor_i2c_addr == (SHTC3_I2C_ADDR << 1)) - send_sensor_word(SHTC3_GO_SLEEP); // Sleep command of the sensor -}