atk_dnesp32s3_box2.cc 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466
  1. #include "wifi_board.h"
  2. #include "codecs/es8389_audio_codec.h"
  3. #include "display/lcd_display.h"
  4. #include "system_reset.h"
  5. #include "application.h"
  6. #include "button.h"
  7. #include "config.h"
  8. #include "power_save_timer.h"
  9. #include "led/single_led.h"
  10. #include "assets/lang_config.h"
  11. #include "power_manager.h"
  12. #include "i2c_device.h"
  13. #include <esp_log.h>
  14. #include <esp_lcd_panel_vendor.h>
  15. #include <wifi_station.h>
  16. #include <driver/rtc_io.h>
  17. #include <esp_sleep.h>
  18. #include "esp_io_expander_tca95xx_16bit.h"
  19. #define TAG "atk_dnesp32s3_box2_wifi"
  20. LV_FONT_DECLARE(font_puhui_20_4);
  21. LV_FONT_DECLARE(font_awesome_20_4);
  22. class atk_dnesp32s3_box2_wifi : public WifiBoard {
  23. private:
  24. i2c_master_bus_handle_t i2c_bus_;
  25. LcdDisplay* display_;
  26. esp_io_expander_handle_t io_exp_handle;
  27. button_handle_t btns;
  28. button_driver_t* btn_driver_ = nullptr;
  29. static atk_dnesp32s3_box2_wifi* instance_;
  30. PowerSaveTimer* power_save_timer_;
  31. PowerManager* power_manager_;
  32. PowerSupply power_status_;
  33. esp_timer_handle_t wake_timer_handle_;
  34. esp_lcd_panel_io_handle_t panel_io = nullptr;
  35. esp_lcd_panel_handle_t panel = nullptr;
  36. int ticks_ = 0;
  37. const int kChgCtrlInterval = 5;
  38. void InitializeBoardPowerManager() {
  39. instance_ = this;
  40. if (IoExpanderGetLevel(XIO_CHRG) == 0) {
  41. power_status_ = kDeviceTypecSupply;
  42. } else {
  43. power_status_ = kDeviceBatterySupply;
  44. }
  45. esp_timer_create_args_t wake_display_timer_args = {
  46. .callback = [](void *arg) {
  47. atk_dnesp32s3_box2_wifi* self = static_cast<atk_dnesp32s3_box2_wifi*>(arg);
  48. self->ticks_ ++;
  49. if (self->ticks_ % self->kChgCtrlInterval == 0) {
  50. if (self->IoExpanderGetLevel(XIO_CHRG) == 0) {
  51. self->power_status_ = kDeviceTypecSupply;
  52. } else {
  53. self->power_status_ = kDeviceBatterySupply;
  54. }
  55. /* 低于某个电量,会自动关机 */
  56. if (self->power_manager_->low_voltage_ < 2630 && self->power_status_ == kDeviceBatterySupply) {
  57. esp_timer_stop(self->power_manager_->timer_handle_);
  58. esp_io_expander_set_dir(self->io_exp_handle, XIO_CHG_CTRL, IO_EXPANDER_OUTPUT);
  59. esp_io_expander_set_level(self->io_exp_handle, XIO_CHG_CTRL, 0);
  60. vTaskDelay(pdMS_TO_TICKS(100));
  61. esp_io_expander_set_dir(self->io_exp_handle, XIO_CHG_CTRL, IO_EXPANDER_INPUT);
  62. esp_io_expander_set_level(self->io_exp_handle, XIO_CHG_CTRL, 0);
  63. vTaskDelay(pdMS_TO_TICKS(100));
  64. }
  65. }
  66. },
  67. .arg = this,
  68. .dispatch_method = ESP_TIMER_TASK,
  69. .name = "wake_update_timer",
  70. .skip_unhandled_events = true,
  71. };
  72. ESP_ERROR_CHECK(esp_timer_create(&wake_display_timer_args, &wake_timer_handle_));
  73. ESP_ERROR_CHECK(esp_timer_start_periodic(wake_timer_handle_, 100000));
  74. }
  75. void InitializePowerManager() {
  76. power_manager_ = new PowerManager(io_exp_handle);
  77. power_manager_->OnChargingStatusChanged([this](bool is_charging) {
  78. if (is_charging) {
  79. power_save_timer_->SetEnabled(false);
  80. } else {
  81. power_save_timer_->SetEnabled(true);
  82. }
  83. });
  84. }
  85. void InitializePowerSaveTimer() {
  86. power_save_timer_ = new PowerSaveTimer(-1, 60, 300);
  87. power_save_timer_->OnEnterSleepMode([this]() {
  88. display_->SetChatMessage("system", "");
  89. display_->SetEmotion("sleepy");
  90. GetBacklight()->SetBrightness(1);
  91. });
  92. power_save_timer_->OnExitSleepMode([this]() {
  93. display_->SetChatMessage("system", "");
  94. display_->SetEmotion("neutral");
  95. GetBacklight()->RestoreBrightness();
  96. });
  97. power_save_timer_->OnShutdownRequest([this]() {
  98. if (power_status_ == kDeviceBatterySupply) {
  99. GetBacklight()->SetBrightness(0);
  100. esp_timer_stop(power_manager_->timer_handle_);
  101. esp_io_expander_set_dir( io_exp_handle, XIO_CHG_CTRL, IO_EXPANDER_OUTPUT);
  102. esp_io_expander_set_level(io_exp_handle, XIO_CHG_CTRL, 0);
  103. vTaskDelay(pdMS_TO_TICKS(100));
  104. esp_io_expander_set_level(io_exp_handle, XIO_SYS_POW, 0);
  105. }
  106. });
  107. power_save_timer_->SetEnabled(true);
  108. }
  109. void audio_volume_change(bool direction) {
  110. auto codec = GetAudioCodec();
  111. auto volume = codec->output_volume();
  112. if (direction) {
  113. volume += 10;
  114. if (volume > 100) {
  115. volume = 100;
  116. }
  117. codec->SetOutputVolume(volume);
  118. } else {
  119. volume -= 10;
  120. if (volume < 0) {
  121. volume = 0;
  122. }
  123. codec->SetOutputVolume(volume);
  124. }
  125. GetDisplay()->ShowNotification(Lang::Strings::VOLUME + std::to_string(volume));
  126. }
  127. void audio_volume_minimum(){
  128. GetAudioCodec()->SetOutputVolume(0);
  129. GetDisplay()->ShowNotification(Lang::Strings::MUTED);
  130. }
  131. void audio_volume_maxmum(){
  132. GetAudioCodec()->SetOutputVolume(100);
  133. GetDisplay()->ShowNotification(Lang::Strings::MAX_VOLUME);
  134. }
  135. esp_err_t IoExpanderSetLevel(uint16_t pin_mask, uint8_t level) {
  136. return esp_io_expander_set_level(io_exp_handle, pin_mask, level);
  137. }
  138. uint8_t IoExpanderGetLevel(uint16_t pin_mask) {
  139. uint32_t pin_val = 0;
  140. esp_io_expander_get_level(io_exp_handle, DRV_IO_EXP_INPUT_MASK, &pin_val);
  141. pin_mask &= DRV_IO_EXP_INPUT_MASK;
  142. return (uint8_t)((pin_val & pin_mask) ? 1 : 0);
  143. }
  144. void InitializeIoExpander() {
  145. esp_err_t ret = ESP_OK;
  146. esp_io_expander_new_i2c_tca95xx_16bit(i2c_bus_, ESP_IO_EXPANDER_I2C_TCA9555_ADDRESS_000, &io_exp_handle);
  147. ret |= esp_io_expander_set_dir(io_exp_handle, DRV_IO_EXP_OUTPUT_MASK, IO_EXPANDER_OUTPUT);
  148. ret |= esp_io_expander_set_dir(io_exp_handle, DRV_IO_EXP_INPUT_MASK, IO_EXPANDER_INPUT);
  149. ret |= esp_io_expander_set_level(io_exp_handle, XIO_SYS_POW, 1);
  150. ret |= esp_io_expander_set_level(io_exp_handle, XIO_EN_3V3A, 1);
  151. ret |= esp_io_expander_set_level(io_exp_handle, XIO_EN_4G, 1);
  152. ret |= esp_io_expander_set_level(io_exp_handle, XIO_SPK_EN, 1);
  153. ret |= esp_io_expander_set_level(io_exp_handle, XIO_USB_SEL, 1);
  154. ret |= esp_io_expander_set_level(io_exp_handle, XIO_VBUS_EN, 0);
  155. assert(ret == ESP_OK);
  156. }
  157. // Initialize I2C peripheral
  158. void InitializeI2c() {
  159. i2c_master_bus_config_t i2c_bus_cfg = {
  160. .i2c_port = (i2c_port_t)I2C_NUM_0,
  161. .sda_io_num = AUDIO_CODEC_I2C_SDA_PIN,
  162. .scl_io_num = AUDIO_CODEC_I2C_SCL_PIN,
  163. .clk_source = I2C_CLK_SRC_DEFAULT,
  164. .glitch_ignore_cnt = 7,
  165. .intr_priority = 0,
  166. .trans_queue_depth = 0,
  167. .flags = {
  168. .enable_internal_pullup = 1,
  169. },
  170. };
  171. ESP_ERROR_CHECK(i2c_new_master_bus(&i2c_bus_cfg, &i2c_bus_));
  172. }
  173. void InitializeButtons() {
  174. instance_ = this;
  175. button_config_t l_btn_cfg = {
  176. .long_press_time = 800,
  177. .short_press_time = 500
  178. };
  179. button_config_t m_btn_cfg = {
  180. .long_press_time = 800,
  181. .short_press_time = 500
  182. };
  183. button_config_t r_btn_cfg = {
  184. .long_press_time = 800,
  185. .short_press_time = 500
  186. };
  187. button_driver_t* xio_l_btn_driver_ = nullptr;
  188. button_driver_t* xio_m_btn_driver_ = nullptr;
  189. button_handle_t l_btn_handle = NULL;
  190. button_handle_t m_btn_handle = NULL;
  191. button_handle_t r_btn_handle = NULL;
  192. xio_l_btn_driver_ = (button_driver_t*)calloc(1, sizeof(button_driver_t));
  193. xio_l_btn_driver_->enable_power_save = false;
  194. xio_l_btn_driver_->get_key_level = [](button_driver_t *button_driver) -> uint8_t {
  195. return !instance_->IoExpanderGetLevel(XIO_KEY_L);
  196. };
  197. ESP_ERROR_CHECK(iot_button_create(&l_btn_cfg, xio_l_btn_driver_, &l_btn_handle));
  198. xio_m_btn_driver_ = (button_driver_t*)calloc(1, sizeof(button_driver_t));
  199. xio_m_btn_driver_->enable_power_save = false;
  200. xio_m_btn_driver_->get_key_level = [](button_driver_t *button_driver) -> uint8_t {
  201. return instance_->IoExpanderGetLevel(XIO_KEY_M);
  202. };
  203. ESP_ERROR_CHECK(iot_button_create(&m_btn_cfg, xio_m_btn_driver_, &m_btn_handle));
  204. button_gpio_config_t r_cfg = {
  205. .gpio_num = R_BUTTON_GPIO,
  206. .active_level = BUTTON_INACTIVE,
  207. .enable_power_save = false,
  208. .disable_pull = false
  209. };
  210. ESP_ERROR_CHECK(iot_button_new_gpio_device(&r_btn_cfg, &r_cfg, &r_btn_handle));
  211. iot_button_register_cb(l_btn_handle, BUTTON_PRESS_DOWN, nullptr, [](void* button_handle, void* usr_data) {
  212. auto self = static_cast<atk_dnesp32s3_box2_wifi*>(usr_data);
  213. self->power_save_timer_->WakeUp();
  214. self->audio_volume_change(false);
  215. }, this);
  216. iot_button_register_cb(l_btn_handle, BUTTON_LONG_PRESS_START, nullptr, [](void* button_handle, void* usr_data) {
  217. auto self = static_cast<atk_dnesp32s3_box2_wifi*>(usr_data);
  218. self->power_save_timer_->WakeUp();
  219. self->audio_volume_minimum();
  220. }, this);
  221. iot_button_register_cb(m_btn_handle, BUTTON_PRESS_DOWN, nullptr, [](void* button_handle, void* usr_data) {
  222. auto self = static_cast<atk_dnesp32s3_box2_wifi*>(usr_data);
  223. self->power_save_timer_->WakeUp();
  224. auto& app = Application::GetInstance();
  225. app.ToggleChatState();
  226. }, this);
  227. iot_button_register_cb(m_btn_handle, BUTTON_LONG_PRESS_START, nullptr, [](void* button_handle, void* usr_data) {
  228. auto self = static_cast<atk_dnesp32s3_box2_wifi*>(usr_data);
  229. auto& app = Application::GetInstance();
  230. if (app.GetDeviceState() == kDeviceStateStarting && !WifiStation::GetInstance().IsConnected()) {
  231. self->ResetWifiConfiguration();
  232. }
  233. if (self->power_status_ == kDeviceBatterySupply) {
  234. auto backlight = Board::GetInstance().GetBacklight();
  235. backlight->SetBrightness(0);
  236. esp_timer_stop(self->power_manager_->timer_handle_);
  237. esp_io_expander_set_dir(self->io_exp_handle, XIO_CHG_CTRL, IO_EXPANDER_OUTPUT);
  238. esp_io_expander_set_level(self->io_exp_handle, XIO_CHG_CTRL, 0);
  239. vTaskDelay(pdMS_TO_TICKS(100));
  240. esp_io_expander_set_level(self->io_exp_handle, XIO_SYS_POW, 0);
  241. vTaskDelay(pdMS_TO_TICKS(100));
  242. }
  243. }, this);
  244. iot_button_register_cb(r_btn_handle, BUTTON_PRESS_DOWN, nullptr, [](void* button_handle, void* usr_data) {
  245. auto self = static_cast<atk_dnesp32s3_box2_wifi*>(usr_data);
  246. self->power_save_timer_->WakeUp();
  247. self->audio_volume_change(true);
  248. }, this);
  249. iot_button_register_cb(r_btn_handle, BUTTON_LONG_PRESS_START, nullptr, [](void* button_handle, void* usr_data) {
  250. auto self = static_cast<atk_dnesp32s3_box2_wifi*>(usr_data);
  251. self->power_save_timer_->WakeUp();
  252. self->audio_volume_maxmum();
  253. }, this);
  254. }
  255. void InitializeSt7789Display() {
  256. ESP_LOGI(TAG, "Install panel IO");
  257. /* RD PIN */
  258. gpio_config_t gpio_init_struct;
  259. gpio_init_struct.intr_type = GPIO_INTR_DISABLE;
  260. gpio_init_struct.mode = GPIO_MODE_INPUT_OUTPUT;
  261. gpio_init_struct.pin_bit_mask = 1ull << LCD_PIN_RD;
  262. gpio_init_struct.pull_down_en = GPIO_PULLDOWN_DISABLE;
  263. gpio_init_struct.pull_up_en = GPIO_PULLUP_ENABLE;
  264. gpio_config(&gpio_init_struct);
  265. gpio_set_level(LCD_PIN_RD, 1);
  266. /* BL PIN */
  267. gpio_init_struct.pin_bit_mask = 1ull << DISPLAY_BACKLIGHT_PIN;
  268. gpio_init_struct.pull_down_en = GPIO_PULLDOWN_DISABLE;
  269. gpio_init_struct.pull_up_en = GPIO_PULLUP_ENABLE;
  270. gpio_config(&gpio_init_struct);
  271. esp_lcd_i80_bus_handle_t i80_bus = NULL;
  272. esp_lcd_i80_bus_config_t bus_config = {
  273. .dc_gpio_num = LCD_PIN_DC,
  274. .wr_gpio_num = LCD_PIN_WR,
  275. .clk_src = LCD_CLK_SRC_DEFAULT,
  276. .data_gpio_nums = {
  277. LCD_PIN_D0,
  278. LCD_PIN_D1,
  279. LCD_PIN_D2,
  280. LCD_PIN_D3,
  281. LCD_PIN_D4,
  282. LCD_PIN_D5,
  283. LCD_PIN_D6,
  284. LCD_PIN_D7,
  285. },
  286. .bus_width = 8,
  287. .max_transfer_bytes = DISPLAY_WIDTH * DISPLAY_HEIGHT * sizeof(uint16_t),
  288. .psram_trans_align = 64,
  289. .sram_trans_align = 4,
  290. };
  291. ESP_ERROR_CHECK(esp_lcd_new_i80_bus(&bus_config, &i80_bus));
  292. esp_lcd_panel_io_i80_config_t io_config = {
  293. .cs_gpio_num = LCD_PIN_CS,
  294. .pclk_hz = (20 * 1000 * 1000),
  295. .trans_queue_depth = 7,
  296. .on_color_trans_done = nullptr,
  297. .user_ctx = nullptr,
  298. .lcd_cmd_bits = 8,
  299. .lcd_param_bits = 8,
  300. .dc_levels = {
  301. .dc_idle_level = 1,
  302. .dc_cmd_level = 0,
  303. .dc_dummy_level = 0,
  304. .dc_data_level = 1,
  305. },
  306. .flags = {
  307. .cs_active_high = 0,
  308. .pclk_active_neg = 0,
  309. .pclk_idle_low = 0,
  310. },
  311. };
  312. ESP_ERROR_CHECK(esp_lcd_new_panel_io_i80(i80_bus, &io_config, &panel_io));
  313. esp_lcd_panel_dev_config_t panel_config = {
  314. .reset_gpio_num = LCD_PIN_RST,
  315. .rgb_ele_order = LCD_RGB_ELEMENT_ORDER_RGB,
  316. .bits_per_pixel = 16,
  317. };
  318. ESP_ERROR_CHECK(esp_lcd_new_panel_st7789(panel_io, &panel_config, &panel));
  319. esp_lcd_panel_reset(panel);
  320. esp_lcd_panel_init(panel);
  321. esp_lcd_panel_invert_color(panel, true);
  322. esp_lcd_panel_set_gap(panel, 0, 0);
  323. esp_lcd_panel_io_tx_param(panel_io, 0xCF, (uint8_t[]) {0x00,0x83,0x30}, 3);
  324. esp_lcd_panel_io_tx_param(panel_io, 0xED, (uint8_t[]) {0x64,0x03,0x12,0x81}, 4);
  325. esp_lcd_panel_io_tx_param(panel_io, 0xE8, (uint8_t[]) {0x85,0x01,0x79}, 3);
  326. esp_lcd_panel_io_tx_param(panel_io, 0xCB, (uint8_t[]) {0x39,0x2C,0x00,0x34,0x02}, 5);
  327. esp_lcd_panel_io_tx_param(panel_io, 0xF7, (uint8_t[]) {0x20}, 1);
  328. esp_lcd_panel_io_tx_param(panel_io, 0xEA, (uint8_t[]) {0x00,0x00}, 2);
  329. esp_lcd_panel_io_tx_param(panel_io, 0xbb, (uint8_t[]) {0x20}, 1);
  330. esp_lcd_panel_io_tx_param(panel_io, 0xc3, (uint8_t[]) {0x00}, 1);
  331. esp_lcd_panel_io_tx_param(panel_io, 0xC4, (uint8_t[]) {0x20}, 1);
  332. esp_lcd_panel_io_tx_param(panel_io, 0xC5, (uint8_t[]) {0x20}, 1);
  333. esp_lcd_panel_io_tx_param(panel_io, 0xC6, (uint8_t[]) {0x10}, 1);
  334. esp_lcd_panel_io_tx_param(panel_io, 0xC7, (uint8_t[]) {0xB0}, 1);
  335. esp_lcd_panel_io_tx_param(panel_io, 0x36, (uint8_t[]) {0x60}, 1);
  336. esp_lcd_panel_io_tx_param(panel_io, 0x3A, (uint8_t[]) {0x55}, 1);
  337. esp_lcd_panel_io_tx_param(panel_io, 0xB1, (uint8_t[]) {0x00,0x1B}, 2);
  338. esp_lcd_panel_io_tx_param(panel_io, 0xF2, (uint8_t[]) {0x08}, 1);
  339. esp_lcd_panel_io_tx_param(panel_io, 0x26, (uint8_t[]) {0x01}, 1);
  340. esp_lcd_panel_io_tx_param(panel_io, 0xE0, (uint8_t[]) {0xD0,0x00,0x02,0x07,0x0A,0x28,0x32,0x44,0x42,0x06,0x0E,0x12,0x14,0x17}, 14);
  341. esp_lcd_panel_io_tx_param(panel_io, 0xE1, (uint8_t[]) {0xD0,0x00,0x02,0x07,0x0A,0x28,0x31,0x54,0x47,0x0E,0x1C,0x17,0x1B,0x1E}, 14);
  342. esp_lcd_panel_io_tx_param(panel_io, 0xB7, (uint8_t[]) {0x07}, 1);
  343. esp_lcd_panel_swap_xy(panel, DISPLAY_SWAP_XY);
  344. esp_lcd_panel_mirror(panel, DISPLAY_MIRROR_X, DISPLAY_MIRROR_Y);
  345. display_ = new SpiLcdDisplay(panel_io, panel,
  346. DISPLAY_WIDTH, DISPLAY_HEIGHT, DISPLAY_OFFSET_X, DISPLAY_OFFSET_Y, DISPLAY_MIRROR_X, DISPLAY_MIRROR_Y, DISPLAY_SWAP_XY,
  347. {
  348. .text_font = &font_puhui_20_4,
  349. .icon_font = &font_awesome_20_4,
  350. .emoji_font = DISPLAY_HEIGHT >= 240 ? font_emoji_64_init() : font_emoji_32_init(),
  351. });
  352. }
  353. public:
  354. atk_dnesp32s3_box2_wifi() {
  355. InitializeI2c();
  356. InitializeIoExpander();
  357. InitializePowerSaveTimer();
  358. InitializePowerManager();
  359. InitializeSt7789Display();
  360. InitializeButtons();
  361. GetBacklight()->RestoreBrightness();
  362. InitializeBoardPowerManager();
  363. }
  364. virtual AudioCodec* GetAudioCodec() override {
  365. static Es8389AudioCodec audio_codec(
  366. i2c_bus_,
  367. I2C_NUM_0,
  368. AUDIO_INPUT_SAMPLE_RATE,
  369. AUDIO_OUTPUT_SAMPLE_RATE,
  370. AUDIO_I2S_GPIO_MCLK,
  371. AUDIO_I2S_GPIO_BCLK,
  372. AUDIO_I2S_GPIO_WS,
  373. AUDIO_I2S_GPIO_DOUT,
  374. AUDIO_I2S_GPIO_DIN,
  375. GPIO_NUM_NC,
  376. AUDIO_CODEC_ES8389_ADDR,
  377. false);
  378. return &audio_codec;
  379. }
  380. virtual Display* GetDisplay() override {
  381. return display_;
  382. }
  383. virtual Backlight* GetBacklight() override {
  384. static PwmBacklight backlight(DISPLAY_BACKLIGHT_PIN, DISPLAY_BACKLIGHT_OUTPUT_INVERT);
  385. return &backlight;
  386. }
  387. virtual bool GetBatteryLevel(int& level, bool& charging, bool& discharging) override {
  388. static bool last_discharging = false;
  389. charging = power_manager_->IsCharging();
  390. discharging = power_manager_->IsDischarging();
  391. if (discharging != last_discharging) {
  392. power_save_timer_->SetEnabled(discharging);
  393. last_discharging = discharging;
  394. }
  395. level = power_manager_->GetBatteryLevel();
  396. return true;
  397. }
  398. virtual void SetPowerSaveMode(bool enabled) override {
  399. if (!enabled) {
  400. power_save_timer_->WakeUp();
  401. }
  402. WifiBoard::SetPowerSaveMode(enabled);
  403. }
  404. };
  405. DECLARE_BOARD(atk_dnesp32s3_box2_wifi);
  406. // 定义静态成员变量
  407. atk_dnesp32s3_box2_wifi* atk_dnesp32s3_box2_wifi::instance_ = nullptr;