transmit_i2s.c 8.5 KB

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