transmit_i2s.c 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306
  1. /*
  2. * SPDX-FileCopyrightText: 2019 Helmut Pozimski <helmut@pozimski.eu>
  3. *
  4. * SPDX-License-Identifier: GPL-2.0-only
  5. */
  6. #include <freertos/FreeRTOS.h>
  7. #include <freertos/event_groups.h>
  8. #include <esp_event.h>
  9. #include <esp_wifi.h>
  10. #include <esp_log.h>
  11. #include <esp_event_loop.h>
  12. #include <driver/gpio.h>
  13. #include <driver/i2s.h>
  14. #include <lwip/sockets.h>
  15. #include <soc/io_mux_reg.h>
  16. #include <nvs_flash.h>
  17. #include <string.h>
  18. #include "wifi_credentials.h"
  19. #include "configuration.h"
  20. #define WIFI_LOG_PREFIX "Wifi"
  21. #define TCP_LOG_PREFIX "TCP"
  22. // Mapping of board pins to the functions they are used for
  23. /* Pins for PCM1808 */
  24. #define MD1 16
  25. #define MD0 17
  26. #define FMT 23
  27. /* Pins for PLL1708 */
  28. #define MD 18
  29. #define MC 19
  30. #define MS 21
  31. #define CSEL 22
  32. #define SLAVE_DATA_IN 27
  33. #define SLAVE_BCK_IN 26
  34. #define SLAVE_WS_IN 25
  35. #define GPIO_OUTPUT_PIN_SEL ((1ULL<<MD0) |(1ULL<<MD1) | (1ULL<<MD) | (1ULL<<MC) \
  36. | (1ULL<<MS) | (1ULL<<CSEL) | (1ULL<<FMT))
  37. #define gpio_set(x,y) ESP_ERROR_CHECK(gpio_set_level(x,y))
  38. /* Bit sequence to send to the clock generator */
  39. #if SAMPLE_RATE == 8000
  40. static uint16_t pll_seq = 21518;
  41. #elif SAMPLE_RATE == 16000
  42. static uint16_t pll_seq = 17422;
  43. #elif SAMPLE_RATE == 32000
  44. static uint16_t pll_seq = 25614;
  45. #elif SAMPLE_RATE == 44100
  46. static uint16_t pll_seq = 41998;
  47. #elif SAMPLE_RATE == 48000
  48. static uint16_t pll_seq = 9230;
  49. #endif
  50. /* Event group for Wifi events */
  51. static EventGroupHandle_t wifi_event_group;
  52. /* Bit to signal that a connection to the AP has been establisched */
  53. const int WIFI_CONNECTED_BIT = BIT0 ;
  54. /* Structures to handle synchronisation with the server */
  55. typedef struct {
  56. uint32_t sample_rate;
  57. uint32_t bits_per_sample;
  58. } sync;
  59. typedef struct {
  60. char ack[4];
  61. sync dat;
  62. } sync_ack;
  63. /*
  64. * Function: wifi_event_handler
  65. * ----------------------------
  66. * Callback function that handles wifi events
  67. *
  68. * ctx: context from which the function was called
  69. * event: event that occured and should be handled
  70. *
  71. * returns: an error code
  72. */
  73. static esp_err_t wifi_event_handler(void *ctx, system_event_t *event) {
  74. ESP_LOGI(WIFI_LOG_PREFIX, "Event handler called");
  75. if (event->event_id == SYSTEM_EVENT_STA_START) {
  76. ESP_LOGI(WIFI_LOG_PREFIX, "Wifi connection started");
  77. esp_wifi_connect();
  78. } else if (event->event_id == SYSTEM_EVENT_STA_GOT_IP) {
  79. ESP_LOGI(WIFI_LOG_PREFIX, "Acquired IP address: %s",
  80. ip4addr_ntoa (&event->event_info.got_ip.ip_info.ip));
  81. xEventGroupSetBits(wifi_event_group, WIFI_CONNECTED_BIT);
  82. } else if (event->event_id == SYSTEM_EVENT_STA_DISCONNECTED) {
  83. ESP_LOGI(WIFI_LOG_PREFIX, "Connection lost");
  84. esp_wifi_connect();
  85. xEventGroupClearBits(wifi_event_group, WIFI_CONNECTED_BIT);
  86. }
  87. return ESP_OK;
  88. }
  89. /*
  90. * Function: configure_wifi
  91. * ------------------------
  92. * Configures the necessary parameters to establish a wifi connection
  93. */
  94. static void configure_wifi(void) {
  95. wifi_event_group = xEventGroupCreate();
  96. tcpip_adapter_init();
  97. ESP_ERROR_CHECK(esp_event_loop_init(wifi_event_handler, NULL));
  98. wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
  99. ESP_ERROR_CHECK(esp_wifi_init(&cfg));
  100. ESP_ERROR_CHECK( esp_wifi_set_storage(WIFI_STORAGE_RAM) );
  101. wifi_config_t wifi_config = {
  102. .sta = {
  103. .ssid = WIFI_AP,
  104. .password = WIFI_WPA_KEY
  105. },
  106. };
  107. ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA));
  108. ESP_ERROR_CHECK(esp_wifi_set_config(ESP_IF_WIFI_STA, &wifi_config));
  109. ESP_ERROR_CHECK(esp_wifi_set_protocol(ESP_IF_WIFI_STA, WIFI_PROTOCOL_11B |
  110. WIFI_PROTOCOL_11G | WIFI_PROTOCOL_11N));
  111. ESP_ERROR_CHECK(esp_wifi_set_bandwidth(ESP_IF_WIFI_STA, WIFI_BW_HT40));
  112. ESP_ERROR_CHECK(esp_wifi_start());
  113. }
  114. /*
  115. * Function: setup_gpio
  116. * --------------------
  117. * Configures the GPIO Pins that are used
  118. *
  119. * returns: error code of the configuration operation
  120. */
  121. static esp_err_t setup_gpio(void) {
  122. esp_err_t gpio_err;
  123. PIN_FUNC_SELECT(PERIPHS_IO_MUX_GPIO16_U, FUNC_GPIO16_GPIO16);
  124. PIN_FUNC_SELECT(PERIPHS_IO_MUX_GPIO17_U, FUNC_GPIO17_GPIO17);
  125. PIN_FUNC_SELECT(PERIPHS_IO_MUX_GPIO18_U, FUNC_GPIO18_GPIO18);
  126. PIN_FUNC_SELECT(PERIPHS_IO_MUX_GPIO19_U, FUNC_GPIO19_GPIO19);
  127. PIN_FUNC_SELECT(PERIPHS_IO_MUX_GPIO21_U, FUNC_GPIO21_GPIO21);
  128. PIN_FUNC_SELECT(PERIPHS_IO_MUX_GPIO22_U, FUNC_GPIO22_GPIO22);
  129. PIN_FUNC_SELECT(PERIPHS_IO_MUX_GPIO23_U, FUNC_GPIO23_GPIO23);
  130. gpio_config_t io_conf = {
  131. .intr_type = GPIO_INTR_DISABLE,
  132. .mode = GPIO_MODE_OUTPUT,
  133. .pin_bit_mask = GPIO_OUTPUT_PIN_SEL,
  134. .pull_down_en = 0,
  135. .pull_up_en = 0,
  136. };
  137. gpio_err = gpio_config(&io_conf);
  138. return gpio_err;
  139. }
  140. /*
  141. * Function pcm1808_config
  142. * --------------------------
  143. * Sets the MD0 and MD1 inputs for the pcm1808
  144. *
  145. * md1: value for input md1
  146. * md0: value for input md0
  147. */
  148. static void pcm1808_config(uint32_t md1, uint32_t md0) {
  149. gpio_set(MD1, md1);
  150. gpio_set(MD0, md0);
  151. gpio_set(FMT, 0);
  152. }
  153. /* Function send_pll_bits
  154. * ----------------------
  155. * Sends a bit sequence to configure the PLL1708
  156. *
  157. * bits: 16 bit unsigned integer representing the bits to be send from right to left
  158. */
  159. static void send_pll_bits(uint16_t bits) {
  160. gpio_set(MS,0);
  161. gpio_set(MC,0);
  162. for (uint8_t i=16; i>0; i--) {
  163. vTaskDelay(100 / portTICK_PERIOD_MS);
  164. gpio_set(MD, bits & 1);
  165. bits = bits >>1;
  166. gpio_set(MC, 1);
  167. vTaskDelay(100 / portTICK_PERIOD_MS);
  168. gpio_set(MC, 0);
  169. }
  170. gpio_set(MS,1);
  171. }
  172. /*
  173. * Function: setup_i2s
  174. * -------------------
  175. * Initializes the i2s driver with the proper configuration
  176. */
  177. static void setup_i2s(void) {
  178. i2s_config_t i2s_config = {
  179. .mode = I2S_MODE_SLAVE | I2S_MODE_RX,
  180. .sample_rate = SAMPLE_RATE,
  181. .bits_per_sample = I2S_BITS_PER_SAMPLE_32BIT,
  182. .channel_format = I2S_CHANNEL_FMT_ONLY_LEFT,
  183. .communication_format = I2S_COMM_FORMAT_I2S,
  184. .dma_buf_count = 35,
  185. .dma_buf_len = 256
  186. };
  187. i2s_pin_config_t pin_config = {
  188. .bck_io_num = SLAVE_BCK_IN,
  189. .ws_io_num = SLAVE_WS_IN,
  190. .data_in_num = SLAVE_DATA_IN,
  191. .data_out_num = I2S_PIN_NO_CHANGE
  192. };
  193. ESP_ERROR_CHECK(i2s_driver_install(I2S_NUM_0, &i2s_config, 0, NULL));
  194. ESP_ERROR_CHECK(i2s_set_pin(I2S_NUM_0, &pin_config));
  195. }
  196. /*
  197. * Function: transmit_task
  198. * Function that reads values from i2s and transmits them via TCP, it represents the main task
  199. *
  200. * pvParameters: parameters passed to the task
  201. */
  202. static void transmit_task(void *pvParameters) {
  203. send_pll_bits(pll_seq);
  204. struct sockaddr_in dest_addr;
  205. dest_addr.sin_addr.s_addr = inet_addr(TARGET_HOST);
  206. dest_addr.sin_family = AF_INET;
  207. dest_addr.sin_port = htons(TARGET_PORT);
  208. int sock = 0;
  209. void *transmit_buffer = malloc(1458);
  210. if (transmit_buffer == NULL) {
  211. ESP_LOGE("MALLOC", "Could not allocate memory for data buffer");
  212. }
  213. uint16_t offset = 0;
  214. unsigned int bytes_read;
  215. int err;
  216. sync sync_data = {
  217. .sample_rate = SAMPLE_RATE,
  218. .bits_per_sample = 24
  219. };
  220. sync_ack ack;
  221. while (1) {
  222. if (sock != 0) {
  223. close(sock);
  224. }
  225. sock = socket(dest_addr.sin_family, SOCK_STREAM, IPPROTO_IP);
  226. if (sock < 0) {
  227. ESP_LOGE(TCP_LOG_PREFIX, "Could not create socket");
  228. continue;
  229. }
  230. xEventGroupWaitBits(wifi_event_group, WIFI_CONNECTED_BIT, false, true, portMAX_DELAY);
  231. ESP_LOGI(TCP_LOG_PREFIX, "Establishing connection");
  232. err = connect(sock, (struct sockaddr*)&dest_addr, sizeof(dest_addr));
  233. if (err != 0) {
  234. ESP_LOGE(TCP_LOG_PREFIX, "Failed to establish a TCP connection");
  235. continue;
  236. }
  237. send(sock, &sync_data, sizeof(sync_data), 0);
  238. recv(sock, &ack, sizeof(ack), 0);
  239. if ((strcmp(ack.ack, "ACK") !=0) || (ack.dat.sample_rate != SAMPLE_RATE) || (ack.dat.bits_per_sample != 24)) {
  240. ESP_LOGE(TCP_LOG_PREFIX, "Synchronisation with server not successful");
  241. continue;
  242. }
  243. ESP_LOGI(TCP_LOG_PREFIX, "Connection successfully established");
  244. uint8_t discard;
  245. while (1) {
  246. if (offset < 1458) {
  247. i2s_read(I2S_NUM_0, transmit_buffer + offset, 3, &bytes_read, portMAX_DELAY);
  248. offset += 3;
  249. i2s_read(I2S_NUM_0, &discard, 1, &bytes_read, portMAX_DELAY);
  250. }
  251. if (offset == 1458) {
  252. err = send(sock, transmit_buffer, 1458, 0);
  253. if (err < 0) {
  254. ESP_LOGE(TCP_LOG_PREFIX, "TCP connection lost");
  255. break;
  256. }
  257. offset = 0;
  258. }
  259. }
  260. }
  261. vTaskDelete(NULL);
  262. }
  263. /*
  264. * Function: app_main
  265. * ------------------
  266. * Entry function that sets up the main task and initializes everything
  267. */
  268. void app_main(void) {
  269. ESP_ERROR_CHECK(nvs_flash_init());
  270. configure_wifi();
  271. xEventGroupWaitBits(wifi_event_group, WIFI_CONNECTED_BIT, false, true, portMAX_DELAY);
  272. // Initialize GPIO pins
  273. ESP_ERROR_CHECK(setup_gpio());
  274. // Set PCM1808 configuration
  275. pcm1808_config(0, 1);
  276. gpio_set(CSEL, 0);
  277. // Power down PLL1708
  278. send_pll_bits(40974);
  279. // Initialize the i2s driver
  280. setup_i2s();
  281. xTaskCreate(transmit_task, "transmit_task", 4096, NULL, 7, NULL);
  282. }