#ifdef __RAND_FROM_MIC__ #include "randfrommic.h" #include "app_audio.h" #include "app_bt_stream.h" #include "app_utils.h" #include "audioflinger.h" #include "cmsis_gcc.h" #include "cmsis_os.h" #include "hal_timer.h" #include "hal_trace.h" #include "stdio.h" #include "stdlib.h" #include "string.h" #if BT_DRV_DEBUG #define RAND_TRACE(n, fmt, ...) TRACE(n, fmt, ##__VA_ARGS__) #define RAND_DUMP(s, buff, len) DUMP8(s, buff, len) #else #define RAND_TRACE(n, fmt, ...) #define RAND_DUMP(s, buff, len) #endif static void generateRand(bool on); static uint32_t rand_data_handle(uint8_t *buf, uint32_t len); static uint8_t deviceId = 0; static uint8_t *captureBuffer = NULL; static uint32_t randSeed = 1; static bool randInitialised = false; // 4 bytes aligned #define RAND_GRAB_BITS_PER_SAMPLE 4 #define RAND_GRAB_BITS_MASK_PER_SAMPLE ((1 << RAND_GRAB_BITS_PER_SAMPLE) - 1) RAND_NUMBER_T randomBuffer = { 25, RAND_STATUS_CLOSE, }; /** * Description: parse mic data according to the stream cfg(bit mode and channel * number) only the lowest byte of each frame is taken ADC format: 16bit mode -> * [15:0] is valid 24bit mode -> [23:4] is valid 32bit mode -> [31:12] is valid * */ static int randDataParse(uint8_t *buf, uint32_t len, enum AUD_BITS_T bits, enum AUD_CHANNEL_NUM_T ch_num) { uint8_t index = 0; union { uint32_t seedValue; uint8_t value[4]; } seedData; if ((NULL == buf) || ((RANDOM_CAPTURE_BUFFER_SIZE / 2) > len)) // ping-pong buffer { return -1; } RAND_TRACE(1, "%s", __func__); RAND_DUMP("%x ", buf, 16); switch (bits) { case AUD_BITS_16: { uint16_t *content = (uint16_t *)buf; for (index = 0; index < 4; index++) { seedData.value[index] = ((*content) & RAND_GRAB_BITS_MASK_PER_SAMPLE) | (((*(content + ch_num)) & RAND_GRAB_BITS_MASK_PER_SAMPLE) << RAND_GRAB_BITS_PER_SAMPLE); content += ((8 / RAND_GRAB_BITS_PER_SAMPLE) * ch_num); } break; } case AUD_BITS_24: { uint32_t *content = (uint32_t *)buf; for (index = 0; index < 4; index++) { // bit 23:4 are valid seedData.value[index] = (((*content) >> 4) & RAND_GRAB_BITS_MASK_PER_SAMPLE) | ((((*(content + ch_num)) >> 4) & RAND_GRAB_BITS_MASK_PER_SAMPLE) << RAND_GRAB_BITS_PER_SAMPLE); content += ((8 / RAND_GRAB_BITS_PER_SAMPLE) * ch_num); } break; } case AUD_BITS_32: { uint32_t *content = (uint32_t *)buf; for (index = 0; index < 4; index++) { // bit 31:12 are valid seedData.value[index] = (((*content) >> 12) & RAND_GRAB_BITS_MASK_PER_SAMPLE) | ((((*(content + ch_num)) >> 12) & RAND_GRAB_BITS_MASK_PER_SAMPLE) << RAND_GRAB_BITS_PER_SAMPLE); content += ((8 / RAND_GRAB_BITS_PER_SAMPLE) * ch_num); } break; } default: { return -1; } break; } randSeed = seedData.seedValue; return 0; } static void generateRand(bool on) { struct AF_STREAM_CONFIG_T stream_cfg; RAND_TRACE(2, "%s op:%d", __func__, on); if (on) { randomBuffer.skipRound = 10; randomBuffer.status = random_mic_is_on(&deviceId); RAND_TRACE(2, "%s random status = %d", __func__, randomBuffer.status); if (RAND_STATUS_CLOSE == randomBuffer.status) { app_sysfreq_req(APP_SYSFREQ_USER_RANDOM, APP_SYSFREQ_208M); app_capture_audio_mempool_init(); app_capture_audio_mempool_get_buff(&captureBuffer, RANDOM_CAPTURE_BUFFER_SIZE); memset(&stream_cfg, 0, sizeof(stream_cfg)); stream_cfg.bits = AUD_BITS_16; stream_cfg.channel_num = AUD_CHANNEL_NUM_1; stream_cfg.device = AUD_STREAM_USE_INT_CODEC; stream_cfg.sample_rate = AUD_SAMPRATE_8000; stream_cfg.vol = TGT_VOLUME_LEVEL_15; stream_cfg.io_path = AUD_INPUT_PATH_MAINMIC; stream_cfg.handler = rand_data_handle; stream_cfg.data_ptr = BT_AUDIO_CACHE_2_UNCACHE(captureBuffer); stream_cfg.data_size = RANDOM_CAPTURE_BUFFER_SIZE; af_stream_open(AUD_STREAM_ID_0, AUD_STREAM_CAPTURE, &stream_cfg); af_stream_start(AUD_STREAM_ID_0, AUD_STREAM_CAPTURE); randomBuffer.status = RAND_STATUS_OPEN; } else if (RAND_STATUS_MIC_OPENED == randomBuffer.status) { af_stream_start(deviceId, AUD_STREAM_CAPTURE); } } else { // release the acquired system clock app_sysfreq_req(APP_SYSFREQ_USER_RANDOM, APP_SYSFREQ_32K); if (RAND_STATUS_MIC_OPENED == randomBuffer.status) { af_stream_stop(deviceId, AUD_STREAM_CAPTURE); } else if (RAND_STATUS_OPEN == randomBuffer.status) { af_stream_stop(AUD_STREAM_ID_0, AUD_STREAM_CAPTURE); af_stream_close(AUD_STREAM_ID_0, AUD_STREAM_CAPTURE); } randomBuffer.status = RAND_STATUS_CLOSE; } } static uint32_t rand_data_handle(uint8_t *buf, uint32_t len) { if (buf == NULL) { return len; } if ((1 == randomBuffer.skipRound) && (!randDataParse(buf, len, AUD_BITS_16, AUD_CHANNEL_NUM_1))) { generateRand(false); randomBuffer.skipRound = 0; } else if (1 != randomBuffer.skipRound) { randomBuffer.skipRound--; } return len; } void initSeed(void) { uint8_t count = 100; // avoid deed loop RAND_TRACE(2, "%s:+++ initialised = %d", __func__, randInitialised); if (randInitialised) { generateRand(true); while ((0 != randomBuffer.skipRound) && (0 != count)) { osDelay(10); count--; } } if ((0 == count) || (false == randInitialised)) { RAND_TRACE(1, "%s not ready", __func__); randSeed = (uint32_t)hal_sys_timer_get(); generateRand(false); } srand(randSeed); RAND_TRACE(2, "%s:--- count = %d", __func__, count); } void random_status_sync(void) { if (RAND_STATUS_OPEN == randomBuffer.status) { RAND_TRACE(1, "%s random mic has already on,should be closed", __func__); generateRand(false); } } void random_data_process(uint8_t *buf, uint32_t len, enum AUD_BITS_T bits, enum AUD_CHANNEL_NUM_T ch_num) { if (buf == NULL) { return; } if ((RAND_STATUS_MIC_STARTED == randomBuffer.status) || (RAND_STATUS_MIC_OPENED == randomBuffer.status)) { if (len >= RANDOM_CAPTURE_BUFFER_SIZE / 2) { RAND_TRACE(4, "%s buf address = 0x%p, bits = %d, channel num = %d", __func__, buf, bits, ch_num); RAND_DUMP("%02x ", buf, 32); if ((1 == randomBuffer.skipRound) && (!randDataParse(buf, len, bits, ch_num))) { generateRand(false); randomBuffer.skipRound = 0; } else if (1 != randomBuffer.skipRound) { randomBuffer.skipRound--; } } } } void randInit(void) { randInitialised = true; } #endif