From 28f0f617f8f55ecdb10cbca52409b32de584312d Mon Sep 17 00:00:00 2001 From: Michal Moskal Date: Thu, 29 Oct 2020 16:34:00 +0100 Subject: [PATCH 1/6] Move microphone init here from codal --- libs/microphone/microphonehw.cpp | 41 +++++++++----------------------- 1 file changed, 11 insertions(+), 30 deletions(-) diff --git a/libs/microphone/microphonehw.cpp b/libs/microphone/microphonehw.cpp index 5d0a9cdd434..e5220f25cb7 100644 --- a/libs/microphone/microphonehw.cpp +++ b/libs/microphone/microphonehw.cpp @@ -4,46 +4,27 @@ #include "pxt.h" #if MICROBIT_CODAL + #include "LevelDetector.h" #include "LevelDetectorSPL.h" #include "DataStream.h" -#ifndef MIC_DEVICE -// STM? -class DummyDataSource : public codal::DataSource { - public: - DummyDataSource() {} -}; -class PanicPDM { - public: - uint8_t level; - DummyDataSource source; - codal::DataStream output; - - PanicPDM(Pin &sd, Pin &sck) : output(source) { target_panic(PANIC_MICROPHONE_MISSING); } - void enable() {} - void disable() {} -}; -#define MIC_DEVICE PanicPDM -#endif - -#ifndef MIC_INIT -#define MIC_INIT \ - : microphone(*LOOKUP_PIN(MIC_DATA), *LOOKUP_PIN(MIC_CLOCK)) \ - , level(microphone.output, 95.0, 75.0, 9, 52, DEVICE_ID_MICROPHONE) -#endif - -#ifndef MIC_ENABLE -#define MIC_ENABLE microphone.enable() -#endif namespace pxt { class WMicrophone { public: - MIC_DEVICE microphone; + NRF52ADCChannel *microphone; + StreamNormalizer normalizer; LevelDetectorSPL level; - WMicrophone() MIC_INIT { MIC_ENABLE; } + WMicrophone() + : microphone(uBit.adc.getChannel(uBit.io.microphone)), + normalizer(microphone->output, 1.0f, true, DATASTREAM_FORMAT_UNKNOWN, 10), + level(normalizer.output, 75.0, 60.0, 9, 52, DEVICE_ID_MICROPHONE) { + uBit.io.runmic.setDigitalValue(1); + uBit.io.runmic.setHighDrive(true); + microphone->setGain(7, 0); + } }; SINGLETON(WMicrophone); From f2761982ee3f9fc23fafd67e0ddb625c39bfbfce Mon Sep 17 00:00:00 2001 From: Michal Moskal Date: Thu, 29 Oct 2020 17:34:44 +0100 Subject: [PATCH 2/6] Add input.onSoundData() --- libs/microphone/micbuffer.ts | 19 +++++++++ libs/microphone/microphonehw.cpp | 67 ++++++++++++++++++++++++++++++-- libs/microphone/pxt.json | 11 +++++- 3 files changed, 93 insertions(+), 4 deletions(-) create mode 100644 libs/microphone/micbuffer.ts diff --git a/libs/microphone/micbuffer.ts b/libs/microphone/micbuffer.ts new file mode 100644 index 00000000000..65166d6ddff --- /dev/null +++ b/libs/microphone/micbuffer.ts @@ -0,0 +1,19 @@ +namespace input { + //% shim=microphone::_readyEvent + function _readyEvent(): number { + return 0xffff + } + + //% shim=microphone::_pull + function _pull(): Buffer { + return null + } + + export function onSoundData(cb: (data: Buffer) => void) { + control.internalOnEvent(DAL.DEVICE_ID_NOTIFY, _readyEvent(), () => { + const buf = _pull() + if (buf) + cb(buf) + }) + } +} \ No newline at end of file diff --git a/libs/microphone/microphonehw.cpp b/libs/microphone/microphonehw.cpp index e5220f25cb7..56d4d34a5e5 100644 --- a/libs/microphone/microphonehw.cpp +++ b/libs/microphone/microphonehw.cpp @@ -9,21 +9,57 @@ #include "LevelDetectorSPL.h" #include "DataStream.h" - namespace pxt { +class TeeStream : public DataSink, public DataSource { + public: + int evid; + DataSource &upstream; + DataStream output; + ManagedBuffer buffer; + bool pxtPending; + + TeeStream(int evid, DataSource &src) : evid(evid), upstream(src), output(*this) { + pxtPending = false; + output.setBlocking(false); + upstream.connect(*this); + } + + Buffer pxtBuffer() { + if (!pxtPending) + return nullptr; + pxtPending = false; + return mkBuffer(buffer.getBytes(), buffer.length()); + } + + virtual ManagedBuffer pull() override { return buffer; } + virtual int getFormat() override { return upstream.getFormat(); } + virtual int setFormat(int format) override { return upstream.setFormat(format); } + + virtual int pullRequest() override { + buffer = upstream.pull(); + pxtPending = buffer.length() > 0; + output.pullRequest(); + Event(DEVICE_ID_NOTIFY, evid); + return DEVICE_OK; + } +}; + class WMicrophone { public: NRF52ADCChannel *microphone; StreamNormalizer normalizer; + TeeStream tee; LevelDetectorSPL level; WMicrophone() : microphone(uBit.adc.getChannel(uBit.io.microphone)), normalizer(microphone->output, 1.0f, true, DATASTREAM_FORMAT_UNKNOWN, 10), - level(normalizer.output, 75.0, 60.0, 9, 52, DEVICE_ID_MICROPHONE) { + tee(allocateNotifyEvent(), normalizer.output), + level(tee.output, 75.0, 60.0, 9, 52, DEVICE_ID_MICROPHONE) { uBit.io.runmic.setDigitalValue(1); uBit.io.runmic.setHighDrive(true); microphone->setGain(7, 0); + DMESG("microphone: %d Hz", 1000000 / uBit.adc.getSamplePeriod()); } }; SINGLETON(WMicrophone); @@ -34,4 +70,29 @@ codal::LevelDetectorSPL *getMicrophoneLevel() { } } // namespace pxt -#endif \ No newline at end of file + +#endif + +namespace microphone { + +//% +int _readyEvent() { +#if MICROBIT_CODAL + return getWMicrophone()->tee.evid; +#else + target_panic(PANIC_VARIANT_NOT_SUPPORTED); + return 0; +#endif +} + +//% +Buffer _pull() { +#if MICROBIT_CODAL + return getWMicrophone()->tee.pxtBuffer(); +#else + target_panic(PANIC_VARIANT_NOT_SUPPORTED); + return nullptr; +#endif +} + +} // namespace microphone diff --git a/libs/microphone/pxt.json b/libs/microphone/pxt.json index abfae4823a5..ace0677311c 100644 --- a/libs/microphone/pxt.json +++ b/libs/microphone/pxt.json @@ -1,6 +1,15 @@ { "additionalFilePath": "../../node_modules/pxt-common-packages/libs/microphone", + "files": [ + "README.md", + "microphone.cpp", + "microphonehw.cpp", + "micbuffer.ts", + "enums.d.ts", + "shims.d.ts", + "targetoverrides.ts" + ], "dependencies": { "core": "file:../core" } -} +} \ No newline at end of file From 71638cd850259a07a0d3300df46fc2d909da856b Mon Sep 17 00:00:00 2001 From: Michal Moskal Date: Thu, 29 Oct 2020 17:41:32 +0100 Subject: [PATCH 3/6] Add input.soundSamplingPeriod() --- libs/microphone/micbuffer.ts | 2 +- libs/microphone/microphonehw.cpp | 13 +++++++++++++ libs/microphone/shims.d.ts | 8 ++++++++ 3 files changed, 22 insertions(+), 1 deletion(-) diff --git a/libs/microphone/micbuffer.ts b/libs/microphone/micbuffer.ts index 65166d6ddff..47d27eca3a9 100644 --- a/libs/microphone/micbuffer.ts +++ b/libs/microphone/micbuffer.ts @@ -10,7 +10,7 @@ namespace input { } export function onSoundData(cb: (data: Buffer) => void) { - control.internalOnEvent(DAL.DEVICE_ID_NOTIFY, _readyEvent(), () => { + control.onEvent(DAL.DEVICE_ID_NOTIFY, _readyEvent(), () => { const buf = _pull() if (buf) cb(buf) diff --git a/libs/microphone/microphonehw.cpp b/libs/microphone/microphonehw.cpp index 56d4d34a5e5..e339e6f1f59 100644 --- a/libs/microphone/microphonehw.cpp +++ b/libs/microphone/microphonehw.cpp @@ -95,4 +95,17 @@ Buffer _pull() { #endif } +/** + * Return microphone sampling period in microseconds. + */ +//% +int soundSamplingPeriod() { +#if MICROBIT_CODAL + return uBit.adc.getSamplePeriod(); +#else + target_panic(PANIC_VARIANT_NOT_SUPPORTED); + return 0; +#endif +} + } // namespace microphone diff --git a/libs/microphone/shims.d.ts b/libs/microphone/shims.d.ts index d189372914e..5e9d9c57570 100644 --- a/libs/microphone/shims.d.ts +++ b/libs/microphone/shims.d.ts @@ -33,5 +33,13 @@ declare namespace input { //% group="micro:bit v2" threshold.defl=128 shim=input::setSoundThreshold function setSoundThreshold(sound: SoundThreshold, threshold?: int32): void; } +declare namespace microphone { + + /** + * Return microphone sampling period in microseconds. + */ + //% shim=microphone::soundSamplingPeriod + function soundSamplingPeriod(): int32; +} // Auto-generated. Do not edit. Really. From ba6540c9d9aa1a29062e088281a8561035374f95 Mon Sep 17 00:00:00 2001 From: Michal Moskal Date: Thu, 29 Oct 2020 18:04:48 +0100 Subject: [PATCH 4/6] Add input.setSoundSamplingPeriod() --- libs/microphone/microphonehw.cpp | 18 +++++++++++++++++- libs/microphone/shims.d.ts | 10 ++++++++-- 2 files changed, 25 insertions(+), 3 deletions(-) diff --git a/libs/microphone/microphonehw.cpp b/libs/microphone/microphonehw.cpp index e339e6f1f59..aadae4b6eb0 100644 --- a/libs/microphone/microphonehw.cpp +++ b/libs/microphone/microphonehw.cpp @@ -95,6 +95,10 @@ Buffer _pull() { #endif } +} // namespace microphone + +namespace input { + /** * Return microphone sampling period in microseconds. */ @@ -108,4 +112,16 @@ int soundSamplingPeriod() { #endif } -} // namespace microphone +/** + * Set microphone sampling period in microseconds. Typical range 20-200. + */ +//% +void setSoundSamplingPeriod(int us) { +#if MICROBIT_CODAL + uBit.adc.setSamplePeriod(us); +#else + target_panic(PANIC_VARIANT_NOT_SUPPORTED); +#endif +} + +} // namespace input diff --git a/libs/microphone/shims.d.ts b/libs/microphone/shims.d.ts index 5e9d9c57570..038d746770e 100644 --- a/libs/microphone/shims.d.ts +++ b/libs/microphone/shims.d.ts @@ -33,13 +33,19 @@ declare namespace input { //% group="micro:bit v2" threshold.defl=128 shim=input::setSoundThreshold function setSoundThreshold(sound: SoundThreshold, threshold?: int32): void; } -declare namespace microphone { +declare namespace input { /** * Return microphone sampling period in microseconds. */ - //% shim=microphone::soundSamplingPeriod + //% shim=input::soundSamplingPeriod function soundSamplingPeriod(): int32; + + /** + * Set microphone sampling period in microseconds. Typical range 20-200. + */ + //% shim=input::setSoundSamplingPeriod + function setSoundSamplingPeriod(us: int32): void; } // Auto-generated. Do not edit. Really. From 72e943e924e36afb8c7c32be9a4348b668b161d3 Mon Sep 17 00:00:00 2001 From: Michal Moskal Date: Mon, 2 Nov 2020 11:47:58 +0100 Subject: [PATCH 5/6] Add (beta) markings on mic functions --- libs/microphone/micbuffer.ts | 3 +++ libs/microphone/microphonehw.cpp | 4 ++-- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/libs/microphone/micbuffer.ts b/libs/microphone/micbuffer.ts index 47d27eca3a9..8a14403133a 100644 --- a/libs/microphone/micbuffer.ts +++ b/libs/microphone/micbuffer.ts @@ -9,6 +9,9 @@ namespace input { return null } + /** + * (beta) Run callback whenever new raw data from microphone is available. + */ export function onSoundData(cb: (data: Buffer) => void) { control.onEvent(DAL.DEVICE_ID_NOTIFY, _readyEvent(), () => { const buf = _pull() diff --git a/libs/microphone/microphonehw.cpp b/libs/microphone/microphonehw.cpp index aadae4b6eb0..cefb99f6b22 100644 --- a/libs/microphone/microphonehw.cpp +++ b/libs/microphone/microphonehw.cpp @@ -100,7 +100,7 @@ Buffer _pull() { namespace input { /** - * Return microphone sampling period in microseconds. + * (beta) Return microphone sampling period in microseconds. */ //% int soundSamplingPeriod() { @@ -113,7 +113,7 @@ int soundSamplingPeriod() { } /** - * Set microphone sampling period in microseconds. Typical range 20-200. + * (beta) Set microphone sampling period in microseconds. Typical range 20-200. */ //% void setSoundSamplingPeriod(int us) { From db3b9e2e2e7da695affb05796b7b5d5e5f909be5 Mon Sep 17 00:00:00 2001 From: Michal Moskal Date: Mon, 2 Nov 2020 13:05:18 +0100 Subject: [PATCH 6/6] Don't set sampling period if no change --- libs/microphone/microphonehw.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libs/microphone/microphonehw.cpp b/libs/microphone/microphonehw.cpp index cefb99f6b22..b9b517849d8 100644 --- a/libs/microphone/microphonehw.cpp +++ b/libs/microphone/microphonehw.cpp @@ -118,7 +118,8 @@ int soundSamplingPeriod() { //% void setSoundSamplingPeriod(int us) { #if MICROBIT_CODAL - uBit.adc.setSamplePeriod(us); + if (us != uBit.adc.getSamplePeriod()) + uBit.adc.setSamplePeriod(us); #else target_panic(PANIC_VARIANT_NOT_SUPPORTED); #endif