From 6803fbcd9687775615febe0b6018d242964db58f Mon Sep 17 00:00:00 2001 From: Allan Skellett Date: Fri, 26 Jun 2026 14:02:55 +0100 Subject: [PATCH 01/12] Wait for data on the port that isn't 0 or 1, send 55 while waiting --- lib_mic_array/api/mic_array/cpp/PdmRx.hpp | 28 +++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/lib_mic_array/api/mic_array/cpp/PdmRx.hpp b/lib_mic_array/api/mic_array/cpp/PdmRx.hpp index a95ffdce..be7e6f48 100644 --- a/lib_mic_array/api/mic_array/cpp/PdmRx.hpp +++ b/lib_mic_array/api/mic_array/cpp/PdmRx.hpp @@ -473,6 +473,34 @@ void mic_array::StandardPdmRxService::SetPort(port_t template void mic_array::StandardPdmRxService::ThreadEntry() { + + uint32_t good_frames = 0; + while(1){ + // During boot, the PDM port may read all 0s or all 1s. + // Output 0x55 (zero) to the buffer until we get a valid frame. + uint32_t data = port_in(this->p_pdm_mics); + this->blocks[0][--phase] = 0x55555555; + + if(!phase){ + this->phase = this->num_phases; + uint32_t* ready_block = this->blocks[0]; + this->blocks[0] = this->blocks[1]; + this->blocks[1] = ready_block; + + s_chan_out_word(this->c_pdm_blocks.end_a, reinterpret_cast(ready_block)); + } + if (data == 0x00000000 || data == 0xFFFFFFFF) { + good_frames = 0; + continue; + } + good_frames++; + if (good_frames > 1) { + // Pin can toggle between 0 and 1, so we need to wait for a few good + // frames before we start using the data. + break; + } + } + while(1){ this->blocks[0][--phase] = port_in(this->p_pdm_mics); From 92454808a10ec39de915c5509f40c97b678b4299 Mon Sep 17 00:00:00 2001 From: Allan Skellett Date: Fri, 26 Jun 2026 15:50:01 +0100 Subject: [PATCH 02/12] add boot logic to python filter --- python/mic_array/filters.py | 41 +++++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/python/mic_array/filters.py b/python/mic_array/filters.py index 20f1f3cc..0b1de82e 100644 --- a/python/mic_array/filters.py +++ b/python/mic_array/filters.py @@ -78,6 +78,45 @@ def _pad_input(self, sig_in): S[:,P:] = sig_in return S + def boot_logic(self, pdm_signal: np.ndarray) -> np.ndarray: + # Simulate the PdmRx thread boot loop (StandardPdmRxService::ThreadEntry, + # PdmRx.hpp): words are received one at a time; 0x55555555 is written to + # the buffer (discarding real data) until good_frames > 1, i.e. 2 + # consecutive words that are neither all-0 (0x00000000) nor all-1 + # (0xFFFFFFFF). Bit layout: bit (c + CHANS*s) of word w = + # to_binary[c, w*spw+s], where to_binary(+1)=0, to_binary(-1)=1. + + CHANS, SAMPS_IN = pdm_signal.shape + BOOT_WORD = np.uint32(0x55555555) + spw = 32 // CHANS # PDM samples per channel packed per interleaved word + total_words = SAMPS_IN // spw + binary = ((1 - pdm_signal) // 2).astype(np.uint32) + + words = np.zeros(total_words, dtype=np.uint32) + for s in range(spw): + for c in range(CHANS): + words |= binary[c, s::spw][:total_words] << np.uint32(c + CHANS * s) + + good_frames = 0 + boot_words = 0 + for word in words: + boot_words += 1 + if word == np.uint32(0x00000000) or word == np.uint32(0xFFFFFFFF): + good_frames = 0 + else: + good_frames += 1 + if good_frames > 1: + break + + pdm_signal = pdm_signal.copy() + for w in range(boot_words): + for s in range(spw): + for c in range(CHANS): + bit = int((BOOT_WORD >> np.uint32(c + CHANS * s)) & np.uint32(1)) + pdm_signal[c, w * spw + s] = np.int32(-1 if bit else 1) + + return pdm_signal + def FilterInt16(self, pdm_signal: np.ndarray) -> np.ndarray: if pdm_signal.ndim == 1: pdm_signal = pdm_signal[np.newaxis,:] @@ -85,6 +124,8 @@ def FilterInt16(self, pdm_signal: np.ndarray) -> np.ndarray: Q = self.DecimationFactor N_pcm = SAMPS_IN // self.DecimationFactor + pdm_signal = self.boot_logic(pdm_signal) + S = self._pad_input(pdm_signal) coefs = self.Coef.astype(np.int32)[:,np.newaxis] res = np.empty((CHANS, N_pcm), dtype=np.int32) From 8b16777904084ec57acda2121449043dfb3ed21a Mon Sep 17 00:00:00 2001 From: Allan Skellett Date: Fri, 26 Jun 2026 16:26:51 +0100 Subject: [PATCH 03/12] bump jsl --- Jenkinsfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Jenkinsfile b/Jenkinsfile index f7075e8f..d8e58b9e 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -1,6 +1,6 @@ // This file relates to internal XMOS infrastructure and should be ignored by external users -@Library('xmos_jenkins_shared_library@v0.49.0') _ +@Library('xmos_jenkins_shared_library@v0.52.0') _ getApproval() pipeline { From f38b2afdb5a5ca658c36085a78b322d3e6a2dee0 Mon Sep 17 00:00:00 2001 From: Allan Skellett Date: Mon, 29 Jun 2026 09:26:51 +0100 Subject: [PATCH 04/12] more sane python boot logic --- python/mic_array/filters.py | 34 ++++++++-------------------------- 1 file changed, 8 insertions(+), 26 deletions(-) diff --git a/python/mic_array/filters.py b/python/mic_array/filters.py index 0b1de82e..952fb44b 100644 --- a/python/mic_array/filters.py +++ b/python/mic_array/filters.py @@ -82,41 +82,23 @@ def boot_logic(self, pdm_signal: np.ndarray) -> np.ndarray: # Simulate the PdmRx thread boot loop (StandardPdmRxService::ThreadEntry, # PdmRx.hpp): words are received one at a time; 0x55555555 is written to # the buffer (discarding real data) until good_frames > 1, i.e. 2 - # consecutive words that are neither all-0 (0x00000000) nor all-1 - # (0xFFFFFFFF). Bit layout: bit (c + CHANS*s) of word w = - # to_binary[c, w*spw+s], where to_binary(+1)=0, to_binary(-1)=1. + # consecutive words that are neither all-0 nor all-1 - CHANS, SAMPS_IN = pdm_signal.shape - BOOT_WORD = np.uint32(0x55555555) - spw = 32 // CHANS # PDM samples per channel packed per interleaved word - total_words = SAMPS_IN // spw - binary = ((1 - pdm_signal) // 2).astype(np.uint32) + good_frames = 0 - words = np.zeros(total_words, dtype=np.uint32) - for s in range(spw): - for c in range(CHANS): - words |= binary[c, s::spw][:total_words] << np.uint32(c + CHANS * s) + for start in range(0, pdm_signal.shape[1], 32): + pdm_signal[:,start:start+32] = np.tile([-1, 1], 16).T # write 0x55555555 to buffer - good_frames = 0 - boot_words = 0 - for word in words: - boot_words += 1 - if word == np.uint32(0x00000000) or word == np.uint32(0xFFFFFFFF): + if np.all(pdm_signal[:,start:start+32] == 1) or np.all(pdm_signal[:,start:start+32] == -1): good_frames = 0 - else: - good_frames += 1 + continue + good_frames += 1 if good_frames > 1: break - pdm_signal = pdm_signal.copy() - for w in range(boot_words): - for s in range(spw): - for c in range(CHANS): - bit = int((BOOT_WORD >> np.uint32(c + CHANS * s)) & np.uint32(1)) - pdm_signal[c, w * spw + s] = np.int32(-1 if bit else 1) - return pdm_signal + def FilterInt16(self, pdm_signal: np.ndarray) -> np.ndarray: if pdm_signal.ndim == 1: pdm_signal = pdm_signal[np.newaxis,:] From 1bf15acfd46ae19dd5ddd50c5d36ea748278d356 Mon Sep 17 00:00:00 2001 From: Allan Skellett Date: Mon, 29 Jun 2026 10:00:35 +0100 Subject: [PATCH 05/12] correct patterns for other mic counts --- lib_mic_array/api/mic_array/cpp/PdmRx.hpp | 12 +++++++++++- python/mic_array/filters.py | 7 +++++-- 2 files changed, 16 insertions(+), 3 deletions(-) diff --git a/lib_mic_array/api/mic_array/cpp/PdmRx.hpp b/lib_mic_array/api/mic_array/cpp/PdmRx.hpp index be7e6f48..83ba3200 100644 --- a/lib_mic_array/api/mic_array/cpp/PdmRx.hpp +++ b/lib_mic_array/api/mic_array/cpp/PdmRx.hpp @@ -474,12 +474,22 @@ template void mic_array::StandardPdmRxService::ThreadEntry() { + // The boot pattern is interleaved silence on each channel, so 0101.. for 1 mic + // 00110011 for 2 mics etc. After deinterleaving, each channel ends up with the + // 0x55555555 (0101..) silence pattern. The pre-deinterleave pattern is + // CHANNELS_IN zeros followed by CHANNELS_IN ones, repeated. + uint32_t boot_pattern = (CHANNELS_IN == 1) ? 0x55555555 : + (CHANNELS_IN == 2) ? 0x33333333 : + (CHANNELS_IN == 4) ? 0x0F0F0F0F : + (CHANNELS_IN == 8) ? 0x00FF00FF : + 0x0000FFFF; // 16 mics + uint32_t good_frames = 0; while(1){ // During boot, the PDM port may read all 0s or all 1s. // Output 0x55 (zero) to the buffer until we get a valid frame. uint32_t data = port_in(this->p_pdm_mics); - this->blocks[0][--phase] = 0x55555555; + this->blocks[0][--phase] = boot_pattern; if(!phase){ this->phase = this->num_phases; diff --git a/python/mic_array/filters.py b/python/mic_array/filters.py index 952fb44b..55f152c5 100644 --- a/python/mic_array/filters.py +++ b/python/mic_array/filters.py @@ -87,11 +87,14 @@ def boot_logic(self, pdm_signal: np.ndarray) -> np.ndarray: good_frames = 0 for start in range(0, pdm_signal.shape[1], 32): - pdm_signal[:,start:start+32] = np.tile([-1, 1], 16).T # write 0x55555555 to buffer - if np.all(pdm_signal[:,start:start+32] == 1) or np.all(pdm_signal[:,start:start+32] == -1): good_frames = 0 + pdm_signal[:,start:start+32] = np.tile([-1, 1], 16).T # write 0x55555555 to buffer continue + + # signal gets modified either way + pdm_signal[:,start:start+32] = np.tile([-1, 1], 16).T # write 0x55555555 to buffer + good_frames += 1 if good_frames > 1: break From 6a78128de35eab548ad7061460581e60c47ce72f Mon Sep 17 00:00:00 2001 From: Allan Skellett Date: Mon, 29 Jun 2026 15:09:31 +0100 Subject: [PATCH 06/12] xrun -l --- Jenkinsfile | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Jenkinsfile b/Jenkinsfile index d8e58b9e..bfc8e702 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -169,6 +169,8 @@ pipeline { // This ensures a project for XS2 can be built and runs OK sh "xsim test_xs2_benign/bin/xs2.xe" + sh "xrun -l" + // Run this first to ensure the XTAG is up and running for subsequent tests timeout(time: 2, unit: 'MINUTES') { sh "xrun --xscope --id 0 unit/bin/tests-unit.xe" From f89758d389568b96ae661da492e8fe23da30bc83 Mon Sep 17 00:00:00 2001 From: Allan Skellett Date: Mon, 29 Jun 2026 15:57:34 +0100 Subject: [PATCH 07/12] slightly faster --- lib_mic_array/api/mic_array/cpp/PdmRx.hpp | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/lib_mic_array/api/mic_array/cpp/PdmRx.hpp b/lib_mic_array/api/mic_array/cpp/PdmRx.hpp index 83ba3200..8408f2c7 100644 --- a/lib_mic_array/api/mic_array/cpp/PdmRx.hpp +++ b/lib_mic_array/api/mic_array/cpp/PdmRx.hpp @@ -499,14 +499,11 @@ void mic_array::StandardPdmRxService::ThreadEntry() s_chan_out_word(this->c_pdm_blocks.end_a, reinterpret_cast(ready_block)); } - if (data == 0x00000000 || data == 0xFFFFFFFF) { - good_frames = 0; - continue; - } - good_frames++; + // During boot the pin can toggle between all-0s and all-1s, so wait for a + // couple of consecutive valid frames before using the data + bool bad_frame = (data == 0x00000000) || (data == 0xFFFFFFFF); + good_frames = bad_frame ? 0 : (good_frames + 1); if (good_frames > 1) { - // Pin can toggle between 0 and 1, so we need to wait for a few good - // frames before we start using the data. break; } } From c173be53336782bb7c759f0204a057dc03d837ee Mon Sep 17 00:00:00 2001 From: Allan Skellett Date: Wed, 1 Jul 2026 15:08:59 +0100 Subject: [PATCH 08/12] experimental continous click detection --- lib_mic_array/api/mic_array/cpp/Decimator.hpp | 35 ++++++++++++++++++- 1 file changed, 34 insertions(+), 1 deletion(-) diff --git a/lib_mic_array/api/mic_array/cpp/Decimator.hpp b/lib_mic_array/api/mic_array/cpp/Decimator.hpp index 7e785113..46aeeb27 100644 --- a/lib_mic_array/api/mic_array/cpp/Decimator.hpp +++ b/lib_mic_array/api/mic_array/cpp/Decimator.hpp @@ -4,6 +4,7 @@ #pragma once #include +#include #include #include @@ -69,6 +70,14 @@ class Decimator * Per-mic, 32-bit PDM output words from the PDM RX stage. */ unsigned pdm_out_words_per_mic; + + /** + * Per-mic flag indicating whether the most recently processed PDM word + * was flagged as bad (excessive leading run of 0s or 1s). Used so that + * the word immediately following a bad word is also replaced, since it + * may itself be corrupted. + */ + bool pdm_word_was_bad[MIC_COUNT]; } stage1; public: @@ -197,8 +206,11 @@ void mic_array::Decimator this->stage1.pdm_out_words_per_mic = pdm_out_words_per_mic; memset(this->stage1.pdm_history_ptr, 0x55, sizeof(int32_t) * MIC_COUNT * this->stage1.pdm_history_sz); + memset(this->stage1.pdm_word_was_bad, 0, sizeof(this->stage1.pdm_word_was_bad)); if(decimator_conf.num_filter_stages >= 2) { + memset(decimator_conf.filter_conf[1].state, 0, sizeof(int32_t) * MIC_COUNT * decimator_conf.filter_conf[1].state_words_per_channel); + for(int k = 0; k < MIC_COUNT; k++){ filter_fir_s32_init(&this->stage2.filters[k], decimator_conf.filter_conf[1].state + (k * decimator_conf.filter_conf[1].state_words_per_channel), decimator_conf.filter_conf[1].num_taps, decimator_conf.filter_conf[1].coef, decimator_conf.filter_conf[1].shr); @@ -207,6 +219,8 @@ void mic_array::Decimator } if(decimator_conf.num_filter_stages == 3) { + memset(decimator_conf.filter_conf[2].state, 0, sizeof(int32_t) * MIC_COUNT * decimator_conf.filter_conf[2].state_words_per_channel); + for(int k = 0; k < MIC_COUNT; k++){ filter_fir_s32_init(&this->stage3.filters[k], decimator_conf.filter_conf[2].state + (k * decimator_conf.filter_conf[2].state_words_per_channel), decimator_conf.filter_conf[2].num_taps, decimator_conf.filter_conf[2].coef, decimator_conf.filter_conf[2].shr); @@ -224,9 +238,26 @@ void mic_array::Decimator { for(unsigned mic = 0; mic < MIC_COUNT; mic++){ uint32_t* hist = this->stage1.pdm_history_ptr + (mic * this->stage1.pdm_history_sz); + bool prev_word_bad = this->stage1.pdm_word_was_bad[mic]; for(unsigned k = 0; k < this->stage2.decimation_factor; k++){ - hist[0] = *(pdm_block + (mic*this->stage2.decimation_factor + k)); + uint32_t pdm_val = *(pdm_block + (mic*this->stage2.decimation_factor + k)); + + constexpr unsigned max_leading_run = 6; + unsigned leading_zeros = __builtin_clz(pdm_val); + unsigned leading_ones = __builtin_clz(~pdm_val); + unsigned max_leading_run_len = (leading_zeros > leading_ones) ? leading_zeros : leading_ones; + + bool this_word_bad = max_leading_run_len > max_leading_run; + + if(this_word_bad || prev_word_bad) { + pdm_val = 0x55555555; // write 0x55555555 to buffer + } + + prev_word_bad = this_word_bad; + + hist[0] = pdm_val; + int32_t streamA_sample = fir_1x16_bit(hist, this->stage1.filter_coef); shift_buffer(hist); @@ -236,6 +267,8 @@ void mic_array::Decimator sample_out[mic] = filter_fir_s32(&this->stage2.filters[mic], streamA_sample); } } + + this->stage1.pdm_word_was_bad[mic] = prev_word_bad; } } From 21e91261b1328dd7edfa83968d793367e9bc8fff Mon Sep 17 00:00:00 2001 From: Allan Skellett Date: Wed, 1 Jul 2026 15:34:50 +0100 Subject: [PATCH 09/12] temp run profile first --- Jenkinsfile | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Jenkinsfile b/Jenkinsfile index bfc8e702..2013be2b 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -175,7 +175,9 @@ pipeline { timeout(time: 2, unit: 'MINUTES') { sh "xrun --xscope --id 0 unit/bin/tests-unit.xe" } - + dir("signal/profile") { + sh "pytest -v" + } // note no xdist for HW tests as only 1 hw instance // Each test has it's own conftest.py so we need to run these seprarately dir("signal/pdmrx_isr") { @@ -204,9 +206,7 @@ pipeline { dir("signal/FilterDesign") { runPytest('-v') } - dir("signal/profile") { - sh "pytest -v" - } + } } archiveArtifacts artifacts: "**/*.pkl", allowEmptyArchive: true From 07d05f0c724190346608f93e63363949d850f94e Mon Sep 17 00:00:00 2001 From: Allan Skellett Date: Wed, 1 Jul 2026 16:34:43 +0100 Subject: [PATCH 10/12] use less regs --- lib_mic_array/api/mic_array/cpp/Decimator.hpp | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/lib_mic_array/api/mic_array/cpp/Decimator.hpp b/lib_mic_array/api/mic_array/cpp/Decimator.hpp index 46aeeb27..c94a335f 100644 --- a/lib_mic_array/api/mic_array/cpp/Decimator.hpp +++ b/lib_mic_array/api/mic_array/cpp/Decimator.hpp @@ -241,23 +241,22 @@ void mic_array::Decimator bool prev_word_bad = this->stage1.pdm_word_was_bad[mic]; for(unsigned k = 0; k < this->stage2.decimation_factor; k++){ - uint32_t pdm_val = *(pdm_block + (mic*this->stage2.decimation_factor + k)); + hist[0] = *(pdm_block + (mic*this->stage2.decimation_factor + k)); - constexpr unsigned max_leading_run = 6; - unsigned leading_zeros = __builtin_clz(pdm_val); - unsigned leading_ones = __builtin_clz(~pdm_val); + constexpr unsigned max_leading_run = 3; + unsigned leading_zeros = __builtin_clz(hist[0]); + unsigned leading_ones = __builtin_clz(~hist[0]); unsigned max_leading_run_len = (leading_zeros > leading_ones) ? leading_zeros : leading_ones; bool this_word_bad = max_leading_run_len > max_leading_run; + if(this_word_bad || prev_word_bad) { - pdm_val = 0x55555555; // write 0x55555555 to buffer + hist[0] = 0x55555555; // write 0x55555555 to buffer } prev_word_bad = this_word_bad; - hist[0] = pdm_val; - int32_t streamA_sample = fir_1x16_bit(hist, this->stage1.filter_coef); shift_buffer(hist); From 8fd2f3a732f9a5d6da0762fadb98a5c44731d1cc Mon Sep 17 00:00:00 2001 From: Allan Skellett Date: Wed, 1 Jul 2026 16:55:50 +0100 Subject: [PATCH 11/12] faster --- lib_mic_array/api/mic_array/cpp/Decimator.hpp | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/lib_mic_array/api/mic_array/cpp/Decimator.hpp b/lib_mic_array/api/mic_array/cpp/Decimator.hpp index c94a335f..68e04713 100644 --- a/lib_mic_array/api/mic_array/cpp/Decimator.hpp +++ b/lib_mic_array/api/mic_array/cpp/Decimator.hpp @@ -244,9 +244,13 @@ void mic_array::Decimator hist[0] = *(pdm_block + (mic*this->stage2.decimation_factor + k)); constexpr unsigned max_leading_run = 3; - unsigned leading_zeros = __builtin_clz(hist[0]); - unsigned leading_ones = __builtin_clz(~hist[0]); - unsigned max_leading_run_len = (leading_zeros > leading_ones) ? leading_zeros : leading_ones; + // leading_zeros and leading_ones are mutually exclusive (only one can + // be non-zero for a given word), so XOR the word with its own sign + // mask (0x00000000 or 0xFFFFFFFF) to fold whichever run it has down + // to a leading-zero run, then use a single clz (a single-cycle + // instruction on XS3A) instead of two clz calls plus a max(). + uint32_t sign_mask = (uint32_t)((int32_t)hist[0] >> 31); + unsigned max_leading_run_len = __builtin_clz(hist[0] ^ sign_mask); bool this_word_bad = max_leading_run_len > max_leading_run; From 5bc172d1a4c62419fa99dec8d72fa04c5fa35c01 Mon Sep 17 00:00:00 2001 From: Allan Skellett Date: Wed, 1 Jul 2026 17:04:54 +0100 Subject: [PATCH 12/12] no boot logic --- lib_mic_array/api/mic_array/cpp/PdmRx.hpp | 66 +++++++++++------------ 1 file changed, 33 insertions(+), 33 deletions(-) diff --git a/lib_mic_array/api/mic_array/cpp/PdmRx.hpp b/lib_mic_array/api/mic_array/cpp/PdmRx.hpp index 8408f2c7..ea51186f 100644 --- a/lib_mic_array/api/mic_array/cpp/PdmRx.hpp +++ b/lib_mic_array/api/mic_array/cpp/PdmRx.hpp @@ -474,39 +474,39 @@ template void mic_array::StandardPdmRxService::ThreadEntry() { - // The boot pattern is interleaved silence on each channel, so 0101.. for 1 mic - // 00110011 for 2 mics etc. After deinterleaving, each channel ends up with the - // 0x55555555 (0101..) silence pattern. The pre-deinterleave pattern is - // CHANNELS_IN zeros followed by CHANNELS_IN ones, repeated. - uint32_t boot_pattern = (CHANNELS_IN == 1) ? 0x55555555 : - (CHANNELS_IN == 2) ? 0x33333333 : - (CHANNELS_IN == 4) ? 0x0F0F0F0F : - (CHANNELS_IN == 8) ? 0x00FF00FF : - 0x0000FFFF; // 16 mics - - uint32_t good_frames = 0; - while(1){ - // During boot, the PDM port may read all 0s or all 1s. - // Output 0x55 (zero) to the buffer until we get a valid frame. - uint32_t data = port_in(this->p_pdm_mics); - this->blocks[0][--phase] = boot_pattern; - - if(!phase){ - this->phase = this->num_phases; - uint32_t* ready_block = this->blocks[0]; - this->blocks[0] = this->blocks[1]; - this->blocks[1] = ready_block; - - s_chan_out_word(this->c_pdm_blocks.end_a, reinterpret_cast(ready_block)); - } - // During boot the pin can toggle between all-0s and all-1s, so wait for a - // couple of consecutive valid frames before using the data - bool bad_frame = (data == 0x00000000) || (data == 0xFFFFFFFF); - good_frames = bad_frame ? 0 : (good_frames + 1); - if (good_frames > 1) { - break; - } - } + // // The boot pattern is interleaved silence on each channel, so 0101.. for 1 mic + // // 00110011 for 2 mics etc. After deinterleaving, each channel ends up with the + // // 0x55555555 (0101..) silence pattern. The pre-deinterleave pattern is + // // CHANNELS_IN zeros followed by CHANNELS_IN ones, repeated. + // uint32_t boot_pattern = (CHANNELS_IN == 1) ? 0x55555555 : + // (CHANNELS_IN == 2) ? 0x33333333 : + // (CHANNELS_IN == 4) ? 0x0F0F0F0F : + // (CHANNELS_IN == 8) ? 0x00FF00FF : + // 0x0000FFFF; // 16 mics + + // uint32_t good_frames = 0; + // while(1){ + // // During boot, the PDM port may read all 0s or all 1s. + // // Output 0x55 (zero) to the buffer until we get a valid frame. + // uint32_t data = port_in(this->p_pdm_mics); + // this->blocks[0][--phase] = boot_pattern; + + // if(!phase){ + // this->phase = this->num_phases; + // uint32_t* ready_block = this->blocks[0]; + // this->blocks[0] = this->blocks[1]; + // this->blocks[1] = ready_block; + + // s_chan_out_word(this->c_pdm_blocks.end_a, reinterpret_cast(ready_block)); + // } + // // During boot the pin can toggle between all-0s and all-1s, so wait for a + // // couple of consecutive valid frames before using the data + // bool bad_frame = (data == 0x00000000) || (data == 0xFFFFFFFF); + // good_frames = bad_frame ? 0 : (good_frames + 1); + // if (good_frames > 1) { + // break; + // } + // } while(1){ this->blocks[0][--phase] = port_in(this->p_pdm_mics);