Skip to content

Commit 43943b5

Browse files
committed
Timers now have unique IDs (#1444)
Added `require("timer")` to access timers, removed `E.dumpTimers` and `Pin.writeAtTime` (fix #2586) Added ability to execute JS from an a timer with `require("timer").add({type:"EXEC",...)`
1 parent ebb469b commit 43943b5

24 files changed

+717
-362
lines changed

ChangeLog

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,9 @@
22
Bangle.js: Updated built-in Layout.js with some minor fixes
33
STM32: Ensure setDeepSleep(1) will only sleep if there are no active PWM outputs
44
Pin.getInfo().negated now set if pin negated in firmware
5+
Timers now have unique IDs (#1444)
6+
Added `require("timer")` to access timers, removed `E.dumpTimers` and `Pin.writeAtTime` (fix #2586)
7+
Added ability to execute JS from an a timer with `require("timer").add({type:"EXEC",...)`
58
Bangle.js: Add Bangle.setOptions({stepCounterDisabled:bool}) to disable the step counter
69
Date: fix parsing of ISO8601 timezones (+HHMM worked, but +HH:MM and +HH added) (fix #2669)
710

Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -270,6 +270,7 @@ src/jswrap_json.c \
270270
src/jswrap_number.c \
271271
src/jswrap_object.c \
272272
src/jswrap_regexp.c \
273+
src/jswrap_timer.c \
273274
src/jswrap_string.c \
274275
src/jswrap_modules.c \
275276
src/jswrap_math.c

boards/BANGLEJS.blocklist

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,8 @@
11
[
22
{"class":"OneWire","name":"*"},
33
{"class":"SPI","name":"send4bit"},
4-
{"class":"E","name":"dumpTimers"},
54
{"class":"E","name":"enableWatchdog"},
65
{"class":"E","name":"getClock"},
76
{"class":"E","name":"setBootCode"},
8-
{"class":"Pin","name":"writeAtTime"}
7+
{"class":"timer","name":"*"}
98
]

src/jsdevices.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -470,6 +470,11 @@ bool CALLED_FROM_INTERRUPT jshPushEvent(IOEventFlags evt, uint8_t *data, unsigne
470470
return true;
471471
}
472472

473+
/// Push a Custom IO event into the ioBuffer (designed to be called from IRQ), returns true on success, Calls jshHadEvent();
474+
bool CALLED_FROM_INTERRUPT jshPushCustomEvent(IOCustomEventFlags customFlags) {
475+
jshPushEvent(EV_CUSTOM, (uint8_t*)&customFlags, sizeof(customFlags));
476+
}
477+
473478
/// Try and handle events in the IRQ itself. true if handled and shouldn't go in queue
474479
static bool jshPushIOCharEventsHandler(IOEventFlags channel, char *data, unsigned int count) {
475480
// Check for a CTRL+C

src/jsdevices.h

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,8 @@ typedef enum {
8787
#ifdef BLUETOOTH
8888
EV_BLUETOOTH_PENDING, // Tasks that came from the Bluetooth Stack in an IRQ
8989
#endif
90-
EV_CUSTOM, ///< Custom event (See IOCustomEventFlags)
90+
EV_RUN_INTERRUPT_JS, ///< Run some JavaScript code. See EXEC_RUN_INTERRUPT_JS. data is JsVarRef of code to run
91+
EV_CUSTOM, ///< Custom event (First byte is IOCustomEventFlags to determine the event type)
9192
#ifdef BANGLEJS
9293
EV_BANGLEJS, // sent whenever Bangle.js-specific data needs to be queued
9394
#endif
@@ -131,10 +132,13 @@ typedef enum {
131132
/** Event types for EV_CUSTOM */
132133
typedef enum {
133134
EVC_NONE,
135+
EVC_TIMER_FINISHED,
136+
EVC_TIMER_BUFFER_FLIP,
134137
#ifdef NRF52_SERIES
135138
EVC_LPCOMP, // jswrap_espruino: E.setComparator / E.on("comparator" event
136139
#endif
137140
EVC_TYPE_MASK = 255,
141+
EVC_DATA_SHIFT = 8,
138142
EVC_DATA_LPCOMP_UP = 256
139143
} PACKED_FLAGS IOCustomEventFlags;
140144

@@ -185,6 +189,8 @@ typedef enum {
185189

186190
/// Push an IO event (max IOEVENT_MAX_LEN) into the ioBuffer (designed to be called from IRQ), returns true on success, Calls jshHadEvent();
187191
bool CALLED_FROM_INTERRUPT jshPushEvent(IOEventFlags evt, uint8_t *data, unsigned int length);
192+
/// Push a Custom IO event into the ioBuffer (designed to be called from IRQ), returns true on success, Calls jshHadEvent();
193+
bool CALLED_FROM_INTERRUPT jshPushCustomEvent(IOCustomEventFlags customFlags);
188194
/// Add this IO event to the IO event queue. Calls jshHadEvent();
189195
void jshPushIOEvent(IOEventFlags channel, JsSysTime time);
190196
/// Signal an IO watch event as having happened. Calls jshHadEvent();
@@ -196,7 +202,7 @@ void jshPushIOCharEvents(IOEventFlags channel, char *data, unsigned int count);
196202

197203
/// pop an IO event, returns EV_NONE on failure. data must be IOEVENT_MAX_LEN bytes
198204
IOEventFlags jshPopIOEvent(uint8_t *data, unsigned int *length);
199-
// pop an IO event of type eventType, returns true on success. data must be IOEVENT_MAX_LEN bytes
205+
// pop an IO event of type eventType, returns event type on success,EV_NONE on failure. data must be IOEVENT_MAX_LEN bytes
200206
IOEventFlags jshPopIOEventOfType(IOEventFlags eventType, uint8_t *data, unsigned int *length);
201207
/// Do we have any events pending? Will jshPopIOEvent return true?
202208
bool jshHasEvents();

src/jsinteractive.c

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2204,6 +2204,20 @@ void jsiHandleIOEventForConsole(uint8_t *eventData, int eventLen) {
22042204
jsiSetBusy(BUSY_INTERACTIVE, false);
22052205
}
22062206

2207+
/** This is called if a EV_RUN_INTERRUPT_JS is received, or when a EXEC_RUN_INTERRUPT_JS is set.
2208+
It executes JavaScript code that was pushed to the queue by a require("timer").add({type:"EXEC", fn:myFunction... */
2209+
static void jsiOnRunInterruptJSEvent(const uint8_t *eventData, unsigned int eventLen) {
2210+
for (unsigned int i=0;i<eventLen-1;i+=2) {
2211+
JsVarRef codeRef = *(JsVarRef *)&eventData[i];
2212+
if (codeRef) {
2213+
JsVar *code = jsvLock(codeRef);
2214+
if (!jsvIsFunction(code)) return; // invalid code - maybe things got moved?
2215+
jsvUnLock(jspExecuteFunction(code, execInfo.root, 0, NULL));
2216+
jsvUnLock(code);
2217+
}
2218+
}
2219+
}
2220+
22072221
void jsiIdle() {
22082222
// This is how many times we have been here and not done anything.
22092223
// It will be zeroed if we do stuff later
@@ -2248,7 +2262,10 @@ void jsiIdle() {
22482262
}
22492263
jsvUnLock(usartClass);
22502264
#endif
2265+
} else if (eventType == EV_RUN_INTERRUPT_JS) {
2266+
jsiOnRunInterruptJSEvent(eventData, eventLen);
22512267
} else if (eventType == EV_CUSTOM) {
2268+
jstOnCustomEvent(eventFlags, eventData, eventLen);
22522269
jswOnCustomEvent(eventFlags, eventData, eventLen);
22532270
#ifdef BLUETOOTH
22542271
} else if (eventType == EV_BLUETOOTH_PENDING) {
@@ -3000,3 +3017,13 @@ void jsiDebuggerLine(JsVar *line) {
30003017
jslSetLex(oldLex);
30013018
}
30023019
#endif // USE_DEBUGGER
3020+
3021+
/** This is called from the parser if EXEC_RUN_INTERRUPT_JS is set.
3022+
It executes JavaScript code that was pushed to the queue by require("timer").add({type:"EXEC", fn:myFunction... */
3023+
void jsiRunInterruptingJS() {
3024+
uint8_t data[8];
3025+
memset(data, 0, sizeof(data));
3026+
if (jshPopIOEventOfType(EV_RUN_INTERRUPT_JS, data, sizeof(data)))
3027+
jsiOnRunInterruptJSEvent(data, sizeof(data));
3028+
}
3029+

src/jsinteractive.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -201,5 +201,8 @@ extern void jsiTimersChanged(); // Flag timers changed so we can skip out of the
201201
extern void jsiDebuggerLoop(); ///< Enter the debugger loop
202202
#endif
203203

204+
/** This is called from the parser if EXEC_RUN_INTERRUPT_JS is set.
205+
It executes JavaScript code that was pushed to the queue by require("timer").add({type:"EXEC", fn:myFunction... */
206+
void jsiRunInterruptingJS();
204207

205208
#endif /* JSINTERACTIVE_H_ */

src/jsparse.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2959,6 +2959,10 @@ NO_INLINE JsVar *jspeStatement() {
29592959
jsiDebuggerLoop();
29602960
}
29612961
#endif
2962+
if (execInfo.execute&EXEC_RUN_INTERRUPT_JS) {
2963+
execInfo.execute&=~EXEC_RUN_INTERRUPT_JS;
2964+
jsiRunInterruptingJS();
2965+
}
29622966
if (lex->tk==LEX_ID ||
29632967
lex->tk==LEX_INT ||
29642968
lex->tk==LEX_FLOAT ||

src/jsparse.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,7 @@ typedef enum {
9898
EXEC_INTERRUPTED = 16, ///< true if execution has been interrupted
9999
EXEC_EXCEPTION = 32, ///< we had an exception, so don't execute until we hit a try/catch block
100100
EXEC_ERROR = 64,
101-
// 128 is free now
101+
EXEC_RUN_INTERRUPT_JS = 128, ///< when set, we should stop our execution to run some JavaScript code (used for immediate timers)
102102

103103
EXEC_FOR_INIT = 256, ///< when in for initialiser parsing - hack to avoid getting confused about multiple use for IN
104104
EXEC_IN_LOOP = 512, ///< when in a loop, set this - we can then block break/continue outside it

0 commit comments

Comments
 (0)