#include #include #include #include #include #include #include #include #include #include "fab-reader2.h" #include "platform.h" #include "st25R3911_interrupt.h" #include "DEV_Config.h" #include "pollingtagdetect.h" #include "epd.h" #include "ota.h" #define SPI_CLK 5 #define SPI_MOSI 6 #define SPI_MISO 7 #define ESP_INTR_FLAG_DEFAULT 0 portMUX_TYPE CommProtectLock = portMUX_INITIALIZER_UNLOCKED; esp_err_t init_mqtt(void); static void IRAM_ATTR gpio_isr_handler(void *arg) { st25r3911Isr(); ets_printf("Interrupt\n"); } static void network_event_handler(void* arg, esp_event_base_t event_base, int32_t event_id, void* event_data) { if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_START) { esp_wifi_connect(); } else if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_DISCONNECTED) { esp_wifi_connect(); } else if (event_base == IP_EVENT && event_id == IP_EVENT_STA_GOT_IP) { ip_event_got_ip_t* event = (ip_event_got_ip_t*) event_data; ESP_LOGI("network", "got ip:" IPSTR, IP2STR(&event->ip_info.ip)); ESP_ERROR_CHECK(init_mqtt()); ESP_LOGI("main", "init_mqtt done"); } } /* * @brief Event handler registered to receive MQTT events * * This function is called by the MQTT client event loop. * * @param handler_args user data registered to the event. * @param base Event base for the handler(always MQTT Base in this example). * @param event_id The id for the received event. * @param event_data The data for the event, esp_mqtt_event_handle_t. */ static void mqtt_event_handler(void *handler_args, esp_event_base_t base, int32_t event_id, void *event_data) { ESP_LOGD("mqtt", "Event dispatched from event loop base=%s, event_id=%d", base, event_id); esp_mqtt_event_handle_t event = event_data; esp_mqtt_client_handle_t client = event->client; int msg_id; switch ((esp_mqtt_event_id_t)event_id) { case MQTT_EVENT_CONNECTED: ESP_LOGI("mqtt", "MQTT_EVENT_CONNECTED"); char id[6] = "00000"; sprintf(id, "%05d", CONFIG_FABREADER2_ID); // Register Reader msg_id = esp_mqtt_client_publish(client, "fabreader", id, 0, 0, 0); ESP_LOGI("mqtt", "sent publish successful, msg_id=%d", msg_id); char topic_requestOTA[] = "fabreader/00000/requestOTA"; sprintf(topic_requestOTA, "fabreader/%05d/requestOTA", CONFIG_FABREADER2_ID); msg_id = esp_mqtt_client_subscribe(client, topic_requestOTA, 0); ESP_LOGI("mqtt", "sent subscribe successful, msg_id=%d", msg_id); char topic_stopOTA[] = "fabreader/00000/stopOTA"; sprintf(topic_stopOTA, "fabreader/%05d/stopOTA", CONFIG_FABREADER2_ID); msg_id = esp_mqtt_client_subscribe(client, topic_stopOTA, 0); ESP_LOGI("mqtt", "sent subscribe successful, msg_id=%d", msg_id); char topic_display[] = "fabreader/00000/display/#"; sprintf(topic_display, "fabreader/%05d/display/#", CONFIG_FABREADER2_ID); msg_id = esp_mqtt_client_subscribe(client, topic_display, 0); ESP_LOGI("mqtt", "sent subscribe successful, msg_id=%d", msg_id); break; case MQTT_EVENT_DISCONNECTED: ESP_LOGI("mqtt", "MQTT_EVENT_DISCONNECTED"); break; case MQTT_EVENT_SUBSCRIBED: ESP_LOGI("mqtt", "MQTT_EVENT_SUBSCRIBED, msg_id=%d", event->msg_id); break; case MQTT_EVENT_UNSUBSCRIBED: ESP_LOGI("mqtt", "MQTT_EVENT_UNSUBSCRIBED, msg_id=%d", event->msg_id); break; case MQTT_EVENT_PUBLISHED: ESP_LOGI("mqtt", "MQTT_EVENT_PUBLISHED, msg_id=%d", event->msg_id); break; case MQTT_EVENT_DATA: ESP_LOGI("mqtt", "MQTT_EVENT_DATA"); printf("TOPIC=%.*s\r\n", event->topic_len, event->topic); printf("DATA=%.*s\r\n", event->data_len, event->data); if (hasActiveOTA()) { continueOTA(client, event->topic, event->data, event->data_len); } break; case MQTT_EVENT_ERROR: ESP_LOGE("mqtt", "MQTT_EVENT_ERROR"); if (event->error_handle->error_type == MQTT_ERROR_TYPE_TCP_TRANSPORT) { ESP_LOGE("mqtt", "Last error code reported from esp-tls: 0x%x", event->error_handle->esp_tls_last_esp_err); ESP_LOGE("mqtt", "Last tls stack error number: 0x%x", event->error_handle->esp_tls_stack_err); ESP_LOGE("mqtt", "Last captured errno : %d (%s)", event->error_handle->esp_transport_sock_errno, strerror(event->error_handle->esp_transport_sock_errno)); } else if (event->error_handle->error_type == MQTT_ERROR_TYPE_CONNECTION_REFUSED) { ESP_LOGE("mqtt", "Connection refused error: 0x%x", event->error_handle->connect_return_code); } else { ESP_LOGW("mqtt", "Unknown error type: 0x%x", event->error_handle->error_type); } break; default: ESP_LOGI("mqtt", "Other event id:%d", event->event_id); break; } } esp_err_t init_gpio(void) { gpio_config_t io_conf = {}; //disable interrupt io_conf.intr_type = GPIO_INTR_DISABLE; //set as output mode io_conf.mode = GPIO_MODE_INPUT_OUTPUT; //bit mask of the pins that you want to set,e.g.GPIO18/19 io_conf.pin_bit_mask = (1ULL << ST25R391X_SS_PIN) | (1ULL << EPD_CS_PIN) | (1ULL << EPD_DC_PIN) | (1ULL << EPD_RST_PIN); //disable pull-down mode io_conf.pull_down_en = 0; //disable pull-up mode io_conf.pull_up_en = 0; //configure GPIO with the given settings esp_err_t ret = gpio_config(&io_conf); ESP_ERROR_CHECK(ret); io_conf.mode = GPIO_MODE_INPUT; io_conf.pin_bit_mask = (1ULL << EPD_BUSY_PIN); ret = gpio_config(&io_conf); ESP_ERROR_CHECK(ret); //interrupt of rising edge io_conf.intr_type = GPIO_INTR_POSEDGE; //bit mask of the pins, use GPIO4/5 here io_conf.pin_bit_mask = (1ULL << ST25R391X_INT_PIN); //set as input mode io_conf.mode = GPIO_MODE_INPUT; //disable pull-down mode io_conf.pull_down_en = 0; //enable pull-up mode io_conf.pull_up_en = 0; ESP_ERROR_CHECK(gpio_config(&io_conf)); ESP_ERROR_CHECK(gpio_install_isr_service(ESP_INTR_FLAG_DEFAULT)); //hook isr handler for specific gpio pin ESP_ERROR_CHECK(gpio_isr_handler_add(ST25R391X_INT_PIN, gpio_isr_handler, NULL)); return ret; } esp_err_t init_spi(void) { spi_bus_config_t buscfg = { .miso_io_num=SPI_MISO, .mosi_io_num=SPI_MOSI, .sclk_io_num=SPI_CLK, .quadwp_io_num=-1, .quadhd_io_num=-1, }; esp_err_t ret = spi_bus_initialize(SPI3_HOST, &buscfg, SPI_DMA_CH_AUTO); ESP_ERROR_CHECK(ret); spi_device_interface_config_t nfc_devcfg = { .clock_speed_hz=SPI_MASTER_FREQ_8M, //Clock out at 26 MHz .mode=1, //SPI mode 1 .spics_io_num=-1, //CS pin .queue_size=1, //We want to be able to queue 7 transactions at a time }; spi_device_handle_t nfc_spi; ret = spi_bus_add_device(SPI3_HOST, &nfc_devcfg, &nfc_spi); ESP_ERROR_CHECK(ret); st25r3911_spi_init(nfc_spi); spi_device_interface_config_t epd_devcfg = { .clock_speed_hz=SPI_MASTER_FREQ_8M, //Clock out at 26 MHz .mode=0, //SPI mode 1 .spics_io_num=-1, //CS pin .queue_size=1, //We want to be able to queue 7 transactions at a time }; spi_device_handle_t epd_spi; ret = spi_bus_add_device(SPI3_HOST, &epd_devcfg, &epd_spi); ESP_ERROR_CHECK(ret); DEV_SPI_Init(epd_spi); return ret; } esp_err_t init_eventloop() { esp_err_t ret = esp_event_loop_create_default(); ESP_ERROR_CHECK(ret); return ret; } esp_err_t init_wifi() { esp_err_t ret; ret = esp_netif_init(); ESP_ERROR_CHECK(ret); wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT(); ret = esp_wifi_init(&cfg); ESP_ERROR_CHECK(ret); ret = esp_event_handler_instance_register(WIFI_EVENT, ESP_EVENT_ANY_ID, &network_event_handler, NULL, NULL); ESP_ERROR_CHECK(ret); ret = esp_event_handler_instance_register(IP_EVENT, IP_EVENT_STA_GOT_IP, &network_event_handler, NULL, NULL); ESP_ERROR_CHECK(ret); // Initialize default station as network interface instance (esp-netif) esp_netif_t *sta_netif = esp_netif_create_default_wifi_sta(); assert(sta_netif); // Initialize and start WiFi wifi_config_t wifi_config = { .sta = { .ssid = DEFAULT_SSID, .password = DEFAULT_PWD, .scan_method = DEFAULT_SCAN_METHOD, .sort_method = DEFAULT_SORT_METHOD, .threshold.rssi = DEFAULT_RSSI, .threshold.authmode = DEFAULT_AUTHMODE, }, }; ret = esp_wifi_set_mode(WIFI_MODE_STA); ESP_ERROR_CHECK(ret); ret = esp_wifi_set_config(WIFI_IF_STA, &wifi_config); ESP_ERROR_CHECK(ret); ret = esp_wifi_start(); ESP_ERROR_CHECK(ret); return ret; } esp_err_t init_nvs() { // Initialize NVS esp_err_t ret = nvs_flash_init(); if (ret == ESP_ERR_NVS_NO_FREE_PAGES || ret == ESP_ERR_NVS_NEW_VERSION_FOUND) { ESP_ERROR_CHECK(nvs_flash_erase()); ret = nvs_flash_init(); } ESP_ERROR_CHECK( ret ); return ret; } esp_err_t init_mqtt() { esp_err_t ret; const esp_mqtt_client_config_t mqtt_cfg = { .uri = CONFIG_BROKER_URI, .crt_bundle_attach = esp_crt_bundle_attach }; esp_mqtt_client_handle_t client = esp_mqtt_client_init(&mqtt_cfg); /* The last argument may be used to pass data to the event handler, in this example mqtt_event_handler */ ret = esp_mqtt_client_register_event(client, MQTT_EVENT_ANY, mqtt_event_handler, NULL); ESP_ERROR_CHECK(ret); ret = esp_mqtt_client_start(client); ESP_ERROR_CHECK(ret); mqtt_client = client; return ret; } esp_err_t init_epd() { esp_err_t ret; reader_info_t reader_info = { .reader_id = CONFIG_FABREADER2_ID, .battery_level = 100 }; buttons_t buttons = { .btn0 = "X", .btn1 = "<", .btn2 = "O", .btn3 = ">" }; display_t display = { .canvas = NULL, .image = NULL, .machine_name = "", .state = "IDLE", .buttons = buttons, .reader_info = reader_info }; ret = epd_init(display); ESP_ERROR_CHECK(ret); return ret; } _Noreturn static void cycle_task(void *arg) { while (1) { TagDetectCycle(); // ESP_LOGI("cycle_task", "running tag detect cycle_task"); } } void app_main(void) { // Log basic information about the system ESP_LOGI("startup", "Startup.."); ESP_LOGI("startup", "Built with IDF version: %s", esp_get_idf_version()); esp_chip_info_t chip_info; esp_chip_info(&chip_info); ESP_LOGI("startup", "This is %s chip with %d CPU cores, WiFi%s%s, ", chip_info.model == CHIP_ESP32S3 ? "ESP32S3" : CHIP_ESP32S2 ? "ESP32S2" : "unknown", chip_info.cores, (chip_info.features & CHIP_FEATURE_BT) ? "/BT" : "", (chip_info.features & CHIP_FEATURE_BLE) ? "/BLE" : ""); // Initialize peripherals ESP_ERROR_CHECK(init_gpio()); ESP_LOGI("main", "init_gpio done"); ESP_ERROR_CHECK(init_spi()); ESP_LOGI("main", "init_spi done"); // ESP_ERROR_CHECK(init_epd()); ESP_LOGI("main", "init_epd done"); ESP_ERROR_CHECK(init_nvs()); ESP_LOGI("main", "init_nvs done"); ESP_ERROR_CHECK(init_eventloop()); ESP_LOGI("main", "init_eventloop done"); ESP_ERROR_CHECK(init_wifi()); ESP_LOGI("main", "init_wifi done"); // epd_update_state("OTA..."); // Start main application ESP_ERROR_CHECK(TagDetectInit()); ESP_LOGI("main", "TagDetectInit done"); xTaskCreate(cycle_task, "cycle_task", 4096, NULL, tskIDLE_PRIORITY, NULL); ESP_LOGI("main", "cycle_task sheduled"); ESP_LOGI("app", "Free memory: %d bytes", esp_get_free_heap_size()); }