diff --git a/libs/microbit/music.ts b/libs/microbit/music.ts index 9426519a..a02ace40 100644 --- a/libs/microbit/music.ts +++ b/libs/microbit/music.ts @@ -157,6 +157,10 @@ namespace music { export function noteFrequency(name: Notes): number { return name; } + + function init() { + if (beatsPerMinute <= 0) beatsPerMinute = 120; + } /** * Returns the duration of a beat in milli-seconds @@ -164,6 +168,7 @@ namespace music { //% help=/functions/beat weight=49 //% blockId=device_beat block="%fraction|beat" export function beat(fraction : BeatFraction = BeatFraction.Whole): number { + init(); let beat = 60000 / beatsPerMinute; if (fraction == BeatFraction.Whole) return beat; else if (fraction == BeatFraction.Half) return beat / 2; @@ -178,6 +183,7 @@ namespace music { //% help=/functions/tempo weight=40 //% blockId=device_tempo block="tempo (bpm)" blockGap=8 export function tempo(): number { + init(); return beatsPerMinute; } @@ -188,7 +194,7 @@ namespace music { //% help=/functions/tempo weight=39 //% blockId=device_change_tempo block="change tempo by (bpm)|%value" blockGap=8 export function changeTempoBy(bpm: number): void { - setTempo(beatsPerMinute + bpm); + setTempo(beat(BeatFraction.Whole) + bpm); } /** @@ -198,6 +204,7 @@ namespace music { //% help=/functions/tempo weight=38 //% blockId=device_set_tempo block="set tempo to (bpm)|%value" export function setTempo(bpm: number): void { + init(); if (bpm > 0) { beatsPerMinute = Math.max(1, bpm); } diff --git a/sim/libmbit.ts b/sim/libmbit.ts index 3cb00c7b..837f38a1 100644 --- a/sim/libmbit.ts +++ b/sim/libmbit.ts @@ -322,6 +322,8 @@ namespace ks.rt.micro_bit { export function setAnalogPeriodUs(pin: Pin, micros:number) { pin.mode = PinMode.Analog | PinMode.Output; + pin.period = micros; + board().updateView(); } export function servoWritePin(pin: Pin, value: number) { @@ -385,16 +387,33 @@ namespace ks.rt.micro_bit { } export function enablePitch(pin: Pin) { - pin.mode = PinMode.Analog | PinMode.Output; + pin.mode = PinMode.Analog | PinMode.Output | PinMode.Pitch; } export function pitch(frequency: number, ms: number) { + // update analog output + let pin = board().pins.filter(pin => !!pin && (pin.mode & PinMode.Pitch) != 0)[0] || board().pins[0]; + if (frequency <= 0) { + pin.value = 0; + pin.period = 0; + } else { + pin.value = 512; + pin.period = 1000000/frequency; + } + board().updateView(); + let cb = getResume(); AudioContextManager.tone(frequency, 1); - setTimeout(() => { - if (ms > 0) AudioContextManager.stop(); - cb() - }, ms); + if (ms <= 0) cb(); + else { + setTimeout(() => { + AudioContextManager.stop(); + pin.value = 0; + pin.period = 0; + board().updateView(); + cb() + }, ms); + } } diff --git a/sim/simsvg.ts b/sim/simsvg.ts index 9f3158be..2bf687fd 100644 --- a/sim/simsvg.ts +++ b/sim/simsvg.ts @@ -219,7 +219,7 @@ namespace ks.rt.micro_bit { let v = ''; if (pin.mode & PinMode.Analog) { v = Math.floor(100 - (pin.value || 0) / 1023 * 100) + '%'; - if(text) text.textContent = (pin.value || 0) + ""; + if(text) text.textContent = (pin.period ? "~" : "") + (pin.value || 0) + ""; } else if (pin.mode & PinMode.Digital) { v = pin.value > 0 ? '0%' : '100%'; diff --git a/sim/state.ts b/sim/state.ts index 104a3748..abbf7778 100644 --- a/sim/state.ts +++ b/sim/state.ts @@ -14,13 +14,15 @@ namespace ks.rt.micro_bit { Analog = 0x0002, Input = 0x0004, Output = 0x0008, - Touch = 0x0010 + Touch = 0x0010, + Pitch = 0x0020 } export class Pin { constructor(public id: number) { } touched = false; value = 0; + period = 0; mode = PinMode.Unused; isTouched(): boolean {