v1.6 beta
This commit is contained in:
parent
a923194d70
commit
fd56473035
26 changed files with 18486 additions and 58 deletions
|
|
@ -51,6 +51,7 @@ Custom firmware for Tuya devices on the PHY622x2 chipset
|
|||
| 1.3 | Добавлен THB1 и TH05V1.3. Следующий этап уменьшения потребления для версий с LCD дисплеем и опция отключения дисплея. |
|
||||
| 1.4 | Стабилизация соединения для всех вариантов устройств. Добавлен [TH05F](https://pvvx.github.io/TH05F). Коррекция хода RTC. Изменено BLE имя для TH05_V1.3 на "TH05D". Добавлены файлы для обновления Boot по OTA. |
|
||||
| 1.5 | Добавлен вариант шифрования BLE рекламы с помощью BindKey. |
|
||||
| 1.6 | Добавлен усреднение расчета напряжения батареи, дублирование состояния контакта open/close и счетчика через 12..20 сек (кратно интервалу рекламы) после срабатывания и далее каждые 30 минут. |
|
||||
|
||||
## Прошивка
|
||||
|
||||
|
|
|
|||
3013
bin/BOOT_BTH01_v16.hex
Normal file
3013
bin/BOOT_BTH01_v16.hex
Normal file
File diff suppressed because it is too large
Load diff
3083
bin/BOOT_TH05D_v16.hex
Normal file
3083
bin/BOOT_TH05D_v16.hex
Normal file
File diff suppressed because it is too large
Load diff
3080
bin/BOOT_TH05F_v16.hex
Normal file
3080
bin/BOOT_TH05F_v16.hex
Normal file
File diff suppressed because it is too large
Load diff
3078
bin/BOOT_TH05_v16.hex
Normal file
3078
bin/BOOT_TH05_v16.hex
Normal file
File diff suppressed because it is too large
Load diff
3075
bin/BOOT_THB1_v16.hex
Normal file
3075
bin/BOOT_THB1_v16.hex
Normal file
File diff suppressed because it is too large
Load diff
3011
bin/BOOT_THB2_v16.hex
Normal file
3011
bin/BOOT_THB2_v16.hex
Normal file
File diff suppressed because it is too large
Load diff
BIN
bin/BTH01_v16.bin
Normal file
BIN
bin/BTH01_v16.bin
Normal file
Binary file not shown.
BIN
bin/TH05D_v16.bin
Normal file
BIN
bin/TH05D_v16.bin
Normal file
Binary file not shown.
BIN
bin/TH05F_v16.bin
Normal file
BIN
bin/TH05F_v16.bin
Normal file
Binary file not shown.
BIN
bin/TH05_v16.bin
Normal file
BIN
bin/TH05_v16.bin
Normal file
Binary file not shown.
BIN
bin/THB1_v16.bin
Normal file
BIN
bin/THB1_v16.bin
Normal file
Binary file not shown.
BIN
bin/THB2_v16.bin
Normal file
BIN
bin/THB2_v16.bin
Normal file
Binary file not shown.
|
|
@ -1,5 +1,5 @@
|
|||
@set PATH=D:\MCU\GNU_Tools_ARM_Embedded\13.2.rel1\bin;%PATH%
|
||||
@set SWVER=_v15
|
||||
@set SWVER=_v16
|
||||
@del /Q "build\THB2%SWVER%.hex"
|
||||
@del /Q "build\THB2%SWVER%.bin"
|
||||
@mkdir .\bin
|
||||
|
|
|
|||
|
|
@ -20,8 +20,22 @@
|
|||
*/
|
||||
#define MIN_ADC_CH 2
|
||||
|
||||
//--- check battery
|
||||
#define BAT_AVERAGE1_SHL 3 // 8*4 = 32 минуты если шаг измерения 60 сек
|
||||
#define BAT_AVERAGE1_COUNT (1 << BAT_AVERAGE1_SHL) // 8
|
||||
#define BAT_AVERAGE2_SHL 2
|
||||
#define BAT_AVERAGE2_COUNT (1 << BAT_AVERAGE2_SHL) // 4
|
||||
struct {
|
||||
uint32_t buf2[BAT_AVERAGE2_COUNT];
|
||||
uint16_t buf1[BAT_AVERAGE1_COUNT];
|
||||
uint16_t battery_mv;
|
||||
uint8_t index1;
|
||||
uint8_t index2;
|
||||
} bat_average;
|
||||
|
||||
static void init_adc_batt(void);
|
||||
|
||||
__ATTR_SECTION_SRAM__
|
||||
void __attribute__((used)) hal_ADC_IRQHandler(void) {
|
||||
uint32_t adc_sum = 0, i;
|
||||
//int status = AP_ADCC->intr_status;
|
||||
|
|
@ -56,17 +70,11 @@ void __attribute__((used)) hal_ADC_IRQHandler(void) {
|
|||
AP_IOMUX->pad_ps0 &= ~BIT(ADC_PIN); // hal_gpio_ds_control(ADC_PIN, Bit_ENABLE);
|
||||
LOG("ADC_measure = %d\n", adc_sum);
|
||||
#if ADC_VBAT_CHL == VBAT_ADC_P15
|
||||
measured_data.battery_mv = (adc_sum * 1710) >> 16; // 3200*65536/(30*4096)=1706.666
|
||||
bat_average.battery_mv = (adc_sum * 1710) >> 16; // 3200*65536/(30*4096)=1706.666
|
||||
#else
|
||||
measured_data.battery_mv = (adc_sum * 1904) >> 16;
|
||||
bat_average.battery_mv = (adc_sum * 1904) >> 16;
|
||||
#endif
|
||||
if (measured_data.battery_mv < 3000)
|
||||
if (measured_data.battery_mv > 2000)
|
||||
measured_data.battery = (measured_data.battery_mv - 2000) / 10;
|
||||
else
|
||||
measured_data.battery = 0;
|
||||
else
|
||||
measured_data.battery = 100;
|
||||
adv_wrk.new_battery = 1; // new battery
|
||||
#if ((DEV_SERVICES & SERVICE_THS) == 0)
|
||||
measured_data.count++;
|
||||
#endif
|
||||
|
|
@ -152,3 +160,44 @@ static void init_adc_batt(void) {
|
|||
AP_IOMUX->Analog_IO_en |= BIT(ADC_PIN - P11); // hal_gpio_cfg_analog_io(ADC_PIN, Bit_ENABLE);
|
||||
#endif
|
||||
}
|
||||
|
||||
void check_battery(void) {
|
||||
uint32_t i;
|
||||
uint32_t summ;
|
||||
if(bat_average.battery_mv == 0)
|
||||
return;
|
||||
//if (bat_average.battery_mv < 2000) // It is not recommended to write Flash below 2V
|
||||
// low_vbat(); // TODO
|
||||
if(bat_average.buf1[0] == 0) {
|
||||
for(i = 0; i < BAT_AVERAGE1_COUNT; i++)
|
||||
bat_average.buf1[i] = bat_average.battery_mv;
|
||||
summ = bat_average.battery_mv << BAT_AVERAGE1_SHL;
|
||||
for(i = 0; i < BAT_AVERAGE2_COUNT; i++)
|
||||
bat_average.buf2[i] = summ;
|
||||
measured_data.battery_mv = bat_average.battery_mv;
|
||||
} else {
|
||||
bat_average.index1++;
|
||||
bat_average.index1 &= BAT_AVERAGE1_COUNT - 1;
|
||||
if(bat_average.index1 == 0) {
|
||||
bat_average.index2++;
|
||||
bat_average.index2 &= BAT_AVERAGE2_COUNT - 1;
|
||||
}
|
||||
bat_average.buf1[bat_average.index1] = bat_average.battery_mv;
|
||||
summ = 0;
|
||||
for(i = 0; i < BAT_AVERAGE1_COUNT; i++)
|
||||
summ += bat_average.buf1[i];
|
||||
bat_average.buf2[bat_average.index2] = summ;
|
||||
summ = 0;
|
||||
for(i = 0; i < BAT_AVERAGE2_COUNT; i++)
|
||||
summ += bat_average.buf2[i];
|
||||
measured_data.battery_mv = summ >> (BAT_AVERAGE1_SHL + BAT_AVERAGE2_SHL);
|
||||
}
|
||||
if (measured_data.battery_mv < 3000)
|
||||
if (measured_data.battery_mv > 2000)
|
||||
measured_data.battery = (measured_data.battery_mv - 2000) / 10;
|
||||
else
|
||||
measured_data.battery = 0;
|
||||
else
|
||||
measured_data.battery = 100;
|
||||
bat_average.battery_mv = 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@
|
|||
#define VBAT_ADC_P20 7
|
||||
|
||||
void batt_start_measure(void);
|
||||
void check_battery(void);
|
||||
|
||||
#endif
|
||||
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@
|
|||
// #include "bus_dev.h"
|
||||
|
||||
#ifndef APP_VERSION
|
||||
#define APP_VERSION 0x15 // BCD
|
||||
#define APP_VERSION 0x14 // BCD
|
||||
#endif
|
||||
|
||||
/* rf_phy_ana_cfg
|
||||
|
|
@ -52,7 +52,7 @@
|
|||
#define SERVICE_OTA 0x00000001 // есть функция OTA
|
||||
#define SERVICE_OTA_EXT 0x00000002 // пока нет // есть расширенная функция OTA
|
||||
#define SERVICE_PINCODE 0x00000004 // пока нет // есть установка pin-code
|
||||
#define SERVICE_BINDKEY 0x00000008 // пока нет // есть шифрование
|
||||
#define SERVICE_BINDKEY 0x00000008 // есть шифрование
|
||||
#define SERVICE_HISTORY 0x00000010 // есть запись истории
|
||||
#define SERVICE_SCREEN 0x00000020 // есть экран
|
||||
#define SERVICE_LE_LR 0x00000040 // пока нет // Есть поддержка рекламы в LE Long Range
|
||||
|
|
@ -380,12 +380,13 @@ typedef struct _adv_work_t {
|
|||
uint32_t measure_interval_ms;
|
||||
uint32_t measure_batt_tik;
|
||||
#if (DEV_SERVICES & SERVICE_RDS)
|
||||
uint32_t rds_timer_tik;
|
||||
uint32_t rds_count;
|
||||
#endif
|
||||
uint8_t adv_meas_count;
|
||||
uint8_t meas_count;
|
||||
uint8_t adv_reload_count;
|
||||
uint8_t adv_batt_count;
|
||||
uint8_t adv_event;
|
||||
uint8_t new_battery; // new battery
|
||||
uint8_t adv_event; // rds event
|
||||
} adv_work_t;
|
||||
extern adv_work_t adv_wrk;
|
||||
|
||||
|
|
|
|||
|
|
@ -214,60 +214,73 @@ static void set_adv_interval(uint16_t advInt)
|
|||
|
||||
//extern void start_measure(void);
|
||||
|
||||
|
||||
static void adv_measure(void) {
|
||||
|
||||
if(gapRole_AdvEnabled) {
|
||||
get_utc_time_sec(); // счет UTC timestamp
|
||||
#if (DEV_SERVICES & SERVICE_RDS)
|
||||
if(!adv_wrk.adv_event) {
|
||||
if(clkt.utc_time_tik - adv_wrk.rds_timer_tik >= (RDS_STEP_TIMER_SEC << 15)) {
|
||||
adv_wrk.rds_timer_tik = clkt.utc_time_tik;
|
||||
adv_wrk.adv_event = 1;
|
||||
adv_wrk.adv_reload_count = RDS_RETRY_ADV_COUNT;
|
||||
LL_SetAdvData(bthome_data_beacon((void *) gapRole_AdvertData), gapRole_AdvertData);
|
||||
set_new_adv_interval(DEF_EVENT_ADV_INERVAL); // actual time * 625us
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
if(clkt.utc_time_tik - adv_wrk.measure_batt_tik >= ((uint32_t)cfg.batt_interval << 15)) {
|
||||
adv_wrk.measure_batt_tik = clkt.utc_time_tik;
|
||||
batt_start_measure();
|
||||
if(clkt.utc_time_tik - adv_wrk.measure_batt_tik >= ((uint32_t)cfg.batt_interval << 15)) {
|
||||
adv_wrk.measure_batt_tik = clkt.utc_time_tik;
|
||||
batt_start_measure();
|
||||
#if ((DEV_SERVICES & SERVICE_THS) == 0)
|
||||
adv_wrk.adv_batt_count = 1;
|
||||
} else {
|
||||
if(adv_wrk.adv_batt_count) {
|
||||
adv_wrk.adv_batt_count = 0;
|
||||
} else {
|
||||
if(adv_wrk.new_battery) {
|
||||
adv_wrk.new_battery = 0;
|
||||
check_battery();
|
||||
#if (DEV_SERVICES & SERVICE_SCREEN)
|
||||
chow_lcd(1);
|
||||
chow_lcd(1);
|
||||
#endif
|
||||
#if (DEV_SERVICES & SERVICE_HISTORY)
|
||||
if (cfg.averaging_measurements != 0)
|
||||
write_memo();
|
||||
if (cfg.averaging_measurements != 0)
|
||||
write_memo();
|
||||
#endif
|
||||
|
||||
LL_SetAdvData(bthome_data_beacon((void *) gapRole_AdvertData), gapRole_AdvertData);
|
||||
LL_SetAdvData(bthome_data_beacon((void *) gapRole_AdvertData), gapRole_AdvertData);
|
||||
#if (DEV_SERVICES & SERVICE_SCREEN)
|
||||
} else {
|
||||
chow_lcd(0);
|
||||
} else {
|
||||
chow_lcd(0);
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
}
|
||||
#if (DEV_SERVICES & SERVICE_THS)
|
||||
if(adv_wrk.adv_meas_count == (uint8_t)(cfg.measure_interval - 1)) {
|
||||
start_measure();
|
||||
if(adv_wrk.meas_count == (uint8_t)(cfg.measure_interval - 1)) {
|
||||
start_measure();
|
||||
#if (DEV_SERVICES & SERVICE_SCREEN)
|
||||
chow_lcd(0);
|
||||
#endif
|
||||
} else {
|
||||
if(adv_wrk.adv_meas_count >= cfg.measure_interval) {
|
||||
adv_wrk.adv_meas_count = 0;
|
||||
read_sensor();
|
||||
#if (DEV_SERVICES & SERVICE_SCREEN)
|
||||
chow_lcd(1);
|
||||
#endif
|
||||
#if (DEV_SERVICES & SERVICE_HISTORY)
|
||||
if (cfg.averaging_measurements != 0)
|
||||
write_memo();
|
||||
#endif
|
||||
LL_SetAdvData(bthome_data_beacon((void *) gapRole_AdvertData), gapRole_AdvertData);
|
||||
#if (DEV_SERVICES & SERVICE_SCREEN)
|
||||
} else {
|
||||
chow_lcd(0);
|
||||
#endif
|
||||
} else {
|
||||
if(adv_wrk.meas_count >= cfg.measure_interval) {
|
||||
adv_wrk.meas_count = 0;
|
||||
read_sensor();
|
||||
if(adv_wrk.new_battery) {
|
||||
adv_wrk.new_battery = 0;
|
||||
check_battery();
|
||||
}
|
||||
#if (DEV_SERVICES & SERVICE_SCREEN)
|
||||
chow_lcd(1);
|
||||
#endif
|
||||
#if (DEV_SERVICES & SERVICE_HISTORY)
|
||||
if (cfg.averaging_measurements != 0)
|
||||
write_memo();
|
||||
#endif
|
||||
LL_SetAdvData(bthome_data_beacon((void *) gapRole_AdvertData), gapRole_AdvertData);
|
||||
#if (DEV_SERVICES & SERVICE_SCREEN)
|
||||
} else {
|
||||
chow_lcd(0);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif // (DEV_SERVICES & SERVICE_THS)
|
||||
#if (DEV_SERVICES & SERVICE_RDS)
|
||||
}
|
||||
|
|
@ -281,13 +294,17 @@ static void adv_measure(void) {
|
|||
#endif
|
||||
if(adv_wrk.adv_event) {
|
||||
adv_wrk.adv_event = 0;
|
||||
if(adv_wrk.new_battery) {
|
||||
adv_wrk.new_battery = 0;
|
||||
check_battery();
|
||||
}
|
||||
measured_data.count++;
|
||||
LL_SetAdvData(bthome_data_beacon((void *) gapRole_AdvertData), gapRole_AdvertData);
|
||||
}
|
||||
set_new_adv_interval(cfg.advertising_interval * 100);
|
||||
}
|
||||
}
|
||||
adv_wrk.adv_meas_count++;
|
||||
adv_wrk.meas_count++;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -558,6 +575,9 @@ void SimpleBLEPeripheral_Init( uint8_t task_id )
|
|||
LL_PLUS_PerStats_Init(&g_perStatsByChanTest);
|
||||
|
||||
batt_start_measure();
|
||||
#if (DEV_SERVICES & SERVICE_RDS)
|
||||
adv_wrk.rds_timer_tik = clkt.utc_time_tik - (RDS_RETRY_START_SEC << 15);
|
||||
#endif
|
||||
|
||||
LOG("=====SimpleBLEPeripheral_Init Done=======\n");
|
||||
}
|
||||
|
|
@ -580,7 +600,7 @@ uint16_t BLEPeripheral_ProcessEvent( uint8_t task_id, uint16_t events )
|
|||
VOID task_id; // OSAL required parameter that isn't used in this function
|
||||
if ( events & ADV_BROADCAST_EVT) {
|
||||
adv_measure();
|
||||
LOG("advN%u\n", adv_wrk.adv_meas_count);
|
||||
LOG("advN%u\n", adv_wrk.meas_count);
|
||||
// return unprocessed events
|
||||
return (events ^ ADV_BROADCAST_EVT);
|
||||
}
|
||||
|
|
@ -602,7 +622,7 @@ uint16_t BLEPeripheral_ProcessEvent( uint8_t task_id, uint16_t events )
|
|||
// enable adv (from gaprole start)
|
||||
if ( events & SBP_RESET_ADV_EVT ) {
|
||||
LOG("SBP_RESET_ADV_EVT\n");
|
||||
adv_wrk.adv_meas_count = 0;
|
||||
adv_wrk.meas_count = 0;
|
||||
// set_new_adv_interval(DEF_ADV_INERVAL); // actual time = advInt * 625us
|
||||
gatrole_advert_enable(TRUE);
|
||||
return ( events ^ SBP_RESET_ADV_EVT );
|
||||
|
|
@ -637,6 +657,7 @@ uint16_t BLEPeripheral_ProcessEvent( uint8_t task_id, uint16_t events )
|
|||
if( events & BATT_VALUE_EVT) {
|
||||
LOG("Vbat: %d mV, %d %%\n", measured_data.battery_mv, measured_data.battery);
|
||||
// Batt Notify
|
||||
check_battery();
|
||||
if(!gapRole_AdvEnabled) {
|
||||
BattNotifyLevel();
|
||||
#if ((DEV_SERVICES & SERVICE_THS)==0)
|
||||
|
|
@ -661,7 +682,7 @@ uint16_t BLEPeripheral_ProcessEvent( uint8_t task_id, uint16_t events )
|
|||
#ifdef GPIO_LED
|
||||
hal_gpio_write(GPIO_LED, LED_OFF);
|
||||
#endif
|
||||
//adv_wrk.adv_meas_count = 0;
|
||||
//adv_wrk.meas_count = 0;
|
||||
#if (DEV_SERVICES & SERVICE_SCREEN)
|
||||
lcd_show_version();
|
||||
#endif
|
||||
|
|
@ -686,7 +707,8 @@ uint16_t BLEPeripheral_ProcessEvent( uint8_t task_id, uint16_t events )
|
|||
if(gapRole_AdvEnabled) {
|
||||
measured_data.count++;
|
||||
adv_wrk.adv_event = 1;
|
||||
adv_wrk.adv_reload_count = 5;
|
||||
adv_wrk.adv_reload_count = RDS_RETRY_ADV_COUNT;
|
||||
adv_wrk.rds_timer_tik = clkt.utc_time_tik - (RDS_RETRY_DOUBLE_SEC << 15);
|
||||
LL_SetAdvData(bthome_data_beacon((void *) gapRole_AdvertData), gapRole_AdvertData);
|
||||
set_new_adv_interval(DEF_EVENT_ADV_INERVAL); // actual time * 625us
|
||||
} else if(cfg.flg & FLG_MEAS_NOTIFY) {
|
||||
|
|
@ -784,13 +806,13 @@ static void peripheralStateReadRssiCB( int8_t rssi )
|
|||
{
|
||||
LOG("Gaprole_adversting\n");
|
||||
osal_stop_timerEx(simpleBLEPeripheral_TaskID, TIMER_BATT_EVT);
|
||||
adv_wrk.adv_meas_count = 0;
|
||||
adv_wrk.meas_count = 0;
|
||||
}
|
||||
break;
|
||||
|
||||
case GAPROLE_CONNECTED:
|
||||
adv_wrk.adv_event = 0;
|
||||
adv_wrk.adv_meas_count = 0;
|
||||
adv_wrk.meas_count = 0;
|
||||
adv_wrk.adv_reload_count = 1;
|
||||
#if (DEV_SERVICES & SERVICE_THS)
|
||||
osal_start_reload_timer(simpleBLEPeripheral_TaskID, TIMER_BATT_EVT, adv_wrk.measure_interval_ms); // 10000 ms
|
||||
|
|
@ -819,7 +841,7 @@ static void peripheralStateReadRssiCB( int8_t rssi )
|
|||
gapRole_SlaveLatency = cfg.connect_latency;
|
||||
#endif
|
||||
adv_wrk.adv_event = 0;
|
||||
adv_wrk.adv_meas_count = 0;
|
||||
adv_wrk.meas_count = 0;
|
||||
adv_wrk.adv_reload_count = 1;
|
||||
#if (DEV_SERVICES & SERVICE_SCREEN)
|
||||
show_ble_symbol(0);
|
||||
|
|
|
|||
|
|
@ -33,6 +33,12 @@ extern "C"
|
|||
#define DEF_OTA_ADV_INERVAL 1600 // 1 sec
|
||||
#define DEF_OTA_ADV_INERVAL_MS ((DEF_OTA_ADV_INERVAL*625)/1000) // 1000 ms
|
||||
|
||||
// adv. event
|
||||
#define RDS_STEP_TIMER_SEC 1800 // шаг передачи 30 минут
|
||||
#define RDS_RETRY_DOUBLE_SEC (RDS_STEP_TIMER_SEC-12) // дубль через 12 сек
|
||||
#define RDS_RETRY_START_SEC (RDS_STEP_TIMER_SEC-120) // старт 2 минуты
|
||||
#define RDS_RETRY_ADV_COUNT 16
|
||||
|
||||
// How often to perform periodic event
|
||||
#define SBP_PERIODIC_EVT_PERIOD 5000
|
||||
|
||||
|
|
|
|||
8
fw.json
8
fw.json
|
|
@ -6,6 +6,14 @@
|
|||
"bin/THB1_v15.bin",
|
||||
"bin/TH05D_v15.bin",
|
||||
"bin/TH05F_v15.bin"],
|
||||
"betafw":[
|
||||
"bin/THB2_v16.bin",
|
||||
"bin/BTH01_v16.bin",
|
||||
"bin/TH05_v16.bin",
|
||||
"?",
|
||||
"bin/THB1_v16.bin",
|
||||
"bin/TH05D_v16.bin",
|
||||
"bin/TH05F_v16.bin"],
|
||||
"updateboot":[
|
||||
"update_boot/BOOT_THB2_v15.bin",
|
||||
"update_boot/BOOT_BTH01_v15.bin",
|
||||
|
|
|
|||
BIN
update_boot/BOOT_BTH01_v16.bin
Normal file
BIN
update_boot/BOOT_BTH01_v16.bin
Normal file
Binary file not shown.
BIN
update_boot/BOOT_TH05D_v16.bin
Normal file
BIN
update_boot/BOOT_TH05D_v16.bin
Normal file
Binary file not shown.
BIN
update_boot/BOOT_TH05F_v16.bin
Normal file
BIN
update_boot/BOOT_TH05F_v16.bin
Normal file
Binary file not shown.
BIN
update_boot/BOOT_TH05_v16.bin
Normal file
BIN
update_boot/BOOT_TH05_v16.bin
Normal file
Binary file not shown.
BIN
update_boot/BOOT_THB1_v16.bin
Normal file
BIN
update_boot/BOOT_THB1_v16.bin
Normal file
Binary file not shown.
BIN
update_boot/BOOT_THB2_v16.bin
Normal file
BIN
update_boot/BOOT_THB2_v16.bin
Normal file
Binary file not shown.
Loading…
Add table
Add a link
Reference in a new issue