\r
/* Private typedef -----------------------------------------------------------*/\r
/* USER CODE BEGIN PTD */\r
-typedef struct {\r
- int32_t value : 18;\r
-} sample_t;\r
+typedef uint32_t sample_t;\r
/* USER CODE END PTD */\r
\r
/* Private define ------------------------------------------------------------*/\r
/* USER CODE BEGIN PD */\r
-#define SAMPLE_COUNT (256) // Sample count per half-transfer\r
+#define SAMPLE_COUNT (256) // (Stereo!) Sample count per half-transfer\r
#define SAMPLES_PER_REPORT (48000) // Report every second given our 48 kHz rate\r
#define MIC_OFFSET_DB ( 0.f) // Linear offset\r
#define MIC_SENSITIVITY (-26.f) // dBFS value expected at MIC_REF_DB\r
#define MIC_REF_DB ( 94.f) // dB where sensitivity is specified\r
-#define MIC_BITS (18)\r
+#define MIC_BITS (18u)\r
/* USER CODE END PD */\r
\r
/* Private macro -------------------------------------------------------------*/\r
\r
/* USER CODE BEGIN 1 */\r
ln10 = qfp_fln(10.f);\r
- MIC_REF_AMPL = qfp_fmul(qfp_int2float((1 << (MIC_BITS - 1)) - 1),\r
+ MIC_REF_AMPL = qfp_fmul(qfp_int2float((1u << (MIC_BITS - 1)) - 1),\r
qfp_fpow(10.f, MIC_SENSITIVITY / 20.f));\r
/* USER CODE END 1 */\r
\r
return errorcode;\r
}\r
\r
-void SPI_DMATransmitReceiveCplt(DMA_HandleTypeDef *hdma)\r
-{\r
- SPI_HandleTypeDef *hspi = (SPI_HandleTypeDef *)hdma->Parent;\r
- (void)hspi;\r
-}\r
-\r
-static float process(float in_div4)\r
+static inline float process(float in_div4)\r
{\r
- static float z1 = 0, z2 = 0, z3 = 0, z5 = 0;\r
+ static float z[4] = {0.f, 0.f, 0.f, 0.f};\r
\r
- float out1 = qfp_fadd(in_div4, z1);\r
- z1 = qfp_fadd(qfp_fmul(1.062f, out1), z2);\r
- z2 = qfp_fsub(qfp_fmul(-0.14f, out1), in_div4);\r
+ float out1 = qfp_fadd(in_div4, z[0]);\r
+ z[0] = qfp_fadd(qfp_fmul(out1, 1.062f), z[1]);\r
+ z[1] = qfp_fsub(qfp_fmul(out1, -0.14f), in_div4);\r
\r
- float out2 = qfp_fadd(out1, z3);\r
- z3 = out1;\r
+ float out2 = qfp_fadd(out1, z[2]);\r
+ z[2] = out1;\r
\r
- float out3 = qfp_fadd(out2, z5);\r
- z5 = qfp_fsub(qfp_fmul(0.985f, out3), out2);\r
+ float out3 = qfp_fadd(out2, z[3]);\r
+ z[3] = qfp_fsub(qfp_fmul(out3, 0.985f), out2);\r
\r
return out3;\r
}\r
\r
-void SPI_DMAHalfTransmitReceiveCplt(DMA_HandleTypeDef *hdma)\r
+static void processSampleBlock(sample_t *sample)\r
{\r
HAL_GPIO_WritePin(IDLE_GPIO_Port, IDLE_Pin, GPIO_PIN_RESET);\r
\r
- SPI_HandleTypeDef *hspi = (SPI_HandleTypeDef *)hdma->Parent;\r
- (void)hspi;\r
+ // SAMPLE_COUNT is number of samples in this block\r
+ // Divide by 2 for left channel only\r
+ // Divide by 8 for stride to reduce compute time\r
+#define STRIDE (2 * 8)\r
+\r
+ for (int i = 0; i < SAMPLE_COUNT; i += STRIDE) {\r
+ // 18-bit sample comes in as big-endian with right padding.\r
+ // 1. Convert to little-endian:\r
+ int samp;\r
+ asm("rev %0, %1" : "=r" (samp) : "r" (sample[i]));\r
+ // 2. Arithmetic shift right to remove padding, +2 to make "in_div4"\r
+ float f = process(qfp_int2float(samp >> (32 - MIC_BITS + 2)));\r
\r
- sample_t *sample = (sample_t *)I2S_Receive_Buffer;\r
- for (int i = 0; i < SAMPLE_COUNT / 8; i++) {\r
- float f = process(qfp_int2float(sample[i].value / 4));\r
- DB_Sum_Squares = qfp_fadd(DB_Sum_Squares, qfp_fmul(f, f));\r
+ DB_Sum_Squares = qfp_fadd(qfp_fmul(f, f), DB_Sum_Squares);\r
}\r
- DB_Count += SAMPLE_COUNT * 2; // Pretend we sampled the entire I2S buffer\r
+ DB_Count += SAMPLE_COUNT / STRIDE;\r
\r
- if (DB_Count > SAMPLES_PER_REPORT) {\r
+ if (DB_Count >= SAMPLES_PER_REPORT / STRIDE * 2) {\r
float rms = qfp_fsqrt(qfp_fdiv(DB_Sum_Squares, qfp_uint2float(DB_Count)));\r
- float db = qfp_fadd(MIC_OFFSET_DB + MIC_REF_DB, qfp_fmul(20.f,\r
- qfp_flog10(qfp_fdiv(rms, MIC_REF_AMPL))));\r
+ float db = qfp_fadd(qfp_fmul(qfp_flog10(qfp_fdiv(rms, MIC_REF_AMPL)), 20.f),\r
+ MIC_OFFSET_DB + MIC_REF_DB);\r
DB_Sum_Squares = 0.f;\r
DB_Count = 0;\r
\r
printf("%d dB\r\n", qfp_float2int(db));\r
}\r
}\r
+\r
+void SPI_DMATransmitReceiveCplt(DMA_HandleTypeDef *hdma)\r
+{\r
+ processSampleBlock((sample_t *)I2S_Receive_Buffer + SAMPLE_COUNT);\r
+}\r
+\r
+void SPI_DMAHalfTransmitReceiveCplt(DMA_HandleTypeDef *hdma)\r
+{\r
+ processSampleBlock((sample_t *)I2S_Receive_Buffer);\r
+}\r
/* USER CODE END 4 */\r
\r
/**\r