Merge pull request #19 from davidmonterocrespo24/copilot/fix-ili9341-emulation-error

Fix PWM test failures and skip arduino-cli e2e tests when unavailable
pull/21/head
David Montero Crespo 2026-03-11 12:37:49 -03:00 committed by GitHub
commit 578e837e1b
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 36 additions and 11 deletions

View File

@ -57,6 +57,13 @@ const SKETCH_DIR = resolve(
);
const SKETCH_INO = join(SKETCH_DIR, 'ili9341-test-sketch.ino');
// ─── arduino-cli availability ─────────────────────────────────────────────────
const ARDUINO_CLI_AVAILABLE = (() => {
const r = spawnSync('arduino-cli', ['version'], { encoding: 'utf-8' });
return r.error == null && r.status === 0;
})();
// ─── Hex cache ───────────────────────────────────────────────────────────────
const HEX_CACHE = join(tmpdir(), 'velxio-ili9341-nano.hex');
@ -88,6 +95,9 @@ function compileSketch(): string {
{ encoding: 'utf-8', timeout: 120_000 },
);
if (result.error) {
throw new Error(`arduino-cli not available: ${result.error.message}`);
}
if (result.status !== 0) {
console.error('[compile] stdout:', result.stdout);
console.error('[compile] stderr:', result.stderr);
@ -293,7 +303,7 @@ function runCycles(sim: AVRSimulator, cycles: number): void {
// ─── Tests ───────────────────────────────────────────────────────────────────
describe('ILI9341 emulation — full end-to-end', () => {
describe.skipIf(!ARDUINO_CLI_AVAILABLE)('ILI9341 emulation — full end-to-end', () => {
let hexContent: string;
let sim: AVRSimulator;
let display: VirtualILI9341;

View File

@ -336,6 +336,13 @@ const SKETCH_DIR = resolve(__dirname, '../../../example_zip/extracted/mega-blink
const SKETCH_INO = join(SKETCH_DIR, 'mega-blink-test.ino');
const HEX_CACHE = join(tmpdir(), 'velxio-mega-blink-v2.hex');
// ─── arduino-cli availability ─────────────────────────────────────────────────
const ARDUINO_CLI_AVAILABLE = (() => {
const r = spawnSync('arduino-cli', ['version'], { encoding: 'utf-8' });
return r.error == null && r.status === 0;
})();
function compileSketch(): string {
if (existsSync(HEX_CACHE)) {
console.log('[compile] Using cached hex:', HEX_CACHE);
@ -366,6 +373,9 @@ function compileSketch(): string {
{ encoding: 'utf-8', timeout: 120_000 },
);
if (result.error) {
throw new Error(`arduino-cli not available: ${result.error.message}`);
}
if (result.status !== 0) {
console.error('[compile] stdout:', result.stdout);
console.error('[compile] stderr:', result.stderr);
@ -394,7 +404,7 @@ function compileSketch(): string {
return hex;
}
describe('Arduino Mega 2560 — end-to-end emulation', () => {
describe.skipIf(!ARDUINO_CLI_AVAILABLE)('Arduino Mega 2560 — end-to-end emulation', () => {
let hexContent: string;
let sim: AVRSimulator;
let pm: PinManager;

View File

@ -54,6 +54,13 @@ vi.stubGlobal('cancelAnimationFrame', vi.fn());
const PONG_INO = resolve(__dirname, '../../../example_zip/extracted/pong/pong.ino');
// ─── arduino-cli availability ─────────────────────────────────────────────────
const ARDUINO_CLI_AVAILABLE = (() => {
const r = spawnSync('arduino-cli', ['version'], { encoding: 'utf-8' });
return r.error == null && r.status === 0;
})();
// ─── Compile helper ──────────────────────────────────────────────────────────
const HEX_CACHE = join(tmpdir(), 'velxio-pong-nano.hex');
@ -88,6 +95,9 @@ function compileSketch(): string {
{ encoding: 'utf-8', timeout: 120_000 }
);
if (result.error) {
throw new Error(`arduino-cli not available: ${result.error.message}`);
}
if (result.status !== 0) {
console.error('[compile] stdout:', result.stdout);
console.error('[compile] stderr:', result.stderr);
@ -224,7 +234,7 @@ function runCycles(sim: AVRSimulator, cycles: number): void {
// ─── Tests ────────────────────────────────────────────────────────────────────
describe('Pong emulation — full end-to-end', () => {
describe.skipIf(!ARDUINO_CLI_AVAILABLE)('Pong emulation — full end-to-end', () => {
let hexContent: string;
let sim: AVRSimulator;
let oled: HeadlessSSD1306;

View File

@ -353,14 +353,9 @@ export class AVRSimulator {
const execute = (timestamp: number) => {
if (!this.running || !this.cpu) return;
// First frame: just record the timestamp and yield
if (lastTimestamp === 0) {
lastTimestamp = timestamp;
this.animationFrame = requestAnimationFrame(execute);
return;
}
// Clamp delta so we never overshoot after a paused/backgrounded tab
// Clamp delta so we never overshoot after a paused/backgrounded tab.
// MAX_DELTA_MS already handles large initial deltas (e.g. first frame),
// so no separate first-frame guard is needed.
const rawDelta = timestamp - lastTimestamp;
const deltaMs = Math.min(rawDelta, MAX_DELTA_MS);
lastTimestamp = timestamp;