printer_i.h 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113
  1. // SPDX-License-Identifier: BSD-2-Clause
  2. // Copyright (c) 2024 KBEmbedded
  3. #ifndef PRINTER_I_H
  4. #define PRINTER_I_H
  5. #include <protocols/printer/include/printer_proto.h>
  6. #define START_L_BYTE 0x88
  7. #define START_H_BYTE 0x33
  8. #define ALIVE_BYTE 0x81
  9. #define CMD_INIT 0x01
  10. #define CMD_PRINT 0x02
  11. #define CMD_TRANSFER 0x10
  12. #define CMD_DATA 0x04
  13. #define CMD_STATUS 0x0f
  14. /* These constants are private to the printer protocol */
  15. #define LINE_BUF_SZ 640 // (TILE_SIZE * WIDTH * 2)
  16. #define TRANSFER_SZ 3584 // (16*16*14) // Image minus frame
  17. /* NOTE:
  18. * These numbers are empirically gathered from a few different games thus far.
  19. * There are many notes floating around the internet of the GB Printer having
  20. * a 100 ms limit between packets where it will reset. However, I've seen
  21. * Pokemon Pinball wait 99.5 ms between packets after a print command which is
  22. * a bit too close for comfort. As this code tracks timestamps _after_ each byte,
  23. * that ends up just over 110 ms which trips the hard timeout and resets state.
  24. * This often cofuses the hell out of games.
  25. *
  26. * Additionally, on the other end of the spectrum, Pokemon Gold absolutely uses
  27. * the hard timeout to reset the printer between packets. It waits ~278 ms, when
  28. * it could just send an init command.
  29. *
  30. * Even more silly, Pokemon Pinball has a fun quirk where if the print completes
  31. * immediately (usually the Flipper will mark a print complete with a single
  32. * packet turnaround), it asks for status a couple of times, then starts (presumably)
  33. * another status packet, but the second byte in the transfer is stopped mid-byte.
  34. * Between that point and the start of the next, real packet, is 30 ms, 32.6 ms
  35. * if you go from end of last byte received to start of next, real packet.
  36. *
  37. * This means there is some "soft" timeout that the printer uses to reset a packet
  38. * transfer in progress, but don't reset the whole printer state.
  39. *
  40. * There are wisps of some "unknown" bit timeout of 1.49 ms. But I've not yet
  41. * seen that in action.
  42. *
  43. * As far as I know, no one has dumped and reverse engineered the ROM of the
  44. * Game Boy Printer directly. I think all of the existing documentation was from
  45. * reverse engineering the communication channel. Maybe someday I'll dump the
  46. * GB Printer ROM and try to better understand all of it.
  47. *
  48. * Additionally, the gameboy camera seems to hint at a 2 second busy timeout, that
  49. * is that the printer needs to return a printing status within 2 seconds of starting
  50. * the print. There is also a hint of a 20 second print timeout, that is that the
  51. * printer needs to return print complete within 20 seconds of starting the print.
  52. * These two values are not really used in this library yet.
  53. */
  54. #define HARD_TIMEOUT_US 125000
  55. #define SOFT_TIMEOUT_US 20000
  56. enum packet_state {
  57. START_L,
  58. START_H,
  59. COMMAND,
  60. COMPRESS,
  61. LEN_L,
  62. LEN_H,
  63. DATA,
  64. CKSUM_L,
  65. CKSUM_H,
  66. ALIVE,
  67. STATUS,
  68. };
  69. struct packet {
  70. uint8_t cmd;
  71. bool compress;
  72. uint16_t len; // This is stored in the flipper endianness, arrives LSB first from GB, unmodified in code
  73. uint8_t line_buf[LINE_BUF_SZ]; // 640 bytes, enough for two lines of tiles
  74. uint16_t cksum; // This is stored in the flipper endianness, arrives LSB first from GB
  75. uint8_t status;
  76. /* These are not part of the packet, but used by us */
  77. uint16_t cksum_calc;
  78. size_t line_buf_sz;
  79. bool print_complete;
  80. uint8_t zero_counter;
  81. enum packet_state state;
  82. uint32_t time;
  83. };
  84. #define THREAD_FLAGS_EXIT (1 << 0)
  85. #define THREAD_FLAGS_DATA (1 << 1)
  86. #define THREAD_FLAGS_PRINT (1 << 2)
  87. #define THREAD_FLAGS_COMPLETE (1 << 3)
  88. #define THREAD_FLAGS_ALL (THREAD_FLAGS_EXIT | THREAD_FLAGS_DATA | THREAD_FLAGS_PRINT | THREAD_FLAGS_COMPLETE)
  89. struct printer_proto {
  90. void *gblink_handle;
  91. void (*callback)(void *cb_context, struct gb_image *image, enum cb_reason reason);
  92. void *cb_context;
  93. struct packet *packet; //packet data used by send()/receive() for tracking
  94. struct gb_image *image; // Details of the current image being sent/received
  95. FuriThread *thread;
  96. };
  97. #endif // PRINTER_I_H