GE-115 Emulator
An Emulator of the General Electrics GE-115 computer
cardreader.c
Go to the documentation of this file.
1/*
2 * cardreader.c - Connector-2 punch-card-reader peripheral for the GE-120 emulator.
3 *
4 * Feeds a .cap punch-card deck into the CPU via the existing integrated-reader
5 * handshake (reader_setup_to_send / reader_clear_sending), mirroring the
6 * manual cadence demonstrated in tests/initial-load.c.
7 *
8 * This is a behavioural twin of the Pico reader that replaces the real machine's
9 * CRZ transport (rpi-pico-card-reader/src/feeder.c, wire_tx.c). The same state
10 * machine, the same LUPOB predicate, the same trigger, the same loader-card
11 * rule -- so a deck that boots here boots on the iron, and a trace from one can
12 * be read against a trace from the other.
13 *
14 * The wire order, as measured on the bench in July 2026:
15 *
16 * 1. The CPU puts an order byte on RE00-07 and strobes TU00N (CE10, states
17 * ca and ab). The reader latches it. NOTHING is strobed back.
18 * 2. The CPU raises TU03N (CE09, state b8 TI10). THAT is what starts the card
19 * moving. Presenting on the command instead hands the card to a channel
20 * that has not armed its transfer yet, and the card is lost.
21 * 3. Columns go out one presentation per input cycle, each with an LU08N
22 * strobe; the last one carries FININ.
23 * 4. FININ, and the data that rode with it, STAY on the pins until the next
24 * read command, the next TU03N, or a timeout.
25 *
26 * Within step 3 the per-character cadence is the one tests/initial-load.c
27 * documents. on_clock runs once per machine cycle at TO00:
28 *
29 * reader_setup_to_send(...) -- before the b8/b9 cycle
30 * [ge_run_cycle b8/b9] -- machine reads the nibble into mem[]
31 * reader_clear_sending(...) -- before the b1 cycle
32 * [ge_run_cycle b1] -- machine packs the nibble
33 *
34 * The IPL reads exactly ONE card: 80 columns nibble-packed into 40 bytes at
35 * address 0, then executed. Every card after that is pulled by a PER read the
36 * loaded program issues itself -- which arrives here as another command, another
37 * feed, another burst. The machine does not read decks; programs do.
38 */
39
40#include "cardreader.h"
41
42#include <stdlib.h>
43#include <stdio.h>
44
45#include "cap.h"
46#include "reader.h"
47#include "log.h"
48
49/* -------------------------------------------------------------------------
50 * Private state
51 * ------------------------------------------------------------------------- */
52
53/*
54 * Feeding state machine, the same one the Pico reader runs
55 * (rpi-pico-card-reader/src/feeder.c, enum feeder_state).
56 *
57 * ARMED_WAIT a card is under the read station; nothing is moving. A read
58 * command latches (cmd_armed) but strobes nothing.
59 * PRESENTING the CPU's TU03N feed arrived and the card is being read out,
60 * one presentation per input cycle.
61 * CARD_DONE the last column has gone by with FININ riding it. FININ is
62 * still standing, and so is the last nibble. It is released by
63 * the next read command, by a TU03N, or by a timeout.
64 * DONE the deck ran out: FIDEN active, reader busy.
65 * ERROR LUREN / LUSEN: nothing is delivered.
66 */
74
75/*
76 * Fallbacks, in elementary cycles (one cycle = 4 us on a 120).
77 *
78 * CR_CMD_TIMEOUT is the Pico's D: the longest a latched read command waits for
79 * the feed before presenting anyway (50 ms there). It should never fire against
80 * a healthy machine -- CE09 raises TU03N in state b8, a handful of cycles after
81 * the command -- so if it does, something upstream stopped feeding.
82 *
83 * CR_FININ_TIMEOUT is the Pico's finin_to_us (1 ms): how long FININ may stand
84 * before the reader drops it unasked.
85 */
86#define CR_CMD_TIMEOUT_CYCLES 12500 /* 50 ms */
87#define CR_FININ_TIMEOUT_CYCLES 250 /* 1 ms */
88
90 struct cap_deck *deck;
92
93 /* The loader card (the first card fed) is read in `mode` (TC_HEX for the
94 * "130 CPU FUNCTIONAL TEST" deck). After the loader sets "by-pass", the
95 * program cards are read in binary, so every card after the loader card
96 * is fed as TC_BINARY. */
98
99 int card_idx; /* index of the current card in the deck */
100 int col_idx; /* index of the current column within the current card */
101
102 /* pre-computed index of last non-empty card and its last column */
105
107
108 /* A presentation is on the lines and the machine has not consumed it yet.
109 * The next on_clock retires it; the one after presents again. That gap is
110 * the b1 pack cycle. */
112
113 /* Set to 1 when the end-of-card presentation (the one carrying FININ) was
114 * put on the lines. */
116
117 /* A read command is latched and waiting for the CPU's TU03N feed. Nothing
118 * is strobed until then: the wire order is command, feed, strobes, and
119 * presenting on the command hands the card to a channel that is not armed
120 * yet. cmd_wait counts down to the autofeed fallback. */
123
124 /* Cycles left before a standing FININ is released unasked. */
126
127 /* Diagnostics: feeds honoured, and feeds we had to invent. */
128 unsigned n_feeds;
129 unsigned n_autofeeds;
130
131 /* Packed / self-loading mode (cardreader_register_packed). The channel-1
132 * input-transfer microcode always packs TWO presented nibbles into one
133 * memory byte. A self-loading SMAC .cap holds the program as full COLBIN
134 * bytes (1 col -> 1 byte), so to land each byte intact we present it as a
135 * hi-then-lo nibble pair; the packer rebuilds the original byte. (This is
136 * also how the real machine reads: the IPL packs the hex loader card, and
137 * after "set by-pass" each binary column delivers a full byte — equivalent
138 * to two packed nibbles here.) `half` tracks which nibble is pending. */
139 int pack;
140 int half; /* 0 = high nibble pending, 1 = low nibble pending */
142
143 /* the ge_peri node we allocated (kept for potential future use) */
144 struct ge_peri peri;
145};
146
147/*
148 * Find the bootstrap loader card in a mixed deck.
149 *
150 * This is the SHARED rule -- the Pico reader runs the identical one
151 * (rpi-pico-card-reader/src/deck.c deck_find_loader_card), so a deck that
152 * bootstraps here bootstraps on the iron:
153 *
154 * marker a row-8 punch in column 3, i.e. cols[2] == 0x0100 exactly
155 * window card indices 0..4 inclusive, first match wins
156 *
157 * Card 0 has to be in the window. A captured box deck leads with a title card
158 * and puts the loader at 1 or later, but a deck synthesized by gasm --boot /
159 * --bootge leads with the loader itself; a window starting at 1 feeds a body
160 * card to the IPL, which then nibble-packs 40 bytes of program payload to
161 * address 0 and executes them.
162 *
163 * Returns the card index, or -1 if no card in the window carries the marker.
164 * The TC_HEX decode of the head is checked too, but only to WARN: the marker is
165 * what selects, on both sides of the wire.
166 */
168{
169 int ncards = cap_num_cards(deck);
170 int limit = ncards < 5 ? ncards : 5;
171
172 for (int i = 0; i < limit; i++) {
173 int ncols = cap_card_ncols(deck, i);
174 const uint16_t *cols;
175 uint8_t b[6];
176
177 if (ncols < 12)
178 continue;
179
180 cols = cap_card_columns(deck, i);
181 if (!cols)
182 continue;
183
184 if (cols[2] != 0x0100)
185 continue;
186
187 for (int j = 0; j < 12; j++) {
188 uint8_t nib = transcode_column(cols[j], TC_HEX) & 0x0f;
189 if ((j & 1) == 0)
190 b[j >> 1] = (uint8_t)(nib << 4);
191 else
192 b[j >> 1] |= nib;
193 }
194
195 /* A real bootstrap card opens with repeated `PER 0x80` orders. If this
196 * one does not, it is still the card the machine will read -- say so
197 * rather than quietly picking a different one. */
198 if (!(b[0] == 0x9e && b[1] == 0x80 &&
199 b[2] == 0x00 && b[4] == 0x9e && b[5] == 0x80))
201 "cardreader: card %d carries the row-8 loader marker but "
202 "decodes to %02x %02x %02x .. %02x %02x, not the usual "
203 "9E 80 00 .. 9E 80\n",
204 i, b[0], b[1], b[2], b[4], b[5]);
205
206 return i;
207 }
208
209 return -1;
210}
211
212/* -------------------------------------------------------------------------
213 * Which mode is this card read in
214 * ------------------------------------------------------------------------- */
215
216/*
217 * The effective read mode for the card currently under the station. Same rule
218 * as the Pico's effective_mode() (src/feeder.c):
219 *
220 * - the loader card is always read in the mode the deck was registered with
221 * (TC_HEX for a real bootstrap card). The CPU's mode-select only offers
222 * normal and binary, and either would corrupt an A-F hex nibble, so it must
223 * not override this one card.
224 * - after the loader, program cards are by-pass / column-binary. The loader's
225 * own "set by-pass" is what selects that on the iron; which RE byte it
226 * actually sends is still open (loader.s reads it as 0x40 under Z=0x80,
227 * gemu latches by-pass on 0x20), so both sides force COLBIN here rather
228 * than depend on the answer.
229 * - otherwise: whatever the CPU last latched via COCON, or raw binary.
230 */
232 struct cardreader_ctx *ctx)
233{
234 if (ctx->pack)
235 return ctx->mode;
236 if (ctx->card_idx == ctx->loader_card)
237 return ctx->mode;
238 if (ctx->post_loader_pack)
239 return TC_COLBIN;
242 return TC_BINARY;
243}
244
245/* Whether this card's columns go out as hi/lo nibble pairs (a whole byte per
246 * column) or one presentation per column (a hex nibble). */
247static int cr_pack_now(struct cardreader_ctx *ctx, enum transcode_mode m)
248{
249 (void)m;
250 return ctx->pack || (ctx->post_loader_pack &&
251 ctx->card_idx != ctx->loader_card);
252}
253
254/* -------------------------------------------------------------------------
255 * Peripheral callbacks
256 * ------------------------------------------------------------------------- */
257
258/* Move the cursor to the next card, or run out of deck. */
259static void cr_next_card(struct cardreader_ctx *ctx)
260{
261 ctx->col_idx = 0;
262 ctx->half = 0;
263 ctx->card_idx++;
264 while (ctx->card_idx < cap_num_cards(ctx->deck) &&
265 cap_card_ncols(ctx->deck, ctx->card_idx) == 0)
266 ctx->card_idx++;
267
268 if (ctx->card_idx >= cap_num_cards(ctx->deck)) {
269 ctx->state = CR_DONE;
270 ge_log(LOG_READER, "cardreader: deck exhausted\n");
271 } else {
272 ctx->state = CR_ARMED_WAIT;
273 }
274}
275
276/*
277 * Drop FININ and the data that rode with it.
278 *
279 * On the wire, FININ is asserted with the last presentation of a card and STAYS
280 * asserted after the strobe -- as does the last nibble on LU00-07. It comes down
281 * on one of three things: the next read command, a TU03N, or a timeout. This is
282 * the release; note that it deliberately does not touch LUPOB (see
283 * cr_lupob_update and its callers for why the fronts land where they do).
284 */
285static void cr_finin_release(struct ge *ge, struct cardreader_ctx *ctx)
286{
289 ctx->finin_wait = 0;
290}
291
292/*
293 * LUPOB / LUPOR, one predicate, exactly the Pico's (src/feeder.c lupob_update).
294 *
295 * Ready means: a deck is in the machine, nothing is being presented, no command
296 * is waiting for its feed, no FININ is standing, and we are parked either
297 * before a card or after one. Everything else -- presenting, error, deck
298 * exhausted, no deck at all -- is busy.
299 *
300 * The bench reading that settles the polarity: on the wire LOW is ready and
301 * HIGH is busy, so an unpowered or unarmed reader reads busy. gemu's internal
302 * LUPO1 ("reader free") is the logical sense, i.e. the inverse of the wire.
303 *
304 * Consequence worth knowing when reading a trace: in the steady loader loop
305 * there is NO ready front between cards. The next read command releases FININ
306 * and latches cmd_armed before this runs, so the reader goes straight from one
307 * card's presentation to the next card's wait without ever reporting ready.
308 */
309static void cr_lupob_update(struct ge *ge, struct cardreader_ctx *ctx)
310{
312
313 r->lupor = (ctx->deck != NULL) &&
314 !ctx->cmd_armed &&
315 !r->fini &&
316 (ctx->state == CR_ARMED_WAIT || ctx->state == CR_CARD_DONE);
317}
318
319/* The feed has arrived (or we gave up waiting for it): start reading out the
320 * card under the station. */
321static void cr_trigger_present(struct ge *ge, struct cardreader_ctx *ctx)
322{
323 enum transcode_mode m;
324
325 ctx->cmd_armed = 0;
326 ctx->cmd_wait = 0;
327
328 if (ctx->state == CR_CARD_DONE)
329 cr_next_card(ctx);
330 if (ctx->state != CR_ARMED_WAIT)
331 return; /* deck exhausted, or already presenting */
332
333 /* POM01 is re-evaluated per card from the mode this card will be read in:
334 * active for a raw/by-pass read, inactive for the transcoded hex loader. */
335 m = cr_effective_mode(ge, ctx);
336 ge->integrated_reader.pom01 = (m == TC_BINARY || m == TC_COLBIN);
337
338 ctx->state = CR_PRESENTING;
339 ge_log(LOG_READER, "cardreader: feed -> presenting card %d (mode %d)\n",
340 ctx->card_idx, (int)m);
341}
342
343/*
344 * on_clock: called at TO00, the first clock of every new machine cycle.
345 *
346 * The order of business here is the order the wire shows on the bench:
347 *
348 * 1. TU00N carries a read command -> latch it, drop any standing FININ.
349 * (reader.c does that half; what arrives here is cmd_pending.)
350 * 2. TU03N arrives (CE09, state b8) -> THIS is what starts the card moving.
351 * 3. presentations, one per input cycle, until the last column carries FININ.
352 * 4. FININ stands until the next command, the next TU03N, or the timeout.
353 *
354 * Within step 3 the cadence is the one tests/initial-load.c documents:
355 *
356 * [b9 cycle, lu08=1] machine reads the nibble
357 * on_clock: retire lu08 -> 0, and return
358 * [b1 cycle, lu08=0] machine packs the nibble
359 * on_clock: present lu08 -> 1
360 *
361 * so a presentation is never replaced in the same cycle it was consumed.
362 */
363static int cardreader_on_clock(struct ge *ge, void *opaque)
364{
365 struct cardreader_ctx *ctx = (struct cardreader_ctx *)opaque;
367 int feed;
368 int pack_now;
369
370 /* LESAB: a reader is on the connector. A strap, not a signal -- it is true
371 * for as long as this peripheral is registered. */
372 r->lesab = 1;
373
374 /* The CPU->reader lines are STROBES, and a strobe that is never taken down
375 * is a stuck pin: whoever reads the trace (or the Pico, sampling the same
376 * wires) sees a command clock that has been standing since the first order.
377 * Each one is read here as the previous cycle's pulse -- reader.c raises
378 * them from the CE commands late in the cycle (CE09/CE10 at TI10), this
379 * runs at TO00 of the next -- and dropped again.
380 *
381 * TU03N is the card feed and the one with a job to do; TU00N (command
382 * clock), COCON (mode-select clock) and REGEN (general clear) are latched
383 * on the reader side by reader.c / ge_clear the moment they arrive, so here
384 * they only have to stop standing. */
385 feed = r->tu03;
386 r->tu03 = 0;
387 r->tu00 = 0;
388 r->cocon = 0;
389 r->regen = 0;
390 if (feed)
391 ctx->n_feeds++;
392
393 /* LUSEN (out-of-service) / LUREN (error or card jam): the reader cannot
394 * deliver. Present nothing and report busy, so a read parks or completes in
395 * error rather than getting data. Both default 0. */
396 if (r->lusen || r->luren) {
397 ctx->state = CR_ERROR;
398 ctx->cmd_armed = 0;
399 r->cmd_pending = 0;
400 cr_lupob_update(ge, ctx);
401 return 0;
402 }
403 if (ctx->state == CR_ERROR)
404 ctx->state = (ctx->card_idx < cap_num_cards(ctx->deck))
406
407 /* Card reject (RE 0x48): this card leaves unread, and no transfer follows. */
408 if (r->cmd_reject) {
409 r->cmd_reject = 0;
410 cr_finin_release(ge, ctx);
411 if (ctx->state == CR_CARD_DONE || ctx->state == CR_ARMED_WAIT)
412 cr_next_card(ctx);
413 ge_log(LOG_READER, "cardreader: card reject -> card %d\n", ctx->card_idx);
414 }
415
416 if (ctx->state == CR_DONE) {
417 r->fiden = 1; /* FIDEN: end of sequence */
418 r->cmd_pending = 0;
419 ctx->cmd_armed = 0;
420 cr_lupob_update(ge, ctx);
421 return 0;
422 }
423
424 /* A read command latches; it does not strobe. FININ came down in reader.c,
425 * on the command itself, before anything here touches LUPOB. */
426 if (r->cmd_pending) {
427 r->cmd_pending = 0;
428 if (ctx->state == CR_ARMED_WAIT || ctx->state == CR_CARD_DONE) {
429 ctx->cmd_armed = 1;
431 ctx->finin_wait = 0;
432 }
433 /* A command arriving mid-presentation is dropped, as on the Pico. */
434 }
435
436 /* TU03N is the trigger. */
437 if (feed) {
438 if (ctx->cmd_armed) {
439 cr_finin_release(ge, ctx);
441 } else if (ctx->state == CR_CARD_DONE) {
442 /* A feed with nothing pending is the reader physically putting the
443 * finished card out and bringing the next one under the station. */
444 cr_finin_release(ge, ctx);
445 cr_next_card(ctx);
446 }
447 } else if (ctx->cmd_armed && ctx->cmd_wait > 0 && --ctx->cmd_wait == 0) {
448 ctx->n_autofeeds++;
450 "cardreader: no TU03N within %d cycles; presenting anyway "
451 "(autofeed %u)\n", CR_CMD_TIMEOUT_CYCLES, ctx->n_autofeeds);
452 cr_finin_release(ge, ctx);
454 }
455
456 /* A standing FININ that nobody came for. */
457 if (ctx->finin_wait > 0 && --ctx->finin_wait == 0) {
458 ge_log(LOG_READER, "cardreader: FININ held %d cycles; releasing\n",
460 cr_finin_release(ge, ctx);
461 }
462
463 if (ctx->state != CR_PRESENTING) {
464 cr_lupob_update(ge, ctx);
465 return 0;
466 }
467
468 /* Retire the previous presentation, and wait a cycle before the next: that
469 * gap is the machine's b1 pack cycle. */
470 if (ctx->awaiting_retire) {
471 ctx->awaiting_retire = 0;
472 reader_clear_sending(ge); /* lu08 down; FININ and data stay put */
473 if (ctx->end_of_card_presented) {
474 ctx->end_of_card_presented = 0;
475 ctx->state = CR_CARD_DONE;
477 }
478 cr_lupob_update(ge, ctx);
479 return 0;
480 }
481
482 /*
483 * Only present while the machine is in the channel-1 transfer phase. RASI
484 * is set at state ab, just before the input-wait loop; before that a
485 * presentation would be ignored and the column consumed for nothing.
486 */
487 if (!ge->RASI || r->lu08) {
488 cr_lupob_update(ge, ctx);
489 return 0;
490 }
491
492 {
493 int ncols = cap_card_ncols(ctx->deck, ctx->card_idx);
494 const uint16_t *cols = cap_card_columns(ctx->deck, ctx->card_idx);
495 enum transcode_mode m = cr_effective_mode(ge, ctx);
496 uint8_t byte;
497 uint8_t present;
498 int is_last_col;
499 int is_last;
500
501 if (ncols <= 0 || !cols || ctx->col_idx >= ncols) {
502 ctx->state = CR_DONE;
503 cr_lupob_update(ge, ctx);
504 return 0;
505 }
506
507 byte = transcode_column(cols[ctx->col_idx], m);
508 pack_now = cr_pack_now(ctx, m);
509 is_last_col = (ctx->col_idx == ncols - 1);
510
511 /*
512 * The channel-1 input transfer packs TWO presentations into one memory
513 * byte. A by-pass column carries a whole byte, so it goes out as a
514 * hi-then-lo nibble pair and the packer rebuilds it; a hex loader
515 * column is already one nibble and goes out whole. FININ rides the LOW
516 * nibble of the last column.
517 */
518 if (pack_now) {
519 present = (ctx->half == 0) ? (uint8_t)((byte >> 4) & 0x0f)
520 : (uint8_t)(byte & 0x0f);
521 is_last = (ctx->half == 1) && is_last_col;
522 } else {
523 present = byte;
524 is_last = is_last_col;
525 }
526
528 "cardreader: presenting card %d col %d half %d byte=0x%02x "
529 "val=0x%02x end=%d\n",
530 ctx->card_idx, ctx->col_idx, ctx->half, byte, present, is_last);
531
532 /* PICON: first column of a card. BI20: the low nibble of a packed
533 * binary column. Both are harness-side wires, not COCA pins. */
534 r->picon = (ctx->col_idx == 0);
535 r->bi20 = (pack_now && ctx->half == 1);
536
537 reader_setup_to_send(ge, present, is_last ? 1 : 0);
538 ctx->end_of_card_presented = is_last;
539 ctx->awaiting_retire = 1;
540
541 /* Advance the cursor. Within a packed column the low nibble follows
542 * without moving on; the card boundary is NOT crossed here -- the card
543 * stays under the station until a feed says otherwise. */
544 if (pack_now && ctx->half == 0) {
545 ctx->half = 1;
546 } else {
547 ctx->half = 0;
548 if (!is_last_col)
549 ctx->col_idx++;
550 }
551 }
552
553 cr_lupob_update(ge, ctx);
554 return 0;
555}
556
557static int cardreader_deinit(struct ge *ge, void *opaque)
558{
559 struct cardreader_ctx *ctx = (struct cardreader_ctx *)opaque;
560 if (ge) {
561 /* The unit leaves the connector, and every line it was holding goes
562 * with it. FININ especially: it STANDS after the last character of a
563 * card (cr_finin_release, and the bench says so), so a reader taken off
564 * with a finished deck leaves an end-of-record on the wire. The next
565 * unit to arrive would find the channel already ended and read nothing
566 * -- which is exactly what a rewound deck did: 00 -> 80 -> c8 and then
567 * parked in b8, the input wait, with FININ standing from the deck
568 * before it. */
576 }
577 if (ctx) {
578 cap_free(ctx->deck);
579 free(ctx);
580 }
581 return 0;
582}
583
584/* -------------------------------------------------------------------------
585 * Public API
586 * ------------------------------------------------------------------------- */
587
588static int cr_register(struct ge *ge, const char *cap_path,
589 enum transcode_mode mode, int first_card, int pack);
590
591/* The reader peripheral on this machine, found by its clock callback -- the
592 * peripheral list carries no unit type, and this is the one node that can be
593 * a card reader. NULL when nothing is on the connector. */
594static struct cardreader_ctx *cr_find(struct ge *ge)
595{
596 struct ge_peri *p;
597
598 for (p = ge ? ge->peri : NULL; p != NULL; p = p->next)
600 return (struct cardreader_ctx *)p->ctx;
601 return NULL;
602}
603
605{
606 struct cardreader_ctx *ctx = cr_find(ge);
607
608 if (!ctx || !ctx->deck)
609 return -1;
610 return cap_num_cards(ctx->deck);
611}
612
614{
615 struct cardreader_ctx *ctx = cr_find(ge);
616 int left = 0;
617
618 if (!ctx || !ctx->deck)
619 return -1;
620 if (ctx->state == CR_DONE)
621 return 0;
622 for (int i = ctx->card_idx; i < cap_num_cards(ctx->deck); i++)
623 if (cap_card_ncols(ctx->deck, i) > 0)
624 left++;
625 /* The card under the station has left the hopper: it is being read, or has
626 * been. Only a card still in the hopper counts. */
627 if (left > 0 && (ctx->state == CR_PRESENTING || ctx->state == CR_CARD_DONE))
628 left--;
629 return left;
630}
631
632int cardreader_register(struct ge *ge, const char *cap_path,
633 enum transcode_mode mode)
634{
635 return cr_register(ge, cap_path, mode, 0, 0);
636}
637
638int cardreader_register_from(struct ge *ge, const char *cap_path,
639 enum transcode_mode mode, int first_card)
640{
641 return cr_register(ge, cap_path, mode, first_card, 0);
642}
643
644/* Self-loading SMAC deck: feed every card's COLBIN bytes as hi/lo nibble pairs
645 * so the channel-1 packing transfer reconstructs the full bytes (1 col -> 1
646 * byte), letting the deck's own loader chain (PER reads + MVC relocation)
647 * assemble the program in memory. */
648int cardreader_register_packed(struct ge *ge, const char *cap_path,
649 enum transcode_mode mode)
650{
651 return cr_register(ge, cap_path, mode, 0, 1);
652}
653
654static int cr_register(struct ge *ge, const char *cap_path,
655 enum transcode_mode mode, int first_card, int pack)
656{
657 struct cap_deck *deck = cap_load(cap_path);
658 int auto_loader = -1;
659 if (!deck) {
660 fprintf(stderr, "cardreader: failed to load deck '%s'\n", cap_path);
661 return -1;
662 }
663
664 struct cardreader_ctx *ctx = calloc(1, sizeof(*ctx));
665 if (!ctx) {
666 cap_free(deck);
667 return -1;
668 }
669
670 ctx->deck = deck;
671 ctx->mode = mode;
672 ctx->pack = pack;
673 ctx->half = 0;
674 ctx->state = CR_ARMED_WAIT;
675
676 /* A plain `cardreader_register(..., TC_NORMAL)` on a real mixed deck should
677 * start from the Hollerith bootstrap loader, not from whichever control
678 * card happens to be first in the capture. Once identified, read that one
679 * card in TC_HEX; later cards still switch to binary via the normal
680 * active-mode/by-pass path. */
681 if (!pack && mode == TC_NORMAL && first_card == 0) {
682 auto_loader = cr_find_hollerith_loader_card(deck);
683
684 /* No marker anywhere in the window. If the deck is a single card,
685 * that card IS the loader -- there is nothing else it could be, and
686 * the IPL is going to nibble-pack it to 0x0000 and execute it either
687 * way. This is how a `gasm --card` boot card boots, and it matches the
688 * Pico's own single-card fallback (deck.c: loader_card = 0 when the
689 * deck holds one card). */
690 if (auto_loader < 0) {
691 int ncards = 0, only = -1;
692 for (int i = 0; i < cap_num_cards(deck); i++) {
693 if (cap_card_ncols(deck, i) > 0) {
694 if (only < 0)
695 only = i;
696 ncards++;
697 }
698 }
699 if (ncards == 1) {
700 auto_loader = only;
702 "cardreader: one-card deck; card %d is its own loader\n",
703 only);
704 }
705 }
706 }
707 if (auto_loader >= 0)
708 ctx->mode = TC_HEX;
709 ctx->post_loader_pack = !ctx->pack && ctx->mode == TC_HEX;
710
711 /* Find the first non-empty card at or after first_card */
712 ctx->card_idx = auto_loader >= 0 ? auto_loader : (first_card < 0 ? 0 : first_card);
713 ctx->col_idx = 0;
714 while (ctx->card_idx < cap_num_cards(deck) &&
715 cap_card_ncols(deck, ctx->card_idx) == 0)
716 ctx->card_idx++;
717
718 /* The first card we feed is the loader card (read in `mode`); later cards
719 * are program cards read in binary. */
720 ctx->loader_card = ctx->card_idx;
721
722 if (ctx->card_idx >= cap_num_cards(deck)) {
723 /* All cards are empty — nothing to send */
724 ctx->state = CR_DONE;
725 ctx->last_card = -1;
726 ctx->last_col = -1;
727 } else {
728 /* Pre-compute last non-empty card and its last column */
729 ctx->last_card = ctx->card_idx; /* start with first non-empty */
730 ctx->last_col = 0;
731 for (int i = ctx->card_idx; i < cap_num_cards(deck); i++) {
732 int nc = cap_card_ncols(deck, i);
733 if (nc > 0) {
734 ctx->last_card = i;
735 ctx->last_col = nc - 1;
736 }
737 }
738 }
739
741 "cardreader: loaded '%s', %d cards, last non-empty card=%d col=%d\n",
742 cap_path, cap_num_cards(deck), ctx->last_card, ctx->last_col);
743
744 /* LESAB: a card reader is on connector 2. A strap, true from the moment the
745 * unit is on the connector -- not from its first clock -- because other
746 * peripherals ask this question before the reader has run (printer.c uses it
747 * to know whose order a shared wait belongs to). */
749
750 /* Initialise the ge_peri node embedded in ctx */
751 ctx->peri.next = NULL;
752 ctx->peri.init = NULL;
753 ctx->peri.on_pulse = NULL;
756 ctx->peri.ctx = ctx;
757
758 return ge_register_peri(ge, &ctx->peri);
759}
const uint16_t * cap_card_columns(const struct cap_deck *d, int i)
Definition cap.c:214
int cap_card_ncols(const struct cap_deck *d, int i)
Definition cap.c:207
int cap_num_cards(const struct cap_deck *d)
Definition cap.c:200
void cap_free(struct cap_deck *d)
Definition cap.c:263
struct cap_deck * cap_load(const char *path)
Definition cap.c:124
#define CR_CMD_TIMEOUT_CYCLES
Definition cardreader.c:86
static enum transcode_mode cr_effective_mode(struct ge *ge, struct cardreader_ctx *ctx)
Definition cardreader.c:231
int cardreader_register_packed(struct ge *ge, const char *cap_path, enum transcode_mode mode)
Definition cardreader.c:648
static struct cardreader_ctx * cr_find(struct ge *ge)
Definition cardreader.c:594
static int cardreader_deinit(struct ge *ge, void *opaque)
Definition cardreader.c:557
cr_state
Definition cardreader.c:67
@ CR_CARD_DONE
Definition cardreader.c:70
@ CR_PRESENTING
Definition cardreader.c:69
@ CR_ARMED_WAIT
Definition cardreader.c:68
@ CR_ERROR
Definition cardreader.c:72
@ CR_DONE
Definition cardreader.c:71
static void cr_next_card(struct cardreader_ctx *ctx)
Definition cardreader.c:259
int cardreader_cards_left(struct ge *ge)
Definition cardreader.c:613
static int cardreader_on_clock(struct ge *ge, void *opaque)
Definition cardreader.c:363
static void cr_trigger_present(struct ge *ge, struct cardreader_ctx *ctx)
Definition cardreader.c:321
int cardreader_register(struct ge *ge, const char *cap_path, enum transcode_mode mode)
Definition cardreader.c:632
static int cr_find_hollerith_loader_card(struct cap_deck *deck)
Definition cardreader.c:167
int cardreader_register_from(struct ge *ge, const char *cap_path, enum transcode_mode mode, int first_card)
Definition cardreader.c:638
static int cr_register(struct ge *ge, const char *cap_path, enum transcode_mode mode, int first_card, int pack)
Definition cardreader.c:654
static void cr_lupob_update(struct ge *ge, struct cardreader_ctx *ctx)
Definition cardreader.c:309
int cardreader_deck_cards(struct ge *ge)
Definition cardreader.c:604
#define CR_FININ_TIMEOUT_CYCLES
Definition cardreader.c:87
static int cr_pack_now(struct cardreader_ctx *ctx, enum transcode_mode m)
Definition cardreader.c:247
static void cr_finin_release(struct ge *ge, struct cardreader_ctx *ctx)
Definition cardreader.c:285
int ge_register_peri(struct ge *ge, struct ge_peri *p)
void ge_log(ge_log_type type, const char *format,...)
Log message.
Definition log.c:122
@ LOG_READER
Integrated Reader.
Definition log.h:28
void reader_setup_to_send(struct ge *ge, uint8_t data, uint8_t end)
Definition reader.c:116
void reader_clear_sending(struct ge *ge)
Definition reader.c:162
Definition cap.c:35
enum transcode_mode mode
Definition cardreader.c:91
unsigned n_autofeeds
Definition cardreader.c:129
struct ge_peri peri
Definition cardreader.c:144
struct cap_deck * deck
Definition cardreader.c:90
unsigned n_feeds
Definition cardreader.c:128
int end_of_card_presented
Definition cardreader.c:115
enum cr_state state
Definition cardreader.c:106
enum transcode_mode active_mode
Definition reader.h:58
uint8_t cmd_pending
Definition reader.h:68
uint8_t cmd_reject
Definition reader.h:69
uint8_t active_valid
Definition reader.h:59
Definition ge.h:882
int(* on_pulse)(struct ge *, void *)
Definition ge.h:885
void * ctx
Definition ge.h:888
struct ge_peri * next
Definition ge.h:883
int(* init)(struct ge *, void *)
Definition ge.h:884
int(* deinit)(struct ge *, void *)
Definition ge.h:887
int(* on_clock)(struct ge *, void *)
Definition ge.h:886
The entire state of the emulated system, including registers, memory, peripherals and timings.
Definition ge.h:172
struct ge_integrated_reader integrated_reader
The I/O interface for the integrated reader (RI)
Definition ge.h:744
uint8_t RASI
Channel 1 in transfer.
Definition ge.h:533
struct ge_peri * peri
Definition ge.h:796
uint8_t transcode_column(uint16_t column, enum transcode_mode mode)
Definition transcode.c:564
transcode_mode
Definition transcode.h:18
@ TC_NORMAL
Definition transcode.h:19
@ TC_BINARY
Definition transcode.h:20
@ TC_COLBIN
Definition transcode.h:22
@ TC_HEX
Definition transcode.h:21