/* * SPDX-FileCopyrightText: 2019 Helmut Pozimski * * SPDX-License-Identifier: GPL-2.0-only */ #include #include #include #include #include #include #include #include #include #include #include #include #include "wifi_credentials.h" #include "configuration.h" #define WIFI_LOG_PREFIX "Wifi" #define TCP_LOG_PREFIX "TCP" // Mapping of board pins to the functions they are used for #define MD1 16 #define MD0 17 #define MD 18 #define MC 19 #define MS 21 #define SLAVE_DATA_IN 27 #define SLAVE_BCK_IN 26 #define SLAVE_WS_IN 25 #define GPIO_OUTPUT_PIN_SEL ((1ULL<event_id == SYSTEM_EVENT_STA_START) { ESP_LOGI(WIFI_LOG_PREFIX, "Wifi connection started"); esp_wifi_connect(); } else if (event->event_id == SYSTEM_EVENT_STA_GOT_IP) { ESP_LOGI(WIFI_LOG_PREFIX, "Acquired IP address: %s", ip4addr_ntoa (&event->event_info.got_ip.ip_info.ip)); xEventGroupSetBits(wifi_event_group, WIFI_CONNECTED_BIT); } else if (event->event_id == SYSTEM_EVENT_STA_DISCONNECTED) { ESP_LOGI(WIFI_LOG_PREFIX, "Connection lost"); esp_wifi_connect(); xEventGroupClearBits(wifi_event_group, WIFI_CONNECTED_BIT); } return ESP_OK; } /* * Function: configure_wifi * ------------------------ * Configures the necessary parameters to establish a wifi connection */ static void configure_wifi(void) { wifi_event_group = xEventGroupCreate(); tcpip_adapter_init(); ESP_ERROR_CHECK(esp_event_loop_init(wifi_event_handler, NULL)); wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT(); ESP_ERROR_CHECK(esp_wifi_init(&cfg)); ESP_ERROR_CHECK( esp_wifi_set_storage(WIFI_STORAGE_RAM) ); wifi_config_t wifi_config = { .sta = { .ssid = WIFI_AP, .password = WIFI_WPA_KEY }, }; ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA)); ESP_ERROR_CHECK(esp_wifi_set_config(ESP_IF_WIFI_STA, &wifi_config)); ESP_ERROR_CHECK(esp_wifi_set_protocol(ESP_IF_WIFI_STA, WIFI_PROTOCOL_11B | WIFI_PROTOCOL_11G | WIFI_PROTOCOL_11N)); ESP_ERROR_CHECK(esp_wifi_set_bandwidth(ESP_IF_WIFI_STA, WIFI_BW_HT40)); ESP_ERROR_CHECK(esp_wifi_start()); } /* * Function: setup_gpio * -------------------- * Configures the GPIO Pins that are used * * returns: error code of the configuration operation */ static esp_err_t setup_gpio(void) { esp_err_t gpio_err; PIN_FUNC_SELECT(PERIPHS_IO_MUX_GPIO16_U, FUNC_GPIO16_GPIO16); PIN_FUNC_SELECT(PERIPHS_IO_MUX_GPIO17_U, FUNC_GPIO17_GPIO17); PIN_FUNC_SELECT(PERIPHS_IO_MUX_GPIO18_U, FUNC_GPIO18_GPIO18); PIN_FUNC_SELECT(PERIPHS_IO_MUX_GPIO19_U, FUNC_GPIO19_GPIO19); PIN_FUNC_SELECT(PERIPHS_IO_MUX_GPIO21_U, FUNC_GPIO21_GPIO21); gpio_config_t io_conf = { .intr_type = GPIO_INTR_DISABLE, .mode = GPIO_MODE_OUTPUT, .pin_bit_mask = GPIO_OUTPUT_PIN_SEL, .pull_down_en = 0, .pull_up_en = 0, }; gpio_err = gpio_config(&io_conf); return gpio_err; } /* * Function pcm1808_config * -------------------------- * Sets the MD0 and MD1 inputs for the pcm1808 * * md1: value for input md1 * md0: value for input md0 */ static void pcm1808_config(uint32_t md1, uint32_t md0) { gpio_set(MD1, md1); gpio_set(MD0, md0); } /* Function send_pll_bits * ---------------------- * Sends a bit sequence to configure the PLL1708 * * bits: 16 bit unsigned integer representing the bits to be send from right to left */ static void send_pll_bits(uint16_t bits) { gpio_set(MS,0); gpio_set(MC,0); for (uint8_t i=16; i>0; i--) { vTaskDelay(100 / portTICK_PERIOD_MS); gpio_set(MD, bits & 1); bits = bits >>1; gpio_set(MC, 1); vTaskDelay(100 / portTICK_PERIOD_MS); gpio_set(MC, 0); } gpio_set(MS,1); } /* * Function: setup_i2s * ------------------- * Initializes the i2s driver with the proper configuration */ static void setup_i2s(void) { i2s_config_t i2s_config = { .mode = I2S_MODE_SLAVE | I2S_MODE_RX, .sample_rate = SAMPLE_RATE, .bits_per_sample = I2S_BITS_PER_SAMPLE_32BIT, .channel_format = I2S_CHANNEL_FMT_ONLY_LEFT, .communication_format = I2S_COMM_FORMAT_I2S, .dma_buf_count = 35, .dma_buf_len = 256 }; i2s_pin_config_t pin_config = { .bck_io_num = SLAVE_BCK_IN, .ws_io_num = SLAVE_WS_IN, .data_in_num = SLAVE_DATA_IN, .data_out_num = I2S_PIN_NO_CHANGE }; ESP_ERROR_CHECK(i2s_driver_install(I2S_NUM_0, &i2s_config, 0, NULL)); ESP_ERROR_CHECK(i2s_set_pin(I2S_NUM_0, &pin_config)); } /* * Function: transmit_task * Function that reads values from i2s and transmits them via TCP, it represents the main task * * pvParameters: parameters passed to the task */ static void transmit_task(void *pvParameters) { send_pll_bits(pll_seq); struct sockaddr_in dest_addr; dest_addr.sin_addr.s_addr = inet_addr(TARGET_HOST); dest_addr.sin_family = AF_INET; dest_addr.sin_port = htons(TARGET_PORT); int sock = 0; void *transmit_buffer = malloc(1458); if (transmit_buffer == NULL) { ESP_LOGE("MALLOC", "Could not allocate memory for data buffer"); } uint16_t offset = 0; unsigned int bytes_read; int err; sync sync_data = { .sample_rate = SAMPLE_RATE, .bits_per_sample = 24 }; sync_ack ack; while (1) { if (sock != 0) { close(sock); } sock = socket(dest_addr.sin_family, SOCK_STREAM, IPPROTO_IP); if (sock < 0) { ESP_LOGE(TCP_LOG_PREFIX, "Could not create socket"); continue; } xEventGroupWaitBits(wifi_event_group, WIFI_CONNECTED_BIT, false, true, portMAX_DELAY); ESP_LOGI(TCP_LOG_PREFIX, "Establishing connection"); err = connect(sock, (struct sockaddr*)&dest_addr, sizeof(dest_addr)); if (err != 0) { ESP_LOGE(TCP_LOG_PREFIX, "Failed to establish a TCP connection"); continue; } send(sock, &sync_data, sizeof(sync_data), 0); recv(sock, &ack, sizeof(ack), 0); if ((strcmp(ack.ack, "ACK") !=0) || (ack.dat.sample_rate != SAMPLE_RATE) || (ack.dat.bits_per_sample != 24)) { ESP_LOGE(TCP_LOG_PREFIX, "Synchronisation with server not successful"); continue; } ESP_LOGI(TCP_LOG_PREFIX, "Connection successfully established"); uint8_t discard; while (1) { if (offset < 1458) { i2s_read(I2S_NUM_0, transmit_buffer + offset, 3, &bytes_read, portMAX_DELAY); offset += 3; i2s_read(I2S_NUM_0, &discard, 1, &bytes_read, portMAX_DELAY); } if (offset == 1458) { err = send(sock, transmit_buffer, 1458, 0); if (err < 0) { ESP_LOGE(TCP_LOG_PREFIX, "TCP connection lost"); break; } offset = 0; } } } vTaskDelete(NULL); } /* * Function: app_main * ------------------ * Entry function that sets up the main task and initializes everything */ void app_main(void) { ESP_ERROR_CHECK(nvs_flash_init()); configure_wifi(); xEventGroupWaitBits(wifi_event_group, WIFI_CONNECTED_BIT, false, true, portMAX_DELAY); // Initialize GPIO pins ESP_ERROR_CHECK(setup_gpio()); // Set PCM1808 configuration pcm1808_config(0, 1); // Power down PLL1708 send_pll_bits(40974); // Initialize the i2s driver setup_i2s(); xTaskCreate(transmit_task, "transmit_task", 4096, NULL, 7, NULL); }