diff --git a/docs/reference/pins/set-events.md b/docs/reference/pins/set-events.md new file mode 100644 index 00000000..105a5cb9 --- /dev/null +++ b/docs/reference/pins/set-events.md @@ -0,0 +1,30 @@ +# Set Events + +Configure the type of events emitted by a given pin. + +```sig +pins.setEvents(DigitalPin.P0, PinEventType.Edge); +``` + +### Parameters + +* ``name``: The @boardname@ hardware pin to configure (``P0`` through ``P20``) +* ``type``: The type of events this pin should emit + +### Example + +The following example configures pin ``P0`` and then +subscribes to the rise and fall events. + +```blocks +control.onEvent(control.eventSourceId(EventBusSource.MICROBIT_ID_IO_P0), control.eventValueId(EventBusValue.MICROBIT_PIN_EVT_RISE), () => { + basic.showString("Rise") +}) +control.onEvent(control.eventSourceId(EventBusSource.MICROBIT_ID_IO_P0), control.eventValueId(EventBusValue.MICROBIT_PIN_EVT_FALL), () => { + basic.showString("Fall") +}) +pins.setEvents(DigitalPin.P0, PinEventType.Edge) +``` + +**This is an advanced API.** For more information, see the +[@boardname@ runtime messageBus documentation](https://lancaster-university.github.io/microbit-docs/ubit/messageBus/) \ No newline at end of file diff --git a/libs/core/_locales/core-jsdoc-strings.json b/libs/core/_locales/core-jsdoc-strings.json index 2a9ac5d3..685c6b3e 100644 --- a/libs/core/_locales/core-jsdoc-strings.json +++ b/libs/core/_locales/core-jsdoc-strings.json @@ -230,6 +230,9 @@ "pins.servoWritePin": "Writes a value to the servo, controlling the shaft accordingly. On a standard servo, this will set the angle of the shaft (in degrees), moving the shaft to that orientation. On a continuous rotation servo, this will set the speed of the servo (with ``0`` being full-speed in one direction, ``180`` being full speed in the other, and a value near ``90`` being no movement).", "pins.servoWritePin|param|name": "pin to write to", "pins.servoWritePin|param|value": "angle or rotation speed, eg:180,90,0", + "pins.setEvents": "Configures the events emitted by this pin. Events can be subscribed to\nusing ``control.onEvent()``.", + "pins.setEvents|param|name": "pin to set the event mode on, eg: DigitalPin.P0", + "pins.setEvents|param|type": "the type of events for this pin to emit, eg: PinEventType.Edge", "pins.setPull": "Configures the pull of this pin.", "pins.setPull|param|name": "pin to set the pull mode on", "pins.setPull|param|pull": "one of the mbed pull configurations: PullUp, PullDown, PullNone ", diff --git a/libs/core/_locales/core-strings.json b/libs/core/_locales/core-strings.json index ea60d955..5fd4824a 100644 --- a/libs/core/_locales/core-strings.json +++ b/libs/core/_locales/core-strings.json @@ -83,6 +83,10 @@ "Note.GSharp4|block": "G#4", "Note.GSharp5|block": "G#5", "Note.GSharp|block": "G#", + "PinEventType.Edge|block": "edge", + "PinEventType.None|block": "none", + "PinEventType.Pulse|block": "pulse", + "PinEventType.Touch|block": "touch", "PinPullMode.PullDown|block": "down", "PinPullMode.PullNone|block": "none", "PinPullMode.PullUp|block": "up", @@ -177,6 +181,7 @@ "pins.pulseIn|block": "pulse in (µs)|pin %name|pulsed %value", "pins.servoSetPulse|block": "servo set pulse|pin %value|to (µs) %micros", "pins.servoWritePin|block": "servo write|pin %name|to %value", + "pins.setEvents|block": "set pin %pin|to emit %type|events", "pins.setPull|block": "set pull|pin %pin|to %pull", "pins.spiWrite|block": "spi write %value", "pins|block": "pins", diff --git a/libs/core/control.cpp b/libs/core/control.cpp index d50def0a..432a9134 100644 --- a/libs/core/control.cpp +++ b/libs/core/control.cpp @@ -57,6 +57,10 @@ enum EventBusValue { MICROBIT_BUTTON_EVT_CLICK_ = MICROBIT_BUTTON_EVT_CLICK, MICROBIT_RADIO_EVT_DATAGRAM_ = MICROBIT_RADIO_EVT_DATAGRAM, MICROBIT_ACCELEROMETER_EVT_DATA_UPDATE_ = MICROBIT_ACCELEROMETER_EVT_DATA_UPDATE, + MICROBIT_PIN_EVT_RISE_ = MICROBIT_PIN_EVT_RISE, + MICROBIT_PIN_EVT_FALL_ = MICROBIT_PIN_EVT_FALL, + MICROBIT_PIN_EVT_PULSE_HI_ = MICROBIT_PIN_EVT_PULSE_HI, + MICROBIT_PIN_EVT_PULSE_LO_ = MICROBIT_PIN_EVT_PULSE_LO, MES_ALERT_EVT_ALARM1_ = MES_ALERT_EVT_ALARM1, MES_ALERT_EVT_ALARM2_ = MES_ALERT_EVT_ALARM2, MES_ALERT_EVT_ALARM3_ = MES_ALERT_EVT_ALARM3, diff --git a/libs/core/enums.d.ts b/libs/core/enums.d.ts index e8b9707e..7c6626a1 100644 --- a/libs/core/enums.d.ts +++ b/libs/core/enums.d.ts @@ -176,6 +176,10 @@ declare namespace input { MICROBIT_BUTTON_EVT_CLICK = 3, // MICROBIT_BUTTON_EVT_CLICK MICROBIT_RADIO_EVT_DATAGRAM = 1, // MICROBIT_RADIO_EVT_DATAGRAM MICROBIT_ACCELEROMETER_EVT_DATA_UPDATE = 1, // MICROBIT_ACCELEROMETER_EVT_DATA_UPDATE + MICROBIT_PIN_EVT_RISE = 2, // MICROBIT_PIN_EVT_RISE + MICROBIT_PIN_EVT_FALL = 3, // MICROBIT_PIN_EVT_FALL + MICROBIT_PIN_EVT_PULSE_HI = 4, // MICROBIT_PIN_EVT_PULSE_HI + MICROBIT_PIN_EVT_PULSE_LO = 5, // MICROBIT_PIN_EVT_PULSE_LO MES_ALERT_EVT_ALARM1 = 6, // MES_ALERT_EVT_ALARM1 MES_ALERT_EVT_ALARM2 = 7, // MES_ALERT_EVT_ALARM2 MES_ALERT_EVT_ALARM3 = 8, // MES_ALERT_EVT_ALARM3 @@ -310,6 +314,18 @@ declare namespace motors { } + declare enum PinEventType { + //% block="edge" + Edge = 1, // MICROBIT_PIN_EVENT_ON_EDGE + //% block="pulse" + Pulse = 2, // MICROBIT_PIN_EVENT_ON_PULSE + //% block="touch" + Touch = 3, // MICROBIT_PIN_EVENT_ON_TOUCH + //% block="none" + None = 0, // MICROBIT_PIN_EVENT_NONE + } + + declare enum SerialPin { P0 = 7, // MICROBIT_ID_IO_P0 P1 = 8, // MICROBIT_ID_IO_P1 diff --git a/libs/core/pins.cpp b/libs/core/pins.cpp index 440dbe03..28b78ff5 100644 --- a/libs/core/pins.cpp +++ b/libs/core/pins.cpp @@ -43,6 +43,17 @@ enum class PinPullMode { PullNone = 2 }; +enum class PinEventType { + //% block="edge" + Edge = MICROBIT_PIN_EVENT_ON_EDGE, + //% block="pulse" + Pulse = MICROBIT_PIN_EVENT_ON_PULSE, + //% block="touch" + Touch = MICROBIT_PIN_EVENT_ON_TOUCH, + //% block="none" + None = MICROBIT_PIN_EVENT_NONE +}; + MicroBitPin *getPin(int id) { switch (id) { case MICROBIT_ID_IO_P0: return &uBit.io.P0; @@ -104,7 +115,7 @@ namespace pins { */ //% help=pins/digital-write-pin weight=29 //% blockId=device_set_digital_pin block="digital write|pin %name|to %value" - void digitalWritePin(DigitalPin name, int value) { + void digitalWritePin(DigitalPin name, int value) { PINOP(setDigitalValue(value)); } @@ -113,7 +124,7 @@ namespace pins { * @param name pin to write to */ //% help=pins/analog-read-pin weight=25 - //% blockId=device_get_analog_pin block="analog read|pin %name" blockGap="8" + //% blockId=device_get_analog_pin block="analog read|pin %name" blockGap="8" int analogReadPin(AnalogPin name) { PINREAD(getAnalogValue()); } @@ -125,7 +136,7 @@ namespace pins { */ //% help=pins/analog-write-pin weight=24 //% blockId=device_set_analog_pin block="analog write|pin %name|to %value" blockGap=8 - void analogWritePin(AnalogPin name, int value) { + void analogWritePin(AnalogPin name, int value) { PINOP(setAnalogValue(value)); } @@ -136,11 +147,11 @@ namespace pins { * @param micros period in micro seconds. eg:20000 */ //% help=pins/analog-set-period weight=23 blockGap=8 - //% blockId=device_set_analog_period block="analog set period|pin %pin|to (µs)%micros" - void analogSetPeriod(AnalogPin name, int micros) { + //% blockId=device_set_analog_period block="analog set period|pin %pin|to (µs)%micros" + void analogSetPeriod(AnalogPin name, int micros) { PINOP(setAnalogPeriodUs(micros)); } - + /** * Configures this pin to a digital input, and generates events where the timestamp is the duration that this pin was either ``high`` or ``low``. */ @@ -149,11 +160,11 @@ namespace pins { void onPulsed(DigitalPin name, PulseValue pulse, Action body) { MicroBitPin* pin = getPin((int)name); if (!pin) return; - - pin->eventOn(MICROBIT_PIN_EVENT_ON_PULSE); + + pin->eventOn(MICROBIT_PIN_EVENT_ON_PULSE); registerWithDal((int)name, (int)pulse, body); } - + /** * Gets the duration of the last pulse in micro-seconds. This function should be called from a ``onPulsed`` handler. */ @@ -169,7 +180,7 @@ namespace pins { * @param name the pin which measures the pulse * @param value the value of the pulse (default high) * @param maximum duration in micro-seconds - */ + */ //% blockId="pins_pulse_in" block="pulse in (µs)|pin %name|pulsed %value" //% weight=20 int pulseIn(DigitalPin name, PulseValue value, int maxDuration = 2000000) { @@ -177,20 +188,20 @@ namespace pins { if (!pin) return 0; int pulse = value == PulseValue::High ? 1 : 0; - uint64_t tick = system_timer_current_time_us(); - uint64_t maxd = (uint64_t)maxDuration; + uint64_t tick = system_timer_current_time_us(); + uint64_t maxd = (uint64_t)maxDuration; while(pin->getDigitalValue() != pulse) { if(system_timer_current_time_us() - tick > maxd) - return 0; + return 0; } - uint64_t start = system_timer_current_time_us(); + uint64_t start = system_timer_current_time_us(); while(pin->getDigitalValue() == pulse) { if(system_timer_current_time_us() - tick > maxd) - return 0; - } - uint64_t end = system_timer_current_time_us(); - return end - start; + return 0; + } + uint64_t end = system_timer_current_time_us(); + return end - start; } /** @@ -201,7 +212,7 @@ namespace pins { //% help=pins/servo-write-pin weight=20 //% blockId=device_set_servo_pin block="servo write|pin %name|to %value" blockGap=8 //% parts=microservo trackArgs=0 - void servoWritePin(AnalogPin name, int value) { + void servoWritePin(AnalogPin name, int value) { PINOP(setServoValue(value)); } @@ -212,7 +223,7 @@ namespace pins { */ //% help=pins/servo-set-pulse weight=19 //% blockId=device_set_servo_pulse block="servo set pulse|pin %value|to (µs) %micros" - void servoSetPulse(AnalogPin name, int micros) { + void servoSetPulse(AnalogPin name, int micros) { PINOP(setServoPulseUs(micros)); } @@ -223,8 +234,9 @@ namespace pins { * Sets the pin used when using `pins->analog pitch`. * @param name TODO */ - //% help=pins/analog-set-pitch weight=12 - void analogSetPitchPin(AnalogPin name) { + //% blockId=device_analog_set_pitch_pin block="analog set pitch pin %name" + //% help=pins/analog-set-pitch weight=3 advanced=true + void analogSetPitchPin(AnalogPin name) { pitchPin = getPin((int)name); } @@ -233,16 +245,18 @@ namespace pins { * @param frequency TODO * @param ms TODO */ - //% help=pins/analog-pitch weight=14 async - void analogPitch(int frequency, int ms) { - if (pitchPin == NULL) return; + //% blockId=device_analog_pitch block="analog pitch %frequency|for (ms) %ms" + //% help=pins/analog-pitch weight=4 async advanced=true blockGap=8 + void analogPitch(int frequency, int ms) { + if (pitchPin == NULL) + analogSetPitchPin(AnalogPin::P1); if (frequency <= 0) { pitchPin->setAnalogValue(0); } else { pitchPin->setAnalogValue(512); pitchPin->setAnalogPeriodUs(1000000/frequency); } - + if (ms > 0) { fiber_sleep(ms); pitchPin->setAnalogValue(0); @@ -251,7 +265,7 @@ namespace pins { } } - + /** * Configures the pull of this pin. * @param name pin to set the pull mode on @@ -260,13 +274,25 @@ namespace pins { //% help=pins/set-pull weight=3 //% blockId=device_set_pull block="set pull|pin %pin|to %pull" void setPull(DigitalPin name, PinPullMode pull) { - PinMode m = pull == PinPullMode::PullDown + PinMode m = pull == PinPullMode::PullDown ? PinMode::PullDown - : pull == PinPullMode::PullUp ? PinMode::PullUp + : pull == PinPullMode::PullUp ? PinMode::PullUp : PinMode::PullNone; PINOP(setPull(m)); } + /** + * Configures the events emitted by this pin. Events can be subscribed to + * using ``control.onEvent()``. + * @param name pin to set the event mode on, eg: DigitalPin.P0 + * @param type the type of events for this pin to emit, eg: PinEventType.Edge + */ + //% help=pins/set-events weight=4 advanced=true + //% blockId=device_set_pin_events block="set pin %pin|to emit %type|events" + void setEvents(DigitalPin name, PinEventType type) { + getPin((int)name)->eventOn((int)type); + } + /** * Create a new zero-initialized buffer. * @param size number of bytes in the buffer @@ -287,7 +313,7 @@ namespace pins { uBit.i2c.read(address << 1, (char*)buf->payload, size, repeat); return buf; } - + /** * Write bytes to a 7-bit I2C `address`. */ @@ -314,5 +340,5 @@ namespace pins { auto p = allocSPI(); return p->write(value); } - + } diff --git a/libs/core/shims.d.ts b/libs/core/shims.d.ts index e2f09c7b..0072bae3 100644 --- a/libs/core/shims.d.ts +++ b/libs/core/shims.d.ts @@ -651,7 +651,8 @@ declare namespace pins { * Sets the pin used when using `pins->analog pitch`. * @param name TODO */ - //% help=pins/analog-set-pitch weight=12 shim=pins::analogSetPitchPin + //% blockId=device_analog_set_pitch_pin block="analog set pitch pin %name" + //% help=pins/analog-set-pitch weight=3 advanced=true shim=pins::analogSetPitchPin function analogSetPitchPin(name: AnalogPin): void; /** @@ -659,7 +660,8 @@ declare namespace pins { * @param frequency TODO * @param ms TODO */ - //% help=pins/analog-pitch weight=14 async shim=pins::analogPitch + //% blockId=device_analog_pitch block="analog pitch %frequency|for (ms) %ms" + //% help=pins/analog-pitch weight=4 async advanced=true blockGap=8 shim=pins::analogPitch function analogPitch(frequency: number, ms: number): void; /** @@ -671,6 +673,16 @@ declare namespace pins { //% blockId=device_set_pull block="set pull|pin %pin|to %pull" shim=pins::setPull function setPull(name: DigitalPin, pull: PinPullMode): void; + /** + * Configures the events emitted by this pin. Events can be subscribed to + * using ``control.onEvent()``. + * @param name pin to set the event mode on, eg: DigitalPin.P0 + * @param type the type of events for this pin to emit, eg: PinEventType.Edge + */ + //% help=pins/set-events weight=4 advanced=true + //% blockId=device_set_pin_events block="set pin %pin|to emit %type|events" shim=pins::setEvents + function setEvents(name: DigitalPin, type: PinEventType): void; + /** * Create a new zero-initialized buffer. * @param size number of bytes in the buffer diff --git a/sim/state/misc.ts b/sim/state/misc.ts index d2d20061..5130801b 100644 --- a/sim/state/misc.ts +++ b/sim/state/misc.ts @@ -119,6 +119,9 @@ namespace pxsim.pins { export function getPinAddress(name: number) { return getPin(name) } + + export function setEvents(name: number, event: number) { + } } namespace pxsim.devices {