/
helpers.cpp
90 lines (78 loc) · 2.89 KB
/
helpers.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
#include "helpers.h"
#include <ion.h>
#include "port.h"
extern "C" {
#include "mphalport.h"
}
bool micropython_port_vm_hook_loop() {
/* This function is called very frequently by the MicroPython engine. We grab
* this opportunity to interrupt execution and/or refresh the display on
* platforms that need it. */
/* Doing too many things here slows down Python execution quite a lot. So we
* only do things once in a while and return as soon as possible otherwise. */
static uint64_t t = Ion::Timing::millis();
constexpr static uint64_t delay = 100;
uint64_t t2 = Ion::Timing::millis();
if (t2 - t < delay) {
return false;
}
t = t2;
micropython_port_vm_hook_refresh_print();
// Check if the user asked for an interruption from the keyboard
return micropython_port_interrupt_if_needed();
}
void micropython_port_vm_hook_refresh_print() {
assert(MicroPython::ExecutionEnvironment::currentExecutionEnvironment() !=
nullptr);
MicroPython::ExecutionEnvironment::currentExecutionEnvironment()
->refreshPrintOutput();
}
bool micropython_port_interruptible_msleep(int32_t delay) {
static uint64_t lastRun = 0;
assert(delay >= 0);
constexpr int32_t miniumDelayBetweenInterruptions = 25;
constexpr int32_t interruptionCheckDelay = 100;
const int32_t numberOfInterruptionChecks = delay / interruptionCheckDelay;
int32_t remainingDelay =
delay - numberOfInterruptionChecks * interruptionCheckDelay;
int32_t currentRemainingInterruptionChecks = numberOfInterruptionChecks;
do {
int32_t timeToSleep =
currentRemainingInterruptionChecks == numberOfInterruptionChecks
? remainingDelay
: interruptionCheckDelay;
/* On simulators the interruption check also refreshes the screen and takes
* about 15ms. We make sure not to execute it too often to ensure a
* consistent speed between platforms. */
uint64_t run = Ion::Timing::millis();
if (run - lastRun > miniumDelayBetweenInterruptions) {
if (micropython_port_interrupt_if_needed()) {
return true;
}
lastRun = run;
/* Remove from timeToSleep the time taken by the check */
timeToSleep -= Ion::Timing::millis() - run;
}
if (timeToSleep > 0) {
Ion::Timing::msleep(timeToSleep);
}
currentRemainingInterruptionChecks--;
} while (currentRemainingInterruptionChecks >= 0);
return false;
}
bool micropython_port_interrupt_if_needed() {
Ion::Keyboard::State state(0);
Ion::Keyboard::Key interruptKey =
static_cast<Ion::Keyboard::Key>(mp_interrupt_char);
bool interruption = false;
while (state != Ion::Keyboard::State(-1)) {
interruption = state.keyDown(interruptKey) ? true : interruption;
state = Ion::Keyboard::scanForInterruptionAndPopState();
};
if (interruption) {
mp_keyboard_interrupt();
return true;
}
return false;
}
int micropython_port_random() { return Ion::random(); }