Skip to content

Commit ac49c47

Browse files
committed
Fix stdio line input wait on channel 2
1 parent 8f64191 commit ac49c47

3 files changed

Lines changed: 68 additions & 1 deletion

File tree

cc/examples/name.c

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
#include <stdio.h>
2+
3+
int main(void)
4+
{
5+
char name[32];
6+
7+
printf("Ciao! Come ti chiami? ");
8+
scanf("%s", name);
9+
printf("Piacere, %s Io sono il GE-120!\n", name);
10+
printf("E` ora possibile spegnere il computer\n");
11+
12+
return 0;
13+
}

printer.c

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -245,7 +245,10 @@ static int printer_on_clock(struct ge *ge, void *opaque)
245245
* — the RC00=0 path below (stall debounce vs the card reader's b8 gap)
246246
* cannot, because RC00 never dropped. Gated on RC00 so a reader inter-byte
247247
* gap (RC00=0) and funktionalcpu's RC00=0 control PER are left to it. */
248-
int control_ready = ge->RC00 && !write_ready && !input_ready;
248+
int control_ready = ge->RC00 &&
249+
cmd != KBD_CMD_LINE &&
250+
cmd != KBD_CMD_CHAR &&
251+
!write_ready;
249252
if (write_ready || input_ready || control_ready) {
250253
ge->PUC2 = 1; /* channel-2 unit ready -> DU97 completes the PER */
251254
ge->RC00 = 1; /* CPU-active request -> rSO=b8 routed into rSA */

tests/printer.c

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
#include "../binimage.h"
3232
#include "../opcodes.h"
3333
#include "../log.h"
34+
#include "../gecode.h"
3435

3536
#include <stdio.h>
3637

@@ -324,3 +325,53 @@ UTEST(printer, output_per_prints_and_halts_when_polled)
324325

325326
ge_deinit(&g);
326327
}
328+
329+
UTEST(printer, input_line_waits_for_keyboard_and_fills_buffer)
330+
{
331+
struct ge g;
332+
ge_init(&g);
333+
334+
/* PER connector-2, order block @ 0x10: read a line into 0x0200. */
335+
g.mem[0x00] = PER_OPCODE; g.mem[0x01] = 0x80; g.mem[0x02] = 0x00; g.mem[0x03] = 0x10;
336+
g.mem[0x10] = 0x00; g.mem[0x11] = 0x40; /* z, cmd=KBD_CMD_LINE */
337+
g.mem[0x12] = 0x00; g.mem[0x13] = 0x20; /* len = 32 */
338+
g.mem[0x14] = 0x02; g.mem[0x15] = 0x00; /* buf = 0x0200 */
339+
340+
ge_clear(&g);
341+
printer_register(&g);
342+
ge_start(&g);
343+
344+
/* Without a completed line queued, the PER must remain pending. */
345+
for (int i = 0; i < 40; i++) {
346+
if (ge_run_cycle(&g))
347+
break;
348+
}
349+
ASSERT_EQ(g.mem[0x30], 0x00);
350+
ASSERT_EQ(g.mem[0x31], 0x00);
351+
ASSERT_EQ(g.mem[0x200], 0x00);
352+
353+
printer_feed_key(&g, 'C');
354+
printer_feed_key(&g, 'I');
355+
printer_feed_key(&g, 'A');
356+
printer_feed_key(&g, 'O');
357+
printer_feed_key(&g, '\r');
358+
359+
for (int i = 0; i < 80; i++) {
360+
if (ge_run_cycle(&g))
361+
break;
362+
if (g.mem[0x31] == 0x01)
363+
break;
364+
}
365+
366+
ASSERT_EQ(g.mem[0x30], 0x00);
367+
ASSERT_EQ(g.mem[0x31], 0x01);
368+
ASSERT_EQ(g.mem[0x32], 0x00);
369+
ASSERT_EQ(g.mem[0x33], 0x04);
370+
ASSERT_EQ(g.mem[0x200], ge_code('C'));
371+
ASSERT_EQ(g.mem[0x201], ge_code('I'));
372+
ASSERT_EQ(g.mem[0x202], ge_code('A'));
373+
ASSERT_EQ(g.mem[0x203], ge_code('O'));
374+
ASSERT_EQ(g.mem[0x204], 0x00); /* trailing NUL */
375+
376+
ge_deinit(&g);
377+
}

0 commit comments

Comments
 (0)