// #define DEBUG #define BAUD_RATE 115200 #include "common.h" #include "fpga.h" #include "wifi.h" #include "config.h" #include "led.h" #include "tty.h" #include "boardinfo_esp.h" #include #include #include #include #include #include #define PIN_USB_PWR_EN 7 #define PIN_USB_PWR_SINK 8 uint8_t efuse_default_mac[6]; void setup_usb_ids() { uint8_t * const mac = efuse_default_mac; char serial[16]; esp_efuse_mac_get_default(mac); snprintf(serial, sizeof serial, "%02X%02X%02X-%02X%02X%02X", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); USB.VID(0x4680); USB.PID(0x0882); USB.firmwareVersion(1); // Do something smarter here USB.productName("MAX80 Network Controller"); USB.manufacturerName("Peter & Per"); USB.serialNumber(serial); } static void heap_info() { size_t il = heap_caps_get_largest_free_block(MALLOC_CAP_INTERNAL); size_t ia = heap_caps_get_free_size(MALLOC_CAP_INTERNAL); size_t sl = heap_caps_get_largest_free_block(MALLOC_CAP_SPIRAM); size_t sa = heap_caps_get_free_size(MALLOC_CAP_SPIRAM); printf("Heap: sram %zu/%zu, spiram %zu/%zu\n", il, ia, sl, sa); } static void dump_config() { printf("--- Configuration:\n"); write_env(stdout, false); printf("--- Status:\n"); write_env(stdout, true); printf("--- End configuration and status\n"); } uint8_t max80_board_version; static void init_hw() { // Start out with disabled shared I/O pins for (int i = 1; i <= 18; i++) pinMode(i, INPUT); // Query board info board_info_init(); // Make sure FPGA nCE input (board 2.1+) is not accidentally pulled high fpga_enable_nce(); // Configure USB power control. Try to detect 36k pulldown // resistor on USB_PWR_EN first, to determine board version 2 // (on board v1, this pin in N/C.) // // This detection algorithm is sketchy at best. In the end the // better option probably would be to use the ADC mode of the input // pin... pinMode(PIN_USB_PWR_SINK, OUTPUT); // IO8: USB_PWR_SINK digitalWrite(PIN_USB_PWR_SINK, 0); // This is a power sink #if 0 pinMode(PIN_USB_PWR_EN, OUTPUT); digitalWrite(PIN_USB_PWR_EN, 0); delayMicroseconds(100); pinMode(PIN_USB_PWR_EN, INPUT_PULLUP); delayMicroseconds(50); pinMode(PIN_USB_PWR_EN, INPUT); delayMicroseconds(50); max80_board_version = digitalRead(PIN_USB_PWR_EN) ? 1 : 2; #else max80_board_version = 2; #endif pinMode(PIN_USB_PWR_EN, OUTPUT); digitalWrite(PIN_USB_PWR_EN, 0); delayMicroseconds(50); // Configure LEDs led_init(); led_set(LED_BLUE, LED_FLASH); // ESP32 software initializing } void setup() { const char *fwdate = __DATE__ " " __TIME__; init_hw(); // Enable external PSRAM for heap heap_caps_malloc_extmem_enable(3000); // >= 3K allocations in PSRAM heap_info(); TTY::init(); heap_info(); printf("[FW] MAX80 firmware compiled on %s\n", fwdate); printf("[PCB] MAX80 board version: %s\n", board_info.version_str); setenv_cond("status.max80.hw.ver", board_info.version_str); Serial.println("MAX80 start"); init_config(); setenv_cond("status.max80.fw.date", fwdate); fpga_service_init(); fpga_service_enable(true); SetupWiFi(); Serial.println("[RDY]"); dump_config(); led_set(LED_BLUE, LED_ON); // Software ready heap_info(); } static inline char task_state(eTaskState state) { switch (state) { case eInvalid: return 'X'; case eReady: case eRunning: return 'R'; case eBlocked: return 'D'; case eSuspended: return 'S'; case eDeleted: return 'Z'; default: return '?'; } } static void dump_tasks(void) { TaskHandle_t task = NULL; while (1) { task = pxTaskGetNext(task); if (!task) break; printf("%-16s %c %2u\n", pcTaskGetName(task), task_state(eTaskGetState(task)), uxTaskPriorityGet(task)); } } void loop() { if (1) { printf("loop task: %s\n", pcTaskGetName(xTaskGetCurrentTaskHandle())); printf("idle task: %s\n", pcTaskGetName(xTaskGetIdleTaskHandle())); dump_tasks(); heap_info(); putchar('\n'); } TTY::ping(); vTaskDelay(5 * configTICK_RATE_HZ); }