aes67_config.h 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233
  1. /*
  2. * SPDX-FileCopyrightText: 2026 DatanoiseTV
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. */
  6. /*
  7. * AES67 configuration structures.
  8. *
  9. * Kconfig provides compile-time defaults; these structs allow runtime
  10. * override before node initialization.
  11. *
  12. * Key design: all buffer sizes and frame counts are COMPUTED from the
  13. * base audio parameters (sample_rate, channels, word_length, packet_time_us)
  14. * via aes67_stream_params_compute(). No hardcoded 192, 2, 48000, etc.
  15. */
  16. #pragma once
  17. #include <stdint.h>
  18. #include <stdbool.h>
  19. #include "esp_eth.h"
  20. #ifdef __cplusplus
  21. extern "C" {
  22. #endif
  23. /* ---- Version ---- */
  24. #define AES67_VERSION_MAJOR 2
  25. #define AES67_VERSION_MINOR 2
  26. #define AES67_VERSION_PATCH 0
  27. /* ---- Limits ---- */
  28. #define AES67_MAX_CHANNELS_PER_STREAM 8
  29. #define AES67_MAX_TIC_FRAMES 1024
  30. #define AES67_MIN_TIC_FRAMES 48
  31. #define AES67_RTP_HEADER_SIZE 12
  32. #define AES67_MAX_WORD_LENGTH 4 /* AM824/L32 = 4 bytes */
  33. /* ---- Enums ---- */
  34. /* Audio codec identifiers matching AES67/RAVENNA conventions */
  35. typedef enum {
  36. AES67_CODEC_L16 = 0, /* 16-bit linear PCM, word_length=2 */
  37. AES67_CODEC_L24, /* 24-bit linear PCM, word_length=3 */
  38. AES67_CODEC_L32, /* 32-bit linear PCM, word_length=4 */
  39. AES67_CODEC_AM824, /* IEC 61937 / AM824, word_length=4 */
  40. } aes67_codec_t;
  41. /* Output mode for received audio data */
  42. typedef enum {
  43. AES67_OUTPUT_I2S = 0, /* Direct I2S output (default) */
  44. AES67_OUTPUT_STREAM_BUFFER, /* FreeRTOS StreamBuffer for app processing */
  45. AES67_OUTPUT_CALLBACK, /* User callback per packet */
  46. } aes67_output_mode_t;
  47. /* Callback for received audio data (when output_mode == AES67_OUTPUT_CALLBACK) */
  48. typedef void (*aes67_audio_data_cb_t)(const int32_t *samples,
  49. uint32_t frame_count,
  50. uint8_t channels,
  51. uint8_t word_length,
  52. uint32_t sample_rate,
  53. void *user_data);
  54. /* ---- Stream Parameters (computed, not configured) ---- */
  55. /*
  56. * Derived parameters computed from the base audio config.
  57. * Use aes67_stream_params_compute() to populate.
  58. * These replace all hardcoded 192, 768, 1536, etc.
  59. */
  60. typedef struct {
  61. /* From config */
  62. uint32_t sample_rate;
  63. uint8_t channels;
  64. uint8_t word_length; /* Bytes per sample on the wire (2/3/4) */
  65. uint16_t packet_time_us;
  66. /* Computed */
  67. uint32_t samples_per_packet; /* Frames per RTP packet (e.g., 48, 192) */
  68. uint32_t frame_bytes_wire; /* Bytes per frame on wire: channels * word_length */
  69. uint32_t frame_bytes_native; /* Bytes per frame in memory: channels * 4 (int32) */
  70. uint32_t packet_payload_size; /* RTP payload bytes: spp * frame_bytes_wire */
  71. uint32_t packet_native_size; /* Converted packet bytes: spp * frame_bytes_native */
  72. uint32_t max_packet_payload; /* Max RTP payload: MAX_TIC_FRAMES * frame_bytes_wire */
  73. } aes67_stream_params_t;
  74. /* Compute derived parameters from base config */
  75. static inline void aes67_stream_params_compute(aes67_stream_params_t *p,
  76. uint32_t sample_rate,
  77. uint8_t channels,
  78. uint8_t word_length,
  79. uint16_t packet_time_us)
  80. {
  81. p->sample_rate = sample_rate;
  82. p->channels = channels;
  83. p->word_length = word_length;
  84. p->packet_time_us = packet_time_us;
  85. p->samples_per_packet = (sample_rate * (uint32_t)packet_time_us) / 1000000;
  86. if (p->samples_per_packet == 0) p->samples_per_packet = 48;
  87. if (p->samples_per_packet > AES67_MAX_TIC_FRAMES) {
  88. p->samples_per_packet = AES67_MAX_TIC_FRAMES;
  89. }
  90. p->frame_bytes_wire = (uint32_t)channels * word_length;
  91. p->frame_bytes_native = (uint32_t)channels * sizeof(int32_t);
  92. p->packet_payload_size = p->samples_per_packet * p->frame_bytes_wire;
  93. p->packet_native_size = p->samples_per_packet * p->frame_bytes_native;
  94. p->max_packet_payload = AES67_MAX_TIC_FRAMES * p->frame_bytes_wire;
  95. }
  96. /* Get word_length from codec enum */
  97. static inline uint8_t aes67_codec_word_length(aes67_codec_t codec)
  98. {
  99. switch (codec) {
  100. case AES67_CODEC_L16: return 2;
  101. case AES67_CODEC_L24: return 3;
  102. case AES67_CODEC_L32: return 4;
  103. case AES67_CODEC_AM824: return 4;
  104. default: return 3;
  105. }
  106. }
  107. /* Get codec from word_length */
  108. static inline aes67_codec_t aes67_word_length_codec(uint8_t wl)
  109. {
  110. switch (wl) {
  111. case 2: return AES67_CODEC_L16;
  112. case 3: return AES67_CODEC_L24;
  113. case 4: return AES67_CODEC_L32;
  114. default: return AES67_CODEC_L24;
  115. }
  116. }
  117. /* ---- Configuration Structs ---- */
  118. /* Network configuration */
  119. typedef struct {
  120. char interface_name[16]; /* Ethernet interface, e.g. "ETH_0" */
  121. esp_eth_handle_t eth_handle; /* Ethernet driver handle */
  122. char rtp_mcast_base[16]; /* Base multicast address for RTP */
  123. uint16_t rtp_port; /* RTP port (default 5004) */
  124. uint8_t ttl; /* Multicast TTL */
  125. uint8_t dscp; /* DSCP for QoS (default 46 = EF) */
  126. } aes67_net_config_t;
  127. /* PTP configuration */
  128. typedef struct {
  129. uint8_t domain; /* PTP domain 0-127 */
  130. uint8_t dscp; /* DSCP for PTP packets */
  131. bool prefer_grandmaster; /* Become GM if no other master found */
  132. } aes67_ptp_config_t;
  133. /* Audio configuration */
  134. typedef struct {
  135. uint32_t sample_rate; /* Sample rate in Hz (44100 or 48000) */
  136. uint8_t word_length; /* Bytes per sample (2, 3, or 4) */
  137. uint16_t packet_time_us; /* Packet time in microseconds */
  138. uint8_t channels; /* Number of audio channels (1-8) */
  139. aes67_codec_t codec; /* Audio codec */
  140. } aes67_audio_config_t;
  141. /* I2S pin configuration */
  142. typedef struct {
  143. int mck_gpio;
  144. int bck_gpio;
  145. int ws_gpio;
  146. int dout_gpio;
  147. int din_gpio;
  148. } aes67_i2s_pins_t;
  149. /* Top-level node configuration */
  150. typedef struct {
  151. char node_name[64]; /* Node name for SDP/mDNS */
  152. aes67_net_config_t net;
  153. aes67_ptp_config_t ptp;
  154. aes67_audio_config_t audio;
  155. aes67_i2s_pins_t i2s_pins;
  156. uint16_t jitter_buffer_ms; /* Jitter buffer depth in ms */
  157. uint16_t ring_buffer_ms; /* Audio ring buffer size in ms */
  158. bool use_psram; /* Allocate large buffers in PSRAM */
  159. bool sap_enabled; /* Enable SAP announcements */
  160. bool mdns_enabled; /* Enable mDNS advertisement */
  161. /* Output routing */
  162. aes67_output_mode_t output_mode; /* How to deliver received audio */
  163. aes67_audio_data_cb_t audio_cb; /* Callback (when mode == CALLBACK) */
  164. void *audio_cb_user_data; /* User data for callback */
  165. } aes67_config_t;
  166. /* Initialize a config struct with Kconfig defaults */
  167. #define AES67_CONFIG_DEFAULT() { \
  168. .node_name = CONFIG_AES67_NODE_NAME, \
  169. .net = { \
  170. .interface_name = "ETH_0", \
  171. .eth_handle = NULL, \
  172. .rtp_mcast_base = CONFIG_AES67_RTP_MCAST_BASE, \
  173. .rtp_port = CONFIG_AES67_RTP_PORT, \
  174. .ttl = 64, \
  175. .dscp = 46, \
  176. }, \
  177. .ptp = { \
  178. .domain = CONFIG_AES67_PTP_DOMAIN, \
  179. .dscp = 46, \
  180. .prefer_grandmaster = true, \
  181. }, \
  182. .audio = { \
  183. .sample_rate = CONFIG_AES67_DEFAULT_SAMPLE_RATE, \
  184. .word_length = CONFIG_AES67_DEFAULT_WORD_LENGTH, \
  185. .packet_time_us = CONFIG_AES67_DEFAULT_PACKET_TIME_US, \
  186. .channels = CONFIG_AES67_DEFAULT_CHANNELS, \
  187. .codec = AES67_CODEC_L24, \
  188. }, \
  189. .i2s_pins = { \
  190. .mck_gpio = CONFIG_AES67_I2S_MCK_GPIO, \
  191. .bck_gpio = CONFIG_AES67_I2S_BCK_GPIO, \
  192. .ws_gpio = CONFIG_AES67_I2S_WS_GPIO, \
  193. .dout_gpio = CONFIG_AES67_I2S_DOUT_GPIO, \
  194. .din_gpio = CONFIG_AES67_I2S_DIN_GPIO, \
  195. }, \
  196. .jitter_buffer_ms = CONFIG_AES67_JITTER_BUFFER_MS, \
  197. .ring_buffer_ms = CONFIG_AES67_AUDIO_RING_BUFFER_MS, \
  198. .use_psram = true, \
  199. .sap_enabled = true, \
  200. .mdns_enabled = true, \
  201. .output_mode = AES67_OUTPUT_I2S, \
  202. .audio_cb = NULL, \
  203. .audio_cb_user_data = NULL, \
  204. }
  205. #ifdef __cplusplus
  206. }
  207. #endif