123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308 |
- /*
- * SPDX-FileCopyrightText: 2019 Helmut Pozimski <helmut@pozimski.eu>
- *
- * SPDX-License-Identifier: GPL-2.0-only
- */
- #include <freertos/FreeRTOS.h>
- #include <freertos/event_groups.h>
- #include <esp_event.h>
- #include <esp_wifi.h>
- #include <esp_log.h>
- #include <esp_event_loop.h>
- #include <driver/gpio.h>
- #include <driver/i2s.h>
- #include <lwip/sockets.h>
- #include <soc/io_mux_reg.h>
- #include <nvs_flash.h>
- #include <string.h>
- #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
- /* Pins for PCM1808 */
- #define MD1 16
- #define MD0 17
- #define FMT 23
- /* Pins for PLL1708 */
- #define MD 18
- #define MC 19
- #define MS 21
- #define CSEL 22
- #define SLAVE_DATA_IN 27
- #define SLAVE_BCK_IN 26
- #define SLAVE_WS_IN 25
- #define GPIO_OUTPUT_PIN_SEL ((1ULL<<MD0) |(1ULL<<MD1) | (1ULL<<MD) | (1ULL<<MC) \
- | (1ULL<<MS) | (1ULL<<CSEL) | (1ULL<<FMT))
- #define gpio_set(x,y) ESP_ERROR_CHECK(gpio_set_level(x,y))
- /* Bit sequence to send to the clock generator */
- #if SAMPLE_RATE == 8000 || SAMPLE_RATE == 16000
- static uint16_t pll_seq = 21518;
- #elif SAMPLE_RATE == 32000
- static uint16_t pll_seq = 17422;
- #elif SAMPLE_RATE == 44100
- static uint16_t pll_seq = 33806;
- #elif SAMPLE_RATE == 48000
- static uint16_t pll_seq = 1038;
- #endif
- /* Event group for Wifi events */
- static EventGroupHandle_t wifi_event_group;
- /* Bit to signal that a connection to the AP has been establisched */
- const int WIFI_CONNECTED_BIT = BIT0 ;
- /* Structures to handle synchronisation with the server */
- typedef struct {
- uint32_t sample_rate;
- uint32_t bits_per_sample;
- } sync;
- typedef struct {
- char ack[4];
- sync dat;
- } sync_ack;
- /*
- * Function: wifi_event_handler
- * ----------------------------
- * Callback function that handles wifi events
- *
- * ctx: context from which the function was called
- * event: event that occured and should be handled
- *
- * returns: an error code
- */
- static esp_err_t wifi_event_handler(void *ctx, system_event_t *event) {
- ESP_LOGI(WIFI_LOG_PREFIX, "Event handler called");
- if (event->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);
- PIN_FUNC_SELECT(PERIPHS_IO_MUX_GPIO22_U, FUNC_GPIO22_GPIO22);
- PIN_FUNC_SELECT(PERIPHS_IO_MUX_GPIO23_U, FUNC_GPIO23_GPIO23);
- 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);
- gpio_set(FMT, 0);
- }
- /* 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
- if (SAMPLE_RATE == 8000) {
- pcm1808_config(0, 1);
- } else {
- pcm1808_config(1, 1);
- }
- gpio_set(CSEL, 0);
- // Power down PLL1708
- send_pll_bits(40974);
- // Initialize the i2s driver
- setup_i2s();
- xTaskCreate(transmit_task, "transmit_task", 4096, NULL, 7, NULL);
- }
|