Browse Source

rewrite gb printer code

Thomas B 1 month ago
parent
commit
226a9058d2
6 changed files with 204 additions and 324 deletions
  1. 149
    299
      src/gbprinter.c
  2. 23
    9
      src/gbprinter.h
  3. 10
    4
      src/gbprinter_error.c
  4. 1
    1
      src/main.c
  5. 16
    10
      src/window.c
  6. 5
    1
      src/window.h

+ 149
- 299
src/gbprinter.c View File

25
 #include <stdio.h>
25
 #include <stdio.h>
26
 #include <string.h>
26
 #include <string.h>
27
 
27
 
28
-#include "gb/gb.h"
29
-#include "gb/hardware.h"
30
 #include "input.h"
28
 #include "input.h"
29
+#include "window.h"
31
 #include "gbprinter.h"
30
 #include "gbprinter.h"
32
 
31
 
33
 BANKREF(gbprinter)
32
 BANKREF(gbprinter)
34
 
33
 
35
-/** Width of the printed image in tiles
36
-*/
37
-#define PRN_TILE_WIDTH          20
38
-
39
-#define PRN_LOW(A) ((A) & 0xFF)
40
-#define PRN_HIGH(A) ((A) >> 8)
41
-
42
-/** 0x88,0x33 are mandatory first bytes to initialise a communication with printer
43
- *   Any command sequence begins by these
44
- */
45
-#define PRN_MAGIC               0x3388
46
-#define PRN_LE(A)               PRN_LOW(A),PRN_HIGH(A)
47
-
48
-/** magic number that is sent in the reply packet by the printer before the status byte
49
- */
50
-#define PRN_MAGIC_DETECT        0x81
51
-
52
-/** INIT command is mandatory to initialize communication protocol with the printer
53
- *   Two consecutive linked commands must never be more than 150 ms apart except the INIT command which is valid at least 10 seconds
54
- */
55
-#define PRN_CMD_INIT            0x01
56
-
57
-/** PRINT command
58
- *   Contains the palette, margins, number of prints and printing intensity
59
- */
60
-#define PRN_CMD_PRINT           0x02
61
-
62
-/** DATA command
63
- *   Can be any length between 0 and 640 bytes.
64
- *   DATA command with lenght 0 triggers PRN_STATUS_FULL and is mandatory before print command
65
- */
66
-#define PRN_CMD_DATA            0x04
67
-
68
-/** BREAK command
69
- *   Not very usefull but exists (see Game Boy Programming Manual)
70
- */
71
-#define PRN_CMD_BREAK           0x08
72
-
73
-/** STATUS command
74
- *   Used to check status bits
75
- *   Maybe be used alone before an INIT command to check physical connection with printer
76
- *   Resets PRN_STATUS_UNTRAN
77
- */
78
-#define PRN_CMD_STATUS          0x0F
79
-
80
-/** Palette format: the bits, grouped two by two, give the printing color of the encoded pixel value
81
- *   for the default palette 0xE4 = 0b11100100 = [3 2 1 0]
82
- *   Any value is valid, which means that 1 to 4 color images are possible
83
- *   0x00 acts the same as 0xE4 for the printer
84
- */
85
-#define PRN_PALETTE_NORMAL      0b11100100u
86
-#define PRN_PALETTE_INV         0b00011011u
87
-
88
-/** Don't use margins
89
- */
90
-#define PRN_NO_MARGINS          0x00
91
-
92
-/** Exposure: 0x40 is default value, values from 0x80 to 0xFF act as 0x40
93
- *   Determines the time used by the printer head to heat the thermal paper
94
- */
95
-#define PRN_EXPOSURE_LIGHT      0x00
96
-#define PRN_EXPOSURE_DEFAULT    0x40
97
-#define PRN_EXPOSURE_DARK       0x7F
98
-
99
-/** Battery too low
100
- */
101
-#define PRN_STATUS_LOWBAT       0x80
102
-
103
-/** Error not specified according to the Game Boy Programming manual
104
- */
105
-#define PRN_STATUS_ER2          0x40
106
-
107
-/** Paper jam  (abnormal motor operation)
108
- */
109
-#define PRN_STATUS_ER1          0x20
110
-
111
-/** Packet error (but not checksum error)
112
- */
113
-#define PRN_STATUS_ER0          0x10
114
-
115
-/** Unprocessed data present in printer memory
116
- *   Allows to verify that printer got some data in memory with correct checksum
117
- *   is resetted by STATUS command
118
- */
119
-#define PRN_STATUS_UNTRAN       0x08
120
-
121
-/** status data ready, mandatory to allow printing
122
- *   is triggered by DATA command with lenght 0
123
- */
124
-#define PRN_STATUS_FULL         0x04
125
-
126
-/** Message sent by the printer while physically printing
127
- */
128
-#define PRN_STATUS_BUSY         0x02
129
-
130
-/** The received packet has a ckecksum error
131
- */
132
-#define PRN_STATUS_SUM          0x01
133
-
134
-#define PRN_STATUS_MASK_ERRORS  0xF0
135
-#define PRN_STATUS_MASK_ANY     0xFF
136
-
137
-#define PRN_SECONDS(A)          ((A)*60)
138
-
139
-#define PRN_MAX_PROGRESS        8
140
-
141
-#define PRN_STATUS_CANCELLED    PRN_STATUS_ER2
142
-
143
-#define REINIT_SEIKO
144
-
145
-#define START_TRANSFER          0x81
146
-#define PRN_BUSY_TIMEOUT        PRN_SECONDS(2)
147
-#define PRN_COMPLETION_TIMEOUT  PRN_SECONDS(20)
148
-#define PRN_SEIKO_RESET_TIMEOUT 10
149
-
150
-#define PRN_FINAL_MARGIN        0x03
34
+#define PRN_TILE_WIDTH     20 // Width of the printed image in tiles
35
+#define PRN_MAGIC          0x3388
36
+#define PRN_MAGIC_DETECT   0x81 // magic reply from printer
37
+#define PRN_DETECT_TIMEOUT 10 // 1/6th second
38
+#define PRN_BUSY_TIMEOUT   (2 * 60) // 2s
39
+#define PRN_PRINT_TIMEOUT  (20 * 60) // 20s
40
+
41
+#define PRN_PALETTE_NORMAL 0b11100100u
42
+#define PRN_PALETTE_INV    0b00011011u
43
+
44
+#define PRN_NO_MARGINS     0x00
45
+#define PRN_FINAL_MARGIN   0x03
46
+
47
+#define PRN_EXPO_LIGHT     0x00
48
+#define PRN_EXPO_DEFAULT   0x40
49
+#define PRN_EXPO_DARK      0x7F
50
+
51
+enum PRN_CMDS {
52
+    PRN_CMD_INIT   = 0x01, // initialize printer
53
+    PRN_CMD_PRINT  = 0x02, // print command
54
+    PRN_CMD_DATA   = 0x04, // data command (up to 640 bytes)
55
+    PRN_CMD_BREAK  = 0x08,
56
+    PRN_CMD_STATUS = 0x0F, // query status
57
+};
151
 
58
 
152
-typedef struct start_print_pkt_s {
59
+struct prn_header {
153
     uint16_t magic;
60
     uint16_t magic;
154
-    uint16_t command;
61
+    uint8_t command;
62
+    uint8_t compression;
155
     uint16_t length;
63
     uint16_t length;
156
-    uint8_t print;
64
+};
65
+
66
+struct prn_config {
67
+    uint8_t sheets;
157
     uint8_t margins;
68
     uint8_t margins;
158
     uint8_t palette;
69
     uint8_t palette;
159
     uint8_t exposure;
70
     uint8_t exposure;
160
-    uint16_t crc;
161
-    uint16_t trail;
162
-} start_print_pkt_t;
163
-
164
-static const uint8_t PRN_PKT_INIT[] = {
165
-    PRN_LE(PRN_MAGIC), PRN_LE(PRN_CMD_INIT),   PRN_LE(0), PRN_LE(0x01), PRN_LE(0)
166
-};
167
-
168
-static const uint8_t PRN_PKT_STATUS[] = {
169
-    PRN_LE(PRN_MAGIC), PRN_LE(PRN_CMD_STATUS), PRN_LE(0), PRN_LE(0x0F), PRN_LE(0)
170
-};
171
-
172
-static const uint8_t PRN_PKT_EOF[] = {
173
-    PRN_LE(PRN_MAGIC), PRN_LE(PRN_CMD_DATA),   PRN_LE(0), PRN_LE(0x04), PRN_LE(0)
174
-};
175
-
176
-static const uint8_t PRN_PKT_CANCEL[] = {
177
-    PRN_LE(PRN_MAGIC), PRN_LE(PRN_CMD_BREAK),  PRN_LE(0), PRN_LE(0x01), PRN_LE(0)
178
 };
71
 };
179
 
72
 
180
-static start_print_pkt_t PRN_PKT_START = {
181
-    .magic = PRN_MAGIC, .command = PRN_CMD_PRINT,
182
-    .length = 4, .print = TRUE,
183
-    .margins = 0, .palette = PRN_PALETTE_NORMAL, .exposure = PRN_EXPOSURE_DARK,
184
-    .crc = 0, .trail = 0
73
+struct prn_footer {
74
+    uint16_t crc;
75
+    uint8_t alive;
76
+    uint8_t status;
185
 };
77
 };
186
 
78
 
187
-static uint16_t printer_status;
188
-static uint8_t printer_tile_num;
189
-
190
-static inline void gbprinter_set_print_params(uint8_t margins, uint8_t palette, uint8_t exposure) {
191
-    PRN_PKT_START.crc = ((PRN_CMD_PRINT + 0x04u + 0x01u)
192
-            + (PRN_PKT_START.margins = margins)
193
-            + (PRN_PKT_START.palette = palette)
194
-            + (PRN_PKT_START.exposure = exposure));
195
-}
196
-
197
-static uint8_t printer_send_receive(uint8_t b) {
79
+static uint8_t prn_send_receive(uint8_t b) {
198
     SB_REG = b;
80
     SB_REG = b;
199
-    SC_REG = START_TRANSFER;
200
-    while (SC_REG & 0x80);
81
+    SC_REG = SIOF_XFER_START | SIOF_CLOCK_INT;
82
+    while (SC_REG & SIOF_XFER_START);
201
     return SB_REG;
83
     return SB_REG;
202
 }
84
 }
203
 
85
 
204
-static uint8_t printer_send_byte(uint8_t b) {
205
-    return (uint8_t)(printer_status = ((printer_status << 8) | printer_send_receive(b)));
86
+static void prn_send_block(uint8_t *data, uint16_t length, uint16_t *crc) {
87
+    while (length-- > 0) {
88
+        uint8_t v = *data;
89
+        *crc += v;
90
+        *data = prn_send_receive(v);
91
+        data++;
92
+    }
206
 }
93
 }
207
 
94
 
208
-static uint8_t printer_send_command(const uint8_t *command, uint8_t length) {
209
-    uint8_t index = 0;
210
-    while (index++ < length) printer_send_byte(*command++);
211
-    return ((uint8_t)(printer_status >> 8) == PRN_MAGIC_DETECT) ? (uint8_t)printer_status : PRN_STATUS_MASK_ERRORS;
212
-}
95
+static enum PRN_STATUS printer_send_command(enum PRN_CMDS cmd,
96
+                                            uint8_t *data, uint16_t length) {
97
+    static struct prn_header header;
98
+    static struct prn_footer footer;
99
+    uint16_t crc = 0;
213
 
100
 
214
-#define PRINTER_SEND_COMMAND(CMD) printer_send_command((const uint8_t *)&(CMD), sizeof(CMD))
101
+    header.magic = PRN_MAGIC;
102
+    header.command = cmd;
103
+    header.compression = 0;
104
+    header.length = data ? length : 0;
215
 
105
 
216
-static uint8_t printer_print_tile(const uint8_t *tiledata) {
217
-    static const uint8_t PRINT_TILE[] = { 0x88,0x33,0x04,0x00,0x80,0x02 };
218
-    static uint16_t printer_CRC;
219
-    if (printer_tile_num == 0) {
220
-        const uint8_t * data = PRINT_TILE;
221
-        for (uint8_t i = sizeof(PRINT_TILE); i != 0; i--) printer_send_receive(*data++);
222
-        printer_CRC = 0x04 + 0x80 + 0x02;
223
-    }
224
-    for(uint8_t i = 0x10; i != 0; i--, tiledata++) {
225
-        printer_CRC += *tiledata;
226
-        printer_send_receive(*tiledata);
227
-    }
228
-    if (++printer_tile_num == 40) {
229
-        printer_send_receive((uint8_t)printer_CRC);
230
-        printer_send_receive((uint8_t)(printer_CRC >> 8));
231
-        printer_send_receive(0x00);
232
-        printer_send_receive(0x00);
233
-        printer_CRC = printer_tile_num = 0;
234
-        return TRUE;
106
+    footer.crc = 0;
107
+    footer.alive = 0;
108
+    footer.status = 0;
109
+
110
+    prn_send_block((uint8_t *)&header, sizeof(struct prn_header), &crc);
111
+    if (data && (length > 0)) {
112
+        prn_send_block(data, length, &crc);
235
     }
113
     }
236
-    return FALSE;
237
-}
238
 
114
 
239
-static inline void printer_init(void) {
240
-    printer_tile_num = 0;
241
-    PRINTER_SEND_COMMAND(PRN_PKT_INIT);
115
+    footer.crc = crc;
116
+    prn_send_block((uint8_t *)&footer, sizeof(struct prn_footer), &crc);
117
+
118
+    enum PRN_STATUS r = footer.status;
119
+    if (footer.alive != PRN_MAGIC_DETECT) {
120
+        r |= PRN_STATUS_NO_MAGIC;
121
+    }
122
+    return r;
242
 }
123
 }
243
 
124
 
244
-uint8_t printer_check_cancel(void) {
125
+static uint8_t printer_check_cancel(void) {
245
     key_read();
126
     key_read();
246
     return key_pressed(J_B);
127
     return key_pressed(J_B);
247
 }
128
 }
248
 
129
 
249
-static uint8_t printer_wait(uint16_t timeout, uint8_t mask, uint8_t value) {
250
-    uint8_t error;
251
-    while (((error = PRINTER_SEND_COMMAND(PRN_PKT_STATUS)) & mask) != value) {
130
+static enum PRN_STATUS printer_wait(uint16_t timeout, uint8_t mask, uint8_t value) {
131
+    enum PRN_STATUS error;
132
+
133
+    while (1) {
134
+        error = printer_send_command(PRN_CMD_STATUS, NULL, 0);
135
+        if ((error & mask) == value) {
136
+            break;
137
+        }
138
+
252
         if (printer_check_cancel()) {
139
         if (printer_check_cancel()) {
253
-            PRINTER_SEND_COMMAND(PRN_PKT_CANCEL);
140
+            printer_send_command(PRN_CMD_BREAK, NULL, 0);
254
             return PRN_STATUS_CANCELLED;
141
             return PRN_STATUS_CANCELLED;
255
         }
142
         }
256
-        if (timeout-- == 0) return PRN_STATUS_MASK_ERRORS;
257
-        if (error & PRN_STATUS_MASK_ERRORS) break;
143
+
144
+        if (timeout-- == 0) {
145
+            return PRN_STATUS_TIMEOUT;
146
+        }
147
+
148
+        if (error & PRN_STATUS_MASK_ERRORS) {
149
+            break;
150
+        }
151
+
258
         vsync();
152
         vsync();
259
     }
153
     }
154
+
260
     return error;
155
     return error;
261
 }
156
 }
262
 
157
 
263
-uint8_t gbprinter_detect(uint8_t delay) BANKED {
264
-    printer_init();
265
-    uint8_t r = printer_wait(delay, PRN_STATUS_MASK_ANY, PRN_STATUS_OK);
158
+enum PRN_STATUS gbprinter_detect(void) BANKED {
159
+    printer_send_command(PRN_CMD_INIT, NULL, 0);
160
+    uint8_t r = printer_wait(PRN_DETECT_TIMEOUT, PRN_STATUS_MASK_ANY, PRN_STATUS_OK);
161
+
266
 #ifdef DEBUG
162
 #ifdef DEBUG
267
     EMU_printf("%s: %hu\n",  __func__, (uint8_t)r);
163
     EMU_printf("%s: %hu\n",  __func__, (uint8_t)r);
268
 #endif // DEBUG
164
 #endif // DEBUG
269
     return r;
165
     return r;
270
 }
166
 }
271
 
167
 
272
-uint8_t gbprinter_print_image(const uint8_t *image_map, const uint8_t *image,
273
-                              int8_t pos_x, uint8_t width, uint8_t height,
274
-                              uint8_t done) BANKED {
275
-    uint8_t tile_data[16];
276
-    uint8_t rows = ((height + 1) >> 1) << 1;
277
-    uint8_t pkt_count = 0;
278
-
279
-    if ((rows >> 1) == 0) return PRN_STATUS_OK;
280
-
281
-    printer_tile_num = 0;
282
-
283
-    for (uint8_t y = 0; y < rows; y++) {
284
-        for (int16_t x = 0; x < PRN_TILE_WIDTH; x++) {
285
-#ifdef DEBUG
286
-            EMU_printf("%s: %hu %i\n",  __func__, (uint8_t)y, (int16_t)x);
287
-#endif // DEBUG
288
-
289
-            // overlay the picture tile if in range
290
-            if ((y < height) && (x >= pos_x) && (x < (pos_x + width))) {
291
-                uint8_t tile = image_map[(y * width) + (x - pos_x)];
292
-                memcpy(tile_data, image + ((uint16_t)tile << 4), sizeof(tile_data));
293
-            } else {
294
-                memset(tile_data, 0, sizeof(tile_data));
295
-            }
296
-
297
-            // print the resulting tile
298
-            if (printer_print_tile(tile_data)) {
299
-                pkt_count++;
300
-
301
-                if (printer_check_cancel()) {
302
-                    PRINTER_SEND_COMMAND(PRN_PKT_CANCEL);
303
-                    return PRN_STATUS_CANCELLED;
304
-                }
305
-            }
306
-
307
-            if (pkt_count == 9) {
308
-                pkt_count = 0;
309
-                PRINTER_SEND_COMMAND(PRN_PKT_EOF);
310
-
311
-                // setup margin if last packet
312
-                gbprinter_set_print_params((y == (rows - 1)) ? PRN_FINAL_MARGIN : PRN_NO_MARGINS,
313
-                                           PRN_PALETTE_NORMAL, PRN_EXPOSURE_DARK);
314
-
315
-                PRINTER_SEND_COMMAND(PRN_PKT_START);
316
-
317
-                // query printer status
318
-                uint8_t error = printer_wait(PRN_BUSY_TIMEOUT, PRN_STATUS_BUSY, PRN_STATUS_BUSY);
319
-                if (error & PRN_STATUS_MASK_ERRORS) {
320
-                    return error;
321
-                }
322
-
323
-                error = printer_wait(PRN_COMPLETION_TIMEOUT, PRN_STATUS_BUSY, 0);
324
-                if (error & PRN_STATUS_MASK_ERRORS) {
325
-                    return error;
326
-                }
327
-
328
-#ifdef REINIT_SEIKO
329
-                // reinit printer (required by Seiko?)
330
-                if (y < (rows - 1)) {
331
-                    PRINTER_SEND_COMMAND(PRN_PKT_INIT);
332
-                    error = printer_wait(PRN_SEIKO_RESET_TIMEOUT, PRN_STATUS_MASK_ANY, PRN_STATUS_OK);
333
-                    if (error) {
334
-                        return error;
335
-                    }
336
-                }
337
-#endif
338
-            }
339
-        }
340
-    }
341
-
342
-    if (pkt_count && done) {
343
-        PRINTER_SEND_COMMAND(PRN_PKT_EOF);
344
-
345
-        // setup printing if required
346
-        gbprinter_set_print_params(PRN_FINAL_MARGIN, PRN_PALETTE_NORMAL, PRN_EXPOSURE_DARK);
347
-        PRINTER_SEND_COMMAND(PRN_PKT_START);
348
-
349
-        // query printer status
350
-        uint8_t error = printer_wait(PRN_BUSY_TIMEOUT, PRN_STATUS_BUSY, PRN_STATUS_BUSY);
351
-        if (error & PRN_STATUS_MASK_ERRORS) {
352
-            return error;
353
-        }
354
-
355
-        error = printer_wait(PRN_COMPLETION_TIMEOUT, PRN_STATUS_BUSY, 0);
356
-        if (error & PRN_STATUS_MASK_ERRORS) {
357
-            return error;
358
-        }
359
-    }
360
-
361
-    return PRINTER_SEND_COMMAND(PRN_PKT_STATUS);
168
+static void win_str_helper(const char *s, uint8_t y_pos) {
169
+    static char line_buff[11];
170
+    strncpy(line_buff, s, 10);
171
+    line_buff[10] = '\0';
172
+    win_str_center(line_buff, y_pos, 0);
362
 }
173
 }
363
 
174
 
364
-uint8_t gbprinter_screenshot(uint8_t win) BANKED {
365
-    static uint8_t map_buff[2 * DEVICE_SCREEN_WIDTH];
175
+enum PRN_STATUS gbprinter_screenshot(uint8_t win) BANKED {
366
     static uint8_t tile_buff[2 * DEVICE_SCREEN_WIDTH * 16];
176
     static uint8_t tile_buff[2 * DEVICE_SCREEN_WIDTH * 16];
177
+    static struct prn_config params;
178
+    enum PRN_STATUS r = PRN_STATUS_OK;
367
 
179
 
368
-    printer_init();
369
-    printer_status = 0x00;
370
-
371
-    uint8_t r = PRN_STATUS_OK;
180
+    printer_send_command(PRN_CMD_INIT, NULL, 0);
372
 
181
 
373
     for (int y = 0; y < DEVICE_SCREEN_HEIGHT; y += 2) {
182
     for (int y = 0; y < DEVICE_SCREEN_HEIGHT; y += 2) {
374
         for (int y2 = 0; y2 < 2; y2++) {
183
         for (int y2 = 0; y2 < 2; y2++) {
375
             for (int x = 0; x < DEVICE_SCREEN_WIDTH; x++) {
184
             for (int x = 0; x < DEVICE_SCREEN_WIDTH; x++) {
376
                 uint8_t tile = win ? get_win_tile_xy(x, y + y2) : get_bkg_tile_xy(x, y + y2);
185
                 uint8_t tile = win ? get_win_tile_xy(x, y + y2) : get_bkg_tile_xy(x, y + y2);
377
-                map_buff[x + (y2 * DEVICE_SCREEN_WIDTH)] = (x + (y2 * DEVICE_SCREEN_WIDTH));
378
                 win ? get_win_data(tile, 1, tile_buff + ((x + (y2 * DEVICE_SCREEN_WIDTH)) * 16))
186
                 win ? get_win_data(tile, 1, tile_buff + ((x + (y2 * DEVICE_SCREEN_WIDTH)) * 16))
379
                     : get_bkg_data(tile, 1, tile_buff + ((x + (y2 * DEVICE_SCREEN_WIDTH)) * 16));
187
                     : get_bkg_data(tile, 1, tile_buff + ((x + (y2 * DEVICE_SCREEN_WIDTH)) * 16));
380
             }
188
             }
384
                 : fill_bkg_rect(0, y + y2, DEVICE_SCREEN_WIDTH, 1, 0);
192
                 : fill_bkg_rect(0, y + y2, DEVICE_SCREEN_WIDTH, 1, 0);
385
         }
193
         }
386
 
194
 
387
-        r = gbprinter_print_image(map_buff, tile_buff, 0, DEVICE_SCREEN_WIDTH, 2,
388
-                                  (y == (DEVICE_SCREEN_HEIGHT - 2)) ? 1 : 0);
195
+        if (win) {
196
+            if (y == 0) {
197
+                win_str_helper("gb printer", 0);
198
+            } else if (y == 2) {
199
+                win_str_helper("transmit", 2);
200
+            } else if (y == 8) {
201
+                win_str_helper("in", 8);
202
+            } else if (y == 10) {
203
+                win_str_helper("progress", 10);
204
+            } else if (y == 16) {
205
+                win_str_helper("printing", 16);
206
+            }
207
+        }
208
+
209
+        r = printer_send_command(PRN_CMD_DATA, tile_buff, sizeof(tile_buff));
389
         if ((r & ~PRN_STATUS_UNTRAN) != PRN_STATUS_OK) {
210
         if ((r & ~PRN_STATUS_UNTRAN) != PRN_STATUS_OK) {
390
-            break;
211
+            goto end;
212
+        }
213
+
214
+        if (printer_check_cancel()) {
215
+            printer_send_command(PRN_CMD_BREAK, NULL, 0);
216
+            r = PRN_STATUS_CANCELLED;
217
+            goto end;
391
         }
218
         }
392
     }
219
     }
393
 
220
 
221
+    printer_send_command(PRN_CMD_DATA, NULL, 0);
222
+
223
+    params.sheets = 1;
224
+    params.margins = PRN_FINAL_MARGIN;
225
+    params.palette = PRN_PALETTE_NORMAL;
226
+    params.exposure = PRN_EXPO_DARK;
227
+
228
+    printer_send_command(PRN_CMD_PRINT, (uint8_t *)&params, sizeof(struct prn_config));
229
+
230
+    r = printer_wait(PRN_BUSY_TIMEOUT, PRN_STATUS_BUSY, PRN_STATUS_BUSY);
231
+    if (r & PRN_STATUS_MASK_ERRORS) {
232
+        goto end;
233
+    }
234
+
235
+    r = printer_wait(PRN_PRINT_TIMEOUT, PRN_STATUS_BUSY, 0);
236
+    if (r & PRN_STATUS_MASK_ERRORS) {
237
+        goto end;
238
+    }
239
+
240
+end:
241
+#ifdef DEBUG
242
+    EMU_printf("%s: %hu\n",  __func__, (uint8_t)r);
243
+#endif // DEBUG
394
     return r;
244
     return r;
395
 }
245
 }

+ 23
- 9
src/gbprinter.h View File

26
 #include <gbdk/platform.h>
26
 #include <gbdk/platform.h>
27
 #include <stdint.h>
27
 #include <stdint.h>
28
 
28
 
29
-#define PRN_STATUS_OK           0x00
30
-#define PRINTER_DETECT_TIMEOUT  10
31
-
32
-uint8_t gbprinter_detect(uint8_t delay) BANKED;
33
-uint8_t gbprinter_print_image(const uint8_t *image_map, const uint8_t *image,
34
-                              int8_t pos_x, uint8_t width, uint8_t height,
35
-                              uint8_t done) BANKED;
36
-uint8_t gbprinter_screenshot(uint8_t win) BANKED;
37
-uint8_t gbprinter_error(uint8_t status, char *buff);
29
+enum PRN_STATUS {
30
+    PRN_STATUS_LOWBAT      = 0x80, // battery too low
31
+    PRN_STATUS_ER2         = 0x40, // unspecified error
32
+    PRN_STATUS_ER1         = 0x20, // paper jam
33
+    PRN_STATUS_ER0         = 0x10, // packet error
34
+    PRN_STATUS_UNTRAN      = 0x08, // unprinted data in buffer
35
+    PRN_STATUS_FULL        = 0x04, // ready, triggered by DATA with len 0
36
+    PRN_STATUS_BUSY        = 0x02, // printer is printing
37
+    PRN_STATUS_CHECKSUM    = 0x01, // Checksum error
38
+    PRN_STATUS_OK          = 0x00,
39
+
40
+    PRN_STATUS_CANCELLED   = 0x100,
41
+    PRN_STATUS_TIMEOUT     = 0x200,
42
+    PRN_STATUS_NO_MAGIC    = 0x400,
43
+
44
+    PRN_STATUS_MASK_ERRORS = 0x7F0,
45
+    PRN_STATUS_MASK_ANY    = 0x7FF,
46
+};
47
+
48
+enum PRN_STATUS gbprinter_detect(void) BANKED;
49
+enum PRN_STATUS gbprinter_screenshot(uint8_t win) BANKED;
50
+
51
+uint8_t gbprinter_error(enum PRN_STATUS status, char *buff);
38
 
52
 
39
 BANKREF_EXTERN(gbprinter)
53
 BANKREF_EXTERN(gbprinter)
40
 BANKREF_EXTERN(gbprinter_error)
54
 BANKREF_EXTERN(gbprinter_error)

+ 10
- 4
src/gbprinter_error.c View File

29
 
29
 
30
 BANKREF(gbprinter_error)
30
 BANKREF(gbprinter_error)
31
 
31
 
32
+#define ERROR_BITS 11
33
+
32
 static const char str_lowbat[] = "battery too low";
34
 static const char str_lowbat[] = "battery too low";
33
 static const char str_er2[] = "unknown error";
35
 static const char str_er2[] = "unknown error";
34
 static const char str_er1[] = "paper jam";
36
 static const char str_er1[] = "paper jam";
37
 static const char str_full[] = "data full";
39
 static const char str_full[] = "data full";
38
 static const char str_busy[] = "printer busy";
40
 static const char str_busy[] = "printer busy";
39
 static const char str_sum[] = "checksum error";
41
 static const char str_sum[] = "checksum error";
42
+static const char str_cancel[] = "cancelled";
43
+static const char str_timeout[] = "timeout";
44
+static const char str_magic[] = "wrong magic byte";
40
 
45
 
41
-static const char * const error_strings[8] = {
46
+static const char * const error_strings[ERROR_BITS] = {
42
     str_sum, str_busy, str_full, str_untran,
47
     str_sum, str_busy, str_full, str_untran,
43
-    str_er0, str_er1, str_er2, str_lowbat
48
+    str_er0, str_er1, str_er2, str_lowbat,
49
+    str_cancel, str_timeout, str_magic,
44
 };
50
 };
45
 
51
 
46
-uint8_t gbprinter_error(uint8_t status, char *buff) NONBANKED {
52
+uint8_t gbprinter_error(enum PRN_STATUS status, char *buff) NONBANKED {
47
     if (status == PRN_STATUS_OK) {
53
     if (status == PRN_STATUS_OK) {
48
         sprintf(buff, "ok");
54
         sprintf(buff, "ok");
49
         return 2;
55
         return 2;
51
 
57
 
52
     uint8_t n = 0;
58
     uint8_t n = 0;
53
     START_ROM_BANK(BANK(gbprinter_error)) {
59
     START_ROM_BANK(BANK(gbprinter_error)) {
54
-        for (uint8_t i = 0; i < 8; i++) {
60
+        for (uint8_t i = 0; i < ERROR_BITS; i++) {
55
             if (status & (1 << i)) {
61
             if (status & (1 << i)) {
56
                 if (n != 0) {
62
                 if (n != 0) {
57
                     buff[n++] = '\n';
63
                     buff[n++] = '\n';

+ 1
- 1
src/main.c View File

89
         if (key_pressed(J_A) || key_pressed(J_B)) {
89
         if (key_pressed(J_A) || key_pressed(J_B)) {
90
             break;
90
             break;
91
         } else if (key_pressed(J_SELECT)) {
91
         } else if (key_pressed(J_SELECT)) {
92
-            uint8_t status = gbprinter_detect(PRINTER_DETECT_TIMEOUT);
92
+            enum PRN_STATUS status = gbprinter_detect();
93
             if (status == PRN_STATUS_OK) {
93
             if (status == PRN_STATUS_OK) {
94
                 win_score_clear(is_black, 1);
94
                 win_score_clear(is_black, 1);
95
                 list_scores(is_black);
95
                 list_scores(is_black);

+ 16
- 10
src/window.c View File

190
     str(s, LINE_WIDTH - n, y_off, is_black);
190
     str(s, LINE_WIDTH - n, y_off, is_black);
191
 }
191
 }
192
 
192
 
193
+void win_str_center(const char *s, uint8_t y_off, uint8_t is_black) NONBANKED {
194
+    START_ROM_BANK(BANK(window)) {
195
+        str_center(s, y_off, is_black);
196
+    } END_ROM_BANK
197
+}
198
+
193
 static void str_lines(const char *s, uint8_t y_off, uint8_t is_black) {
199
 static void str_lines(const char *s, uint8_t y_off, uint8_t is_black) {
194
     if (strlen(s) > 10) {
200
     if (strlen(s) > 10) {
195
         str(s, 0, y_off, is_black);
201
         str(s, 0, y_off, is_black);
289
     number(is_black ? -score.score : score.score, 7, 4 + off * 3, is_black);
295
     number(is_black ? -score.score : score.score, 7, 4 + off * 3, is_black);
290
 }
296
 }
291
 
297
 
292
-void win_score_print(uint8_t status) BANKED {
298
+void win_score_print(enum PRN_STATUS status) BANKED {
293
     static char buff[128];
299
     static char buff[128];
294
 
300
 
295
     if (_cpu == CGB_TYPE) {
301
     if (_cpu == CGB_TYPE) {
296
-        str_ascii("GB Printer", 0, 2, 0);
297
-        str_ascii("Score Printout", 0, 3, 0);
298
-        str_ascii("Result:", 0, 6, 0);
302
+        str_ascii("GB Printer", 0, 0, 0);
303
+        str_ascii("Score Printout", 0, 1, 0);
304
+        str_ascii("Result:", 0, 3, 0);
299
 
305
 
300
         if (status == PRN_STATUS_OK) {
306
         if (status == PRN_STATUS_OK) {
301
-            str_ascii("success", 0, 7, 0);
307
+            str_ascii("success", 0, 8, 0);
302
         } else {
308
         } else {
303
-            sprintf(buff, "error: 0x%hx", (uint8_t)status);
304
-            str_ascii(buff, 0, 7, 0);
305
-        }
309
+            sprintf(buff, "error: 0x%04x", (uint16_t)status);
310
+            str_ascii(buff, 0, 5, 0);
306
 
311
 
307
-        gbprinter_error(status, buff);
308
-        str_ascii_lines(buff, 9, 0);
312
+            gbprinter_error(status, buff);
313
+            str_ascii_lines(buff, 6, 0);
314
+        }
309
     } else {
315
     } else {
310
         str("printout", 0, 4, 0);
316
         str("printout", 0, 4, 0);
311
         if (status == PRN_STATUS_OK) {
317
         if (status == PRN_STATUS_OK) {

+ 5
- 1
src/window.h View File

22
 
22
 
23
 #include <gbdk/platform.h>
23
 #include <gbdk/platform.h>
24
 #include <stdint.h>
24
 #include <stdint.h>
25
+
25
 #include "score.h"
26
 #include "score.h"
27
+#include "gbprinter.h"
26
 
28
 
27
 void win_init(uint8_t is_splash);
29
 void win_init(uint8_t is_splash);
28
 void win_splash_draw(int32_t lowest, int32_t highest) BANKED;
30
 void win_splash_draw(int32_t lowest, int32_t highest) BANKED;
29
 void win_splash_mp(void) BANKED;
31
 void win_splash_mp(void) BANKED;
30
 void win_score_clear(uint8_t is_black, uint8_t no_bg) BANKED;
32
 void win_score_clear(uint8_t is_black, uint8_t no_bg) BANKED;
31
 void win_score_draw(struct scores score, uint8_t off, uint8_t is_black) BANKED;
33
 void win_score_draw(struct scores score, uint8_t off, uint8_t is_black) BANKED;
32
-void win_score_print(uint8_t status) BANKED;
34
+void win_score_print(enum PRN_STATUS status) BANKED;
33
 void win_about(void) BANKED;
35
 void win_about(void) BANKED;
34
 void win_about_mp(void) BANKED;
36
 void win_about_mp(void) BANKED;
35
 void win_conf(void) BANKED;
37
 void win_conf(void) BANKED;
38
 void win_name_draw(uint16_t name, uint8_t is_black, uint8_t pos) BANKED;
40
 void win_name_draw(uint16_t name, uint8_t is_black, uint8_t pos) BANKED;
39
 uint8_t win_game_draw(int32_t score) BANKED;
41
 uint8_t win_game_draw(int32_t score) BANKED;
40
 
42
 
43
+void win_str_center(const char *s, uint8_t y_off, uint8_t is_black);
44
+
41
 BANKREF_EXTERN(window)
45
 BANKREF_EXTERN(window)
42
 
46
 
43
 #endif // __WINDOW_H__
47
 #endif // __WINDOW_H__

Loading…
Cancel
Save