drv_sigma_delta.c 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120
  1. /*
  2. This file contains the sigma-delta driver implementation.
  3. */
  4. #include "platform.h"
  5. #include "hw_timer.h"
  6. #include "task/task.h"
  7. #include <stdlib.h>
  8. #include "pcm.h"
  9. static const os_param_t drv_sd_hw_timer_owner = 0x70636D; // "pcm"
  10. static void ICACHE_RAM_ATTR drv_sd_timer_isr( os_param_t arg )
  11. {
  12. cfg_t *cfg = (cfg_t *)arg;
  13. pcm_buf_t *buf = &(cfg->bufs[cfg->rbuf_idx]);
  14. if (cfg->isr_throttled) {
  15. return;
  16. }
  17. if (!buf->empty) {
  18. uint16_t tmp;
  19. // buffer is not empty, continue reading
  20. tmp = abs((int16_t)(buf->data[buf->rpos]) - 128);
  21. if (tmp > cfg->vu_peak_tmp) {
  22. cfg->vu_peak_tmp = tmp;
  23. }
  24. cfg->vu_samples_tmp++;
  25. if (cfg->vu_samples_tmp >= cfg->vu_req_samples) {
  26. cfg->vu_peak = cfg->vu_peak_tmp;
  27. task_post_low( pcm_data_vu_task, (os_param_t)cfg );
  28. cfg->vu_samples_tmp = 0;
  29. cfg->vu_peak_tmp = 0;
  30. }
  31. platform_sigma_delta_set_target( buf->data[buf->rpos++] );
  32. if (buf->rpos >= buf->len) {
  33. // buffer data consumed, request to re-fill it
  34. buf->empty = TRUE;
  35. cfg->fbuf_idx = cfg->rbuf_idx;
  36. task_post_high( pcm_data_play_task, (os_param_t)cfg );
  37. // switch to next buffer
  38. cfg->rbuf_idx ^= 1;
  39. dbg_platform_gpio_write( PLATFORM_GPIO_LOW );
  40. }
  41. } else {
  42. // flag ISR throttled
  43. cfg->isr_throttled = 1;
  44. dbg_platform_gpio_write( PLATFORM_GPIO_LOW );
  45. cfg->fbuf_idx = cfg->rbuf_idx;
  46. task_post_high( pcm_data_play_task, (os_param_t)cfg );
  47. }
  48. }
  49. static uint8_t drv_sd_stop( cfg_t *cfg )
  50. {
  51. platform_hw_timer_close( drv_sd_hw_timer_owner );
  52. return TRUE;
  53. }
  54. static uint8_t drv_sd_close( cfg_t *cfg )
  55. {
  56. drv_sd_stop( cfg );
  57. platform_sigma_delta_close( cfg->pin );
  58. dbg_platform_gpio_mode( PLATFORM_GPIO_INPUT, PLATFORM_GPIO_PULLUP );
  59. return TRUE;
  60. }
  61. static uint8_t drv_sd_play( cfg_t *cfg )
  62. {
  63. // VU control: derive callback frequency
  64. cfg->vu_req_samples = (uint16_t)((1000000L / (uint32_t)cfg->vu_freq) / (uint32_t)pcm_rate_def[cfg->rate]);
  65. cfg->vu_samples_tmp = 0;
  66. cfg->vu_peak_tmp = 0;
  67. // (re)start hardware timer ISR to feed the sigma-delta
  68. if (platform_hw_timer_init( drv_sd_hw_timer_owner, FRC1_SOURCE, TRUE )) {
  69. platform_hw_timer_set_func( drv_sd_hw_timer_owner, drv_sd_timer_isr, (os_param_t)cfg );
  70. platform_hw_timer_arm_us( drv_sd_hw_timer_owner, pcm_rate_def[cfg->rate] );
  71. return TRUE;
  72. } else {
  73. return FALSE;
  74. }
  75. }
  76. static uint8_t drv_sd_init( cfg_t *cfg )
  77. {
  78. dbg_platform_gpio_write( PLATFORM_GPIO_HIGH );
  79. dbg_platform_gpio_mode( PLATFORM_GPIO_OUTPUT, PLATFORM_GPIO_PULLUP );
  80. platform_sigma_delta_setup( cfg->pin );
  81. platform_sigma_delta_set_prescale( 9 );
  82. return TRUE;
  83. }
  84. static uint8_t drv_sd_fail( cfg_t *cfg )
  85. {
  86. return FALSE;
  87. }
  88. const drv_t pcm_drv_sd = {
  89. .init = drv_sd_init,
  90. .close = drv_sd_close,
  91. .play = drv_sd_play,
  92. .record = drv_sd_fail,
  93. .stop = drv_sd_stop
  94. };