mirror of
https://github.com/espruino/Espruino.git
synced 2025-12-08 19:06:15 +00:00
Util Timer now runs independently of system time. More accurate on nRF52 (fix #2125)
Also remove (mostly) duplicated jshPinPulse
This commit is contained in:
parent
ad3eb1094d
commit
8861b27954
@ -33,6 +33,7 @@
|
||||
Bangle.js1: Add 'back' option to E.showScroller and Bangle.setUI
|
||||
Bangle.js1: setUI button handlers now work on falling edge
|
||||
Bangle.js: Add setUI custom 'swipe' handler
|
||||
Util Timer now runs independently of system time. More accurate on nRF52 (fix #2125)
|
||||
|
||||
2v12 : nRF52840: Flow control XOFF is now sent at only 3/8th full - delays in BLE mean we can sometimes fill our 1k input buffer otherwise
|
||||
__FILE__ is now set correctly for apps (fixes 2v11 regression)
|
||||
|
||||
@ -1674,7 +1674,7 @@ static void jswrap_banglejs_setLCDPowerBacklight(bool isOn) {
|
||||
#elif defined(ESPR_BACKLIGHT_FADE)
|
||||
if (!lcdFadeHandlerActive) {
|
||||
JsSysTime t = jshGetTimeFromMilliseconds(10);
|
||||
jstExecuteFn(backlightFadeHandler, NULL, t, t);
|
||||
jstExecuteFn(backlightFadeHandler, NULL, t, t, NULL);
|
||||
lcdFadeHandlerActive = true;
|
||||
backlightFadeHandler();
|
||||
}
|
||||
@ -4403,7 +4403,7 @@ JsVar *jswrap_banglejs_beep(int time, int freq) {
|
||||
#endif
|
||||
}
|
||||
}
|
||||
jstExecuteFn(jswrap_banglejs_beep_callback, NULL, jshGetTimeFromMilliseconds(time), 0);
|
||||
jstExecuteFn(jswrap_banglejs_beep_callback, NULL, jshGetTimeFromMilliseconds(time), 0, NULL);
|
||||
return jsvLockAgain(promiseBeep);
|
||||
}
|
||||
|
||||
@ -4446,7 +4446,7 @@ JsVar *jswrap_banglejs_buzz(int time, JsVarFloat amt) {
|
||||
if (!promiseBuzz) return 0;
|
||||
|
||||
buzzAmt = (unsigned char)(amt*255);
|
||||
if (jstExecuteFn(jswrap_banglejs_buzz_callback, NULL, jshGetTimeFromMilliseconds(time), 0)) {
|
||||
if (jstExecuteFn(jswrap_banglejs_buzz_callback, NULL, jshGetTimeFromMilliseconds(time), 0, NULL)) {
|
||||
// task schedule succeeded - start buzz
|
||||
if (bangleFlags & JSBF_ENABLE_BUZZ) {
|
||||
_jswrap_banglejs_setVibration();
|
||||
|
||||
@ -257,7 +257,7 @@ void jswrap_microbit_show_raw(uint32_t newState) {
|
||||
if ((newState!=0) && (microbitLEDState==0)) {
|
||||
// we want to display something but we don't have an interval
|
||||
JsSysTime period = jshGetTimeFromMilliseconds(MB_LED_UPDATE_MS);
|
||||
jstExecuteFn(jswrap_microbit_display_callback, 0, period, (uint32_t)period);
|
||||
jstExecuteFn(jswrap_microbit_display_callback, 0, period, (uint32_t)period, NULL);
|
||||
// and also set pins to outputs
|
||||
nrf_gpio_cfg_output(MB_LED_COL1);
|
||||
nrf_gpio_cfg_output(MB_LED_COL2);
|
||||
|
||||
@ -60,7 +60,7 @@ void hrm_timer() {
|
||||
|
||||
static void hrm_sensor_timer_start() {
|
||||
JsSysTime t = jshGetTimeFromMilliseconds(hrmPollInterval);
|
||||
jstExecuteFn(hrm_timer, NULL, t, t);
|
||||
jstExecuteFn(hrm_timer, NULL, t, t, NULL);
|
||||
}
|
||||
|
||||
static void hrm_sensor_timer_stop() {
|
||||
|
||||
@ -30,7 +30,7 @@ void hrm_timer() {
|
||||
|
||||
static void hrm_sensor_timer_start() {
|
||||
JsSysTime t = jshGetTimeFromMilliseconds(hrmPollInterval);
|
||||
jstExecuteFn(hrm_timer, NULL, t, t);
|
||||
jstExecuteFn(hrm_timer, NULL, t, t, NULL);
|
||||
}
|
||||
|
||||
static void hrm_sensor_timer_stop() {
|
||||
|
||||
@ -1109,6 +1109,7 @@ void jswrap_puck_IR(JsVar *data, Pin cathode, Pin anode) {
|
||||
_jswrap_puck_IR_pin = cathode;
|
||||
}
|
||||
JsSysTime time = 0;
|
||||
uint32_t timerOffset = jstGetUtilTimerOffset();
|
||||
bool hasPulses = false;
|
||||
|
||||
JsvIterator it;
|
||||
@ -1116,11 +1117,11 @@ void jswrap_puck_IR(JsVar *data, Pin cathode, Pin anode) {
|
||||
while (jsvIteratorHasElement(&it)) {
|
||||
JsVarFloat pulseTime = jsvIteratorGetFloatValue(&it);
|
||||
if (twoPin) {
|
||||
if (hasPulses) jstPinOutputAtTime(time, &anode, 1, pulsePolarity);
|
||||
if (hasPulses) jstPinOutputAtTime(time, &timerOffset, &anode, 1, pulsePolarity);
|
||||
else jshPinSetState(anode, JSHPINSTATE_GPIO_OUT);
|
||||
} else {
|
||||
if (pulsePolarity) jstExecuteFn(_jswrap_puck_IR_on, NULL, time, 0);
|
||||
else jstExecuteFn(_jswrap_puck_IR_off, NULL, time, 0);
|
||||
if (pulsePolarity) jstExecuteFn(_jswrap_puck_IR_on, NULL, time, 0, &timerOffset);
|
||||
else jstExecuteFn(_jswrap_puck_IR_off, NULL, time, 0, &timerOffset);
|
||||
}
|
||||
hasPulses = true;
|
||||
time += jshGetTimeFromMilliseconds(pulseTime);
|
||||
@ -1132,9 +1133,9 @@ void jswrap_puck_IR(JsVar *data, Pin cathode, Pin anode) {
|
||||
if (hasPulses) {
|
||||
if (twoPin) {
|
||||
uint32_t d = cathode | anode<<8;
|
||||
jstExecuteFn(_jswrap_puck_IR_done, (void*)d, time, 0);
|
||||
jstExecuteFn(_jswrap_puck_IR_done, (void*)d, time, 0, &timerOffset);
|
||||
} else {
|
||||
jstExecuteFn(_jswrap_puck_IR_off, NULL, time, 0);
|
||||
jstExecuteFn(_jswrap_puck_IR_off, NULL, time, 0, &timerOffset);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -58,6 +58,7 @@ TriggerStruct mainTrigger = { (Pin)-1/*pin*/};
|
||||
|
||||
void trigOnTimingPulse(TriggerStruct *data, JsSysTime pulseTime) {
|
||||
JsSysTime currentTime = jshGetSystemTime();
|
||||
uint32_t timerOffset = jstGetUtilTimerOffset();
|
||||
int timeDiff = (int)(pulseTime - data->lastTime);
|
||||
if (timeDiff < 0) {
|
||||
data->errors |= TRIGERR_WRONG_TIME;
|
||||
@ -166,10 +167,10 @@ void trigOnTimingPulse(TriggerStruct *data, JsSysTime pulseTime) {
|
||||
//jsiConsolePrint("Trigger already passed\n");
|
||||
}
|
||||
|
||||
if (!jstPinOutputAtTime(trigTime, trig->pins, TRIGGERPOINT_TRIGGERS_COUNT, 0xFF))
|
||||
if (!jstPinOutputAtTime(trigTime, &timerOffset, trig->pins, TRIGGERPOINT_TRIGGERS_COUNT, 0xFF))
|
||||
data->errors |= TRIGERR_TIMER_FULL;
|
||||
if (trig->pulseLength>0) {
|
||||
if (!jstPinOutputAtTime(trigTime+trig->pulseLength, trig->pins, TRIGGERPOINT_TRIGGERS_COUNT, 0))
|
||||
if (!jstPinOutputAtTime(trigTime+trig->pulseLength, &timerOffset, trig->pins, TRIGGERPOINT_TRIGGERS_COUNT, 0))
|
||||
data->errors |= TRIGERR_TIMER_FULL;
|
||||
}
|
||||
// trigger fired, so update it
|
||||
|
||||
@ -198,8 +198,6 @@ typedef enum {
|
||||
/// Output an analog value on a pin - either via DAC, hardware PWM, or software PWM
|
||||
JshPinFunction jshPinAnalogOutput(Pin pin, JsVarFloat value, JsVarFloat freq, JshAnalogOutputFlags flags); // if freq<=0, the default is used
|
||||
|
||||
/// Pulse a pin for a certain time, but via IRQs, not JS: `digitalWrite(pin,value);setTimeout("digitalWrite(pin,!value)", time*1000);`
|
||||
void jshPinPulse(Pin pin, bool value, JsVarFloat time);
|
||||
/// Can the given pin be watched? it may not be possible because of conflicts
|
||||
bool jshCanWatch(Pin pin);
|
||||
/// start watching pin - return the EXTI (IRQ number flag) associated with it
|
||||
|
||||
@ -47,6 +47,7 @@ void jsserialSoftwareFunc(
|
||||
bitCnt += 1;
|
||||
|
||||
// Get ready to send
|
||||
uint32_t timerOffset = jstGetUtilTimerOffset();
|
||||
JsSysTime bitTime = jshGetTimeFromMilliseconds(1000.0 / inf->baudRate);
|
||||
JsSysTime time;
|
||||
UtilTimerTask task;
|
||||
@ -70,19 +71,19 @@ void jsserialSoftwareFunc(
|
||||
} else {
|
||||
// state changed!
|
||||
time += bitTime*outCount;
|
||||
jstPinOutputAtTime(time, &inf->pinTX, 1, bit);
|
||||
jstPinOutputAtTime(time, &timerOffset, &inf->pinTX, 1, bit);
|
||||
outState = bit;
|
||||
outCount = 1;
|
||||
}*/
|
||||
// hacky - but seems like we may have some timing problems otherwise
|
||||
jstPinOutputAtTime(time, &inf->pinTX, 1, bit);
|
||||
jstPinOutputAtTime(time, &timerOffset, &inf->pinTX, 1, bit);
|
||||
//jsiConsolePrintf("-> %d\n",bit);
|
||||
time += bitTime;
|
||||
}
|
||||
// And finish off by raising...
|
||||
time += bitTime*outCount;
|
||||
//jsiConsolePrintf("-> 1 (final)\n");
|
||||
jstPinOutputAtTime(time, &inf->pinTX, 1, 1);
|
||||
jstPinOutputAtTime(time, &timerOffset, &inf->pinTX, 1, 1);
|
||||
// we do this even if we are high, because we want to ensure that the next char is properly spaced
|
||||
// Ideally we'd be able to store the last bit time when sending so we could just go straight on from it
|
||||
}
|
||||
|
||||
@ -31,6 +31,8 @@ unsigned int utilTimerData;
|
||||
uint16_t utilTimerReload0H, utilTimerReload0L, utilTimerReload1H, utilTimerReload1L;
|
||||
/// When we rescheduled the timer, how far in the future were we meant to get called (in system time)?
|
||||
int utilTimerPeriod;
|
||||
/// Incremented with utilTimerPeriod - used when we're adding multiple items and we want them all relative to each other
|
||||
volatile int utilTimerOffset;
|
||||
|
||||
|
||||
#ifndef SAVE_ON_FLASH
|
||||
@ -95,6 +97,7 @@ void jstUtilTimerInterruptHandler() {
|
||||
utilTimerTasks[t].time -= utilTimerPeriod;
|
||||
t = (t+1) & (UTILTIMERTASK_TASKS-1);
|
||||
}
|
||||
utilTimerOffset += utilTimerPeriod;
|
||||
// Check timers and execute any timers that are due
|
||||
while (utilTimerTasksTail!=utilTimerTasksHead && utilTimerTasks[utilTimerTasksTail].time <= 0) {
|
||||
UtilTimerTask *task = &utilTimerTasks[utilTimerTasksTail];
|
||||
@ -212,6 +215,11 @@ void jstUtilTimerWaitEmpty() {
|
||||
WAIT_UNTIL(!jstUtilTimerIsRunning(), "Utility Timer");
|
||||
}
|
||||
|
||||
/// Get the current timer offset - supply this when adding >1 timer task to ensure they are all executed at the same time relative to each other
|
||||
uint32_t jstGetUtilTimerOffset() {
|
||||
return utilTimerOffset;
|
||||
}
|
||||
|
||||
/// Is the timer full - can it accept any other signals?
|
||||
static bool utilTimerIsFull() {
|
||||
unsigned char nextHead = (utilTimerTasksHead+1) & (UTILTIMERTASK_TASKS-1);
|
||||
@ -226,12 +234,20 @@ void jstRestartUtilTimer() {
|
||||
jshUtilTimerStart(utilTimerPeriod);
|
||||
}
|
||||
|
||||
// Queue a task up to be executed when a timer fires... return false on failure
|
||||
bool utilTimerInsertTask(UtilTimerTask *task) {
|
||||
/** Queue a task up to be executed when a timer fires... return false on failure.
|
||||
* task.time is the delay at which to execute the task. If timerOffset!==NULL then
|
||||
* task.time is relative to the time at which timerOffset=jstGetUtilTimerOffset().
|
||||
* This allows pulse trains/etc to be scheduled in sync.
|
||||
*/
|
||||
bool utilTimerInsertTask(UtilTimerTask *task, uint32_t *timerOffset) {
|
||||
// check if queue is full or not
|
||||
if (utilTimerIsFull()) return false;
|
||||
if (!utilTimerInIRQ) jshInterruptOff();
|
||||
|
||||
// See above - keep times in sync
|
||||
if (timerOffset)
|
||||
task->time += (int)*timerOffset - (int)utilTimerOffset;
|
||||
|
||||
// find out where to insert
|
||||
unsigned char insertPos = utilTimerTasksTail;
|
||||
while (insertPos != utilTimerTasksHead && utilTimerTasks[insertPos].time < task->time)
|
||||
@ -355,7 +371,7 @@ bool jstGetLastBufferTimerTask(JsVar *var, UtilTimerTask *task) {
|
||||
}
|
||||
#endif
|
||||
|
||||
bool jstPinOutputAtTime(JsSysTime time, Pin *pins, int pinCount, uint8_t value) {
|
||||
bool jstPinOutputAtTime(JsSysTime time, uint32_t *timerOffset, Pin *pins, int pinCount, uint8_t value) {
|
||||
assert(pinCount<=UTILTIMERTASK_PIN_COUNT);
|
||||
UtilTimerTask task;
|
||||
task.time = (int)time;
|
||||
@ -367,7 +383,7 @@ bool jstPinOutputAtTime(JsSysTime time, Pin *pins, int pinCount, uint8_t value)
|
||||
task.data.set.value = value;
|
||||
|
||||
WAIT_UNTIL(!utilTimerIsFull(), "Utility Timer");
|
||||
return utilTimerInsertTask(&task);
|
||||
return utilTimerInsertTask(&task, timerOffset);
|
||||
}
|
||||
|
||||
// Do software PWM on the given pin, using the timer IRQs
|
||||
@ -444,15 +460,18 @@ bool jstPinPWM(JsVarFloat freq, JsVarFloat dutyCycle, Pin pin) {
|
||||
|
||||
// first task is to turn on
|
||||
jshPinSetValue(pin, 1);
|
||||
uint32_t timerOffset = jstGetUtilTimerOffset();
|
||||
// now start the 2 PWM tasks
|
||||
WAIT_UNTIL(!utilTimerIsFull(), "Utility Timer");
|
||||
if (!utilTimerInsertTask(&taskon)) return false;
|
||||
if (!utilTimerInsertTask(&taskon, &timerOffset)) return false;
|
||||
WAIT_UNTIL(!utilTimerIsFull(), "Utility Timer");
|
||||
return utilTimerInsertTask(&taskoff);
|
||||
return utilTimerInsertTask(&taskoff, &timerOffset);
|
||||
}
|
||||
|
||||
/// Execute the given function repeatedly after the given time period. If period=0, don't repeat. True on success or false on failure to schedule
|
||||
bool jstExecuteFn(UtilTimerTaskExecFn fn, void *userdata, JsSysTime startTime, uint32_t period) {
|
||||
/** Execute the given function repeatedly after the given time period. If period=0, don't repeat. True on success or false on failure to schedule
|
||||
* See utilTimerInsertTask for notes on timerOffset
|
||||
*/
|
||||
bool jstExecuteFn(UtilTimerTaskExecFn fn, void *userdata, JsSysTime startTime, uint32_t period, uint32_t *timerOffset) {
|
||||
UtilTimerTask task;
|
||||
task.time = (int)startTime;
|
||||
task.repeatInterval = period;
|
||||
@ -461,7 +480,7 @@ bool jstExecuteFn(UtilTimerTaskExecFn fn, void *userdata, JsSysTime startTime, u
|
||||
task.data.execute.userdata = userdata;
|
||||
|
||||
WAIT_UNTIL(!utilTimerIsFull(), "Utility Timer");
|
||||
return utilTimerInsertTask(&task);
|
||||
return utilTimerInsertTask(&task, timerOffset);
|
||||
}
|
||||
|
||||
/// Stop executing the given function
|
||||
@ -475,7 +494,7 @@ bool jstStopExecuteFn(UtilTimerTaskExecFn fn, void *userdata) {
|
||||
/// Set the utility timer so we're woken up in whatever time period
|
||||
bool jstSetWakeUp(JsSysTime period) {
|
||||
UtilTimerTask task;
|
||||
task.time = (int)(jshGetSystemTime() + period);
|
||||
task.time = (int)period;
|
||||
task.repeatInterval = 0;
|
||||
task.type = UET_WAKEUP;
|
||||
|
||||
@ -497,7 +516,7 @@ bool jstSetWakeUp(JsSysTime period) {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ok = utilTimerInsertTask(&task);
|
||||
bool ok = utilTimerInsertTask(&task, NULL);
|
||||
// We wait until the timer is out of the reload event, because the reload event itself would wake us up
|
||||
return ok;
|
||||
}
|
||||
@ -528,7 +547,7 @@ bool jstStartSignal(JsSysTime startTime, JsSysTime period, Pin pin, JsVar *curre
|
||||
if (!jshIsPinValid(pin)) return false;
|
||||
UtilTimerTask task;
|
||||
task.repeatInterval = (unsigned int)period;
|
||||
task.time = (int)(startTime + period);
|
||||
task.time = (int)(startTime-jshGetSystemTime() + period);
|
||||
task.type = type;
|
||||
if (UET_IS_BUFFER_WRITE_EVENT(type)) {
|
||||
task.data.buffer.pinFunction = jshGetCurrentPinFunction(pin);
|
||||
@ -552,7 +571,7 @@ bool jstStartSignal(JsSysTime startTime, JsSysTime period, Pin pin, JsVar *curre
|
||||
}
|
||||
jstUtilTimerSetupBuffer(&task);
|
||||
|
||||
return utilTimerInsertTask(&task);
|
||||
return utilTimerInsertTask(&task, NULL);
|
||||
}
|
||||
|
||||
|
||||
@ -569,6 +588,7 @@ void jstReset() {
|
||||
jshUtilTimerDisable();
|
||||
utilTimerOn = false;
|
||||
utilTimerTasksTail = utilTimerTasksHead = 0;
|
||||
utilTimerOffset = 0;
|
||||
utilTimerPeriod = 0;
|
||||
}
|
||||
|
||||
|
||||
@ -103,20 +103,27 @@ void jstUtilTimerWaitEmpty();
|
||||
/// Return true if the utility timer is running
|
||||
bool jstUtilTimerIsRunning();
|
||||
|
||||
/// Get the current timer offset - supply this when adding >1 timer task to ensure they are all executed at the same time relative to each other
|
||||
uint32_t jstGetUtilTimerOffset();
|
||||
|
||||
/// Return true if a timer task for the given pin exists (and set 'task' to it)
|
||||
bool jstGetLastPinTimerTask(Pin pin, UtilTimerTask *task);
|
||||
|
||||
/// Return true if a timer task for the given variable exists (and set 'task' to it)
|
||||
bool jstGetLastBufferTimerTask(JsVar *var, UtilTimerTask *task);
|
||||
|
||||
/// returns false if timer queue was full... Changes the state of one or more pins at a certain time (using a timer)
|
||||
bool jstPinOutputAtTime(JsSysTime time, Pin *pins, int pinCount, uint8_t value);
|
||||
/** returns false if timer queue was full... Changes the state of one or more pins at a certain time in the future (using a timer)
|
||||
* See utilTimerInsertTask for notes on timerOffset
|
||||
*/
|
||||
bool jstPinOutputAtTime(JsSysTime time, uint32_t *timerOffset, Pin *pins, int pinCount, uint8_t value);
|
||||
|
||||
// Do software PWM on the given pin, using the timer IRQs
|
||||
bool jstPinPWM(JsVarFloat freq, JsVarFloat dutyCycle, Pin pin);
|
||||
|
||||
/// Execute the given function repeatedly after the given time period. If period=0, don't repeat. True on success or false on failure to schedule
|
||||
bool jstExecuteFn(UtilTimerTaskExecFn fn, void *userdata, JsSysTime startTime, uint32_t period);
|
||||
/** Execute the given function repeatedly after the given time period. If period=0, don't repeat. True on success or false on failure to schedule
|
||||
* See utilTimerInsertTask for notes on timerOffset
|
||||
*/
|
||||
bool jstExecuteFn(UtilTimerTaskExecFn fn, void *userdata, JsSysTime startTime, uint32_t period, uint32_t *timerOffset);
|
||||
|
||||
/// Stop executing the given function
|
||||
bool jstStopExecuteFn(UtilTimerTaskExecFn fn, void *userdata);
|
||||
@ -149,8 +156,12 @@ void jstDumpUtilityTimers();
|
||||
need to be called by anything outside jstimer.c */
|
||||
void jstRestartUtilTimer();
|
||||
|
||||
// Queue a task up to be executed when a timer fires... return false on failure
|
||||
bool utilTimerInsertTask(UtilTimerTask *task);
|
||||
/** Queue a task up to be executed when a timer fires... return false on failure.
|
||||
* task.time is the delay at which to execute the task. If timerOffset!==NULL then
|
||||
* task.time is relative to the time at which timerOffset=jstGetUtilTimerOffset().
|
||||
* This allows pulse trains/etc to be scheduled in sync.
|
||||
*/
|
||||
bool utilTimerInsertTask(UtilTimerTask *task, uint32_t *timerOffset);
|
||||
|
||||
/// Remove the task that that 'checkCallback' returns true for. Returns false if none found
|
||||
bool utilTimerRemoveTask(bool (checkCallback)(UtilTimerTask *task, void* data), void *checkCallbackData);
|
||||
|
||||
@ -17,6 +17,7 @@
|
||||
#include "jsvar.h"
|
||||
#include "jswrap_arraybuffer.h" // for jswrap_io_peek
|
||||
#include "jswrapper.h" // for JSWAT_VOID
|
||||
#include "jstimer.h" // for digitalPulse
|
||||
|
||||
#ifdef ESP32
|
||||
#include "freertos/FreeRTOS.h"
|
||||
@ -218,21 +219,38 @@ eg. `digitalPulse(A0,1,5);` pulses A0 high for 5ms. `digitalPulse(A0,1,[5,2,4]);
|
||||
digitalPulse is for SHORT pulses that need to be very accurate. If you're doing anything over a few milliseconds, use setTimeout instead.
|
||||
*/
|
||||
void jswrap_io_digitalPulse(Pin pin, bool value, JsVar *times) {
|
||||
if (!jshIsPinValid(pin)) {
|
||||
jsExceptionHere(JSET_ERROR, "Invalid pin!");
|
||||
return;
|
||||
}
|
||||
// check for currently running timer tasks
|
||||
UtilTimerTask task;
|
||||
uint32_t timerOffset = jstGetUtilTimerOffset();
|
||||
bool hasTimer = jstGetLastPinTimerTask(pin, &task);
|
||||
if (!hasTimer) task.time = 0;
|
||||
// now start either one or a series of pulses
|
||||
if (jsvIsNumeric(times)) {
|
||||
JsVarFloat time = jsvGetFloat(times);
|
||||
if (time<0 || isnan(time)) {
|
||||
JsVarFloat pulseTime = jsvGetFloat(times);
|
||||
if (pulseTime<0 || isnan(pulseTime)) {
|
||||
jsExceptionHere(JSET_ERROR, "Pulse Time given for digitalPulse is less than 0, or not a number");
|
||||
} else {
|
||||
jshPinPulse(pin, value, time);
|
||||
}
|
||||
} else if (pulseTime>0) {
|
||||
if (!hasTimer) jshPinOutput(pin, value);
|
||||
task.time += jshGetTimeFromMilliseconds(pulseTime);
|
||||
jstPinOutputAtTime(task.time, &timerOffset, &pin, 1, !value);
|
||||
} else jstUtilTimerWaitEmpty(); // time==0
|
||||
} else if (jsvIsIterable(times)) {
|
||||
// iterable, so output a square wave
|
||||
if (!hasTimer) jshPinOutput(pin, value);
|
||||
JsvIterator it;
|
||||
jsvIteratorNew(&it, times, JSIF_EVERY_ARRAY_ELEMENT);
|
||||
while (jsvIteratorHasElement(&it)) {
|
||||
JsVarFloat time = jsvIteratorGetFloatValue(&it);
|
||||
if (time>=0 && !isnan(time))
|
||||
jshPinPulse(pin, value, time);
|
||||
JsVarFloat pulseTime = jsvIteratorGetFloatValue(&it);
|
||||
if (!isnan(pulseTime)) {
|
||||
if (pulseTime>0) {
|
||||
task.time += jshGetTimeFromMilliseconds(pulseTime);
|
||||
jstPinOutputAtTime(task.time, &timerOffset, &pin, 1, !value);
|
||||
}
|
||||
}
|
||||
value = !value;
|
||||
jsvIteratorNext(&it);
|
||||
}
|
||||
|
||||
@ -135,7 +135,7 @@ Sets the output state of the pin to the parameter given at the specified time.
|
||||
void jswrap_pin_writeAtTime(JsVar *parent, bool value, JsVarFloat time) {
|
||||
Pin pin = jshGetPinFromVar(parent);
|
||||
JsSysTime sTime = jshGetTimeFromMilliseconds(time*1000) - jshGetSystemTime();
|
||||
jstPinOutputAtTime(sTime, &pin, 1, value);
|
||||
jstPinOutputAtTime(sTime, NULL, &pin, 1, value);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@ -147,9 +147,6 @@ JshPinFunction jshPinAnalogOutput(Pin pin, JsVarFloat value, JsVarFloat freq, Js
|
||||
return JSH_NOTHING;
|
||||
}
|
||||
|
||||
void jshPinPulse(Pin pin, bool value, JsVarFloat time) {
|
||||
}
|
||||
|
||||
bool jshCanWatch(Pin pin) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -86,7 +86,7 @@ void startNotifTimer(){
|
||||
inNotif = true;
|
||||
JsSysTime period = jshGetTimeFromMilliseconds(10);
|
||||
JsSysTime time = jshGetSystemTime();
|
||||
jstExecuteFn(notifTimerCB, NULL, time + period, period);
|
||||
jstExecuteFn(notifTimerCB, NULL, time + period, period, NULL);
|
||||
}
|
||||
void gatts_sendNotification(int c){
|
||||
notifBuffer[notifBufferPnt] = (uint8_t)c;
|
||||
|
||||
@ -436,42 +436,6 @@ bool CALLED_FROM_INTERRUPT jshGetWatchedPinState(IOEventFlags eventFlag) { // ca
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Set the value of the pin to be the value supplied and then wait for
|
||||
* a given period and set the pin value again to be the opposite.
|
||||
*/
|
||||
void jshPinPulse(
|
||||
Pin pin, //!< The pin to be pulsed.
|
||||
bool pulsePolarity, //!< The value to be pulsed into the pin.
|
||||
JsVarFloat pulseTime //!< The duration in milliseconds to hold the pin.
|
||||
) {
|
||||
// ESP32 specific version, replaced by Espruino Style version from nrf52
|
||||
//int duration = (int)pulseTime * 1000; //from millisecs to microsecs
|
||||
//sendPulse(pin, pulsePolarity, duration);
|
||||
|
||||
// ---- USE TIMER FOR PULSE
|
||||
if (!jshIsPinValid(pin)) {
|
||||
jsExceptionHere(JSET_ERROR, "Invalid pin!");
|
||||
return;
|
||||
}
|
||||
if (pulseTime<=0) {
|
||||
// just wait for everything to complete
|
||||
jstUtilTimerWaitEmpty();
|
||||
return;
|
||||
} else {
|
||||
// find out if we already had a timer scheduled
|
||||
UtilTimerTask task;
|
||||
if (!jstGetLastPinTimerTask(pin, &task)) {
|
||||
// no timer - just start the pulse now!
|
||||
jshPinOutput(pin, pulsePolarity);
|
||||
task.time = jshGetSystemTime();
|
||||
}
|
||||
// Now set the end of the pulse to happen on a timer
|
||||
jstPinOutputAtTime(task.time + jshGetTimeFromMilliseconds(pulseTime), &pin, 1, !pulsePolarity);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Determine whether the pin can be watchable.
|
||||
* \return Returns true if the pin is watchable.
|
||||
|
||||
@ -673,37 +673,6 @@ bool CALLED_FROM_INTERRUPT jshGetWatchedPinState(IOEventFlags eventFlag) { // ca
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Set the value of the pin to be the value supplied and then wait for
|
||||
* a given period and set the pin value again to be the opposite.
|
||||
*/
|
||||
void jshPinPulse(
|
||||
Pin pin, //!< The pin to be pulsed.
|
||||
bool pulsePolarity, //!< The value to be pulsed into the pin.
|
||||
JsVarFloat pulseTime //!< The duration in milliseconds to hold the pin.
|
||||
) {
|
||||
|
||||
if (!jshIsPinValid(pin)) {
|
||||
jsExceptionHere(JSET_ERROR, "Invalid pin!");
|
||||
return;
|
||||
}
|
||||
if (pulseTime <= 0) {
|
||||
// just wait for everything to complete [??? what does this mean ???]
|
||||
jstUtilTimerWaitEmpty();
|
||||
return;
|
||||
} else {
|
||||
// find out if we already had a timer scheduled
|
||||
UtilTimerTask task;
|
||||
if (!jstGetLastPinTimerTask(pin, &task)) {
|
||||
// no timer - just start the pulse now!
|
||||
jshPinOutput(pin, pulsePolarity);
|
||||
task.time = jshGetSystemTime();
|
||||
}
|
||||
// Now set the end of the pulse to happen on a timer
|
||||
jstPinOutputAtTime(task.time + jshGetTimeFromMilliseconds(pulseTime), &pin, 1, !pulsePolarity);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine whether the pin can be watchable.
|
||||
* \return Returns true if the pin is wathchable.
|
||||
|
||||
@ -579,15 +579,6 @@ JshPinFunction jshPinAnalogOutput(Pin pin, JsVarFloat value, JsVarFloat freq, Js
|
||||
return JSH_NOTHING;
|
||||
}
|
||||
|
||||
void jshPinPulse(Pin pin, bool value, JsVarFloat time) {
|
||||
if (jshIsPinValid(pin)) {
|
||||
jshPinSetState(pin, JSHPINSTATE_GPIO_OUT);
|
||||
jshPinSetValue(pin, value);
|
||||
jshDelayMicroseconds(time*1000000);
|
||||
jshPinSetValue(pin, !value);
|
||||
} else jsError("Invalid pin!");
|
||||
}
|
||||
|
||||
bool jshCanWatch(Pin pin) {
|
||||
if (jshIsPinValid(pin)) {
|
||||
IOEventFlags exti = getNewEVEXTI();
|
||||
|
||||
@ -1569,30 +1569,6 @@ void jshSetOutputValue(JshPinFunction func, int value) {
|
||||
#endif
|
||||
}
|
||||
|
||||
void jshPinPulse(Pin pin, bool pulsePolarity, JsVarFloat pulseTime) {
|
||||
// ---- USE TIMER FOR PULSE
|
||||
if (!jshIsPinValid(pin)) {
|
||||
jsExceptionHere(JSET_ERROR, "Invalid pin!");
|
||||
return;
|
||||
}
|
||||
if (pulseTime<=0) {
|
||||
// just wait for everything to complete
|
||||
jstUtilTimerWaitEmpty();
|
||||
return;
|
||||
} else {
|
||||
// find out if we already had a timer scheduled
|
||||
UtilTimerTask task;
|
||||
if (!jstGetLastPinTimerTask(pin, &task)) {
|
||||
// no timer - just start the pulse now!
|
||||
jshPinOutput(pin, pulsePolarity);
|
||||
task.time = 0;
|
||||
}
|
||||
// Now set the end of the pulse to happen on a timer
|
||||
jstPinOutputAtTime(task.time + jshGetTimeFromMilliseconds(pulseTime), &pin, 1, !pulsePolarity);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static IOEventFlags jshGetEventFlagsForWatchedPin(nrf_drv_gpiote_pin_t pin) {
|
||||
for (int i=0;i<EXTI_COUNT;i++)
|
||||
if (pin == extiToPin[i])
|
||||
|
||||
@ -2762,29 +2762,6 @@ void jshUtilTimerStart(JsSysTime period) {
|
||||
}
|
||||
|
||||
|
||||
void jshPinPulse(Pin pin, bool pulsePolarity, JsVarFloat pulseTime) {
|
||||
// ---- USE TIMER FOR PULSE
|
||||
if (!jshIsPinValid(pin)) {
|
||||
jsExceptionHere(JSET_ERROR, "Invalid pin!");
|
||||
return;
|
||||
}
|
||||
if (pulseTime<=0) {
|
||||
// just wait for everything to complete
|
||||
jstUtilTimerWaitEmpty();
|
||||
return;
|
||||
} else {
|
||||
// find out if we already had a timer scheduled
|
||||
UtilTimerTask task;
|
||||
if (!jstGetLastPinTimerTask(pin, &task)) {
|
||||
// no timer - just start the pulse now!
|
||||
jshPinOutput(pin, pulsePolarity);
|
||||
task.time = jshGetSystemTime();
|
||||
}
|
||||
// Now set the end of the pulse to happen on a timer
|
||||
jstPinOutputAtTime(task.time + jshGetTimeFromMilliseconds(pulseTime), &pin, 1, !pulsePolarity);
|
||||
}
|
||||
}
|
||||
|
||||
JshPinFunction jshGetCurrentPinFunction(Pin pin) {
|
||||
// FIXME: This isn't actually right - we need to look at the hardware or store this info somewhere.
|
||||
if (jshIsPinValid(pin)) {
|
||||
|
||||
@ -1481,31 +1481,6 @@ JshPinFunction jshPinAnalogOutput(Pin pin, JsVarFloat value, JsVarFloat freq, Js
|
||||
return 0;
|
||||
}
|
||||
|
||||
/// Pulse a pin for a certain time, but via IRQs, not JS: `digitalWrite(pin,value);setTimeout("digitalWrite(pin,!value)", time*1000);`
|
||||
void jshPinPulse(Pin pin, bool pulsePolarity, JsVarFloat pulseTime){
|
||||
// ---- USE TIMER FOR PULSE
|
||||
if (!jshIsPinValid(pin)) {
|
||||
jsExceptionHere(JSET_ERROR, "Invalid pin!");
|
||||
return;
|
||||
}
|
||||
if (pulseTime<=0) {
|
||||
// just wait for everything to complete
|
||||
jstUtilTimerWaitEmpty();
|
||||
return;
|
||||
} else {
|
||||
// find out if we already had a timer scheduled
|
||||
UtilTimerTask task;
|
||||
if (!jstGetLastPinTimerTask(pin, &task)) {
|
||||
// no timer - just start the pulse now!
|
||||
jshPinOutput(pin, pulsePolarity);
|
||||
task.time = jshGetSystemTime();
|
||||
}
|
||||
// Now set the end of the pulse to happen on a timer
|
||||
jstPinOutputAtTime(task.time + jshGetTimeFromMilliseconds(pulseTime), &pin, 1, !pulsePolarity);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/// Can the given pin be watched? it may not be possible because of conflicts
|
||||
bool jshCanWatch(Pin pin){
|
||||
if (jshIsPinValid(pin)) {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user