Summary:
Having gotten the peripheral devices supported and abstracted, I'm on to implementing the higher-level objects. The first one I'm tackling is the interpreter/processor of the HP Printer IR data stream. This will maintain the logical state of the printer (current options like font, wide char, bold/underline, X position).
I am working on implementing the rasterizer of the HP printer data, which will create a bitmap image representing one line of output.
Deets:
Since the printer language the HP printer uses is quite different than that of the receipt printer (also the implied character sets), I've decided to treat everything graphically. This means first rasterizing the HP printer's output to an image, and then outputting that image to the receipt printer in it's native tongue.
The HP 82240B printer has two character sets (the -A had only one, so it's emulation is therefor supported as well), so I'm going to have to go through the tedious process of creating the font for the 256-32=224 X 2 fonts = 448 characters. *sigh* On the positive side, I had completed some character blitting code for a different project a couple months back, so I will reuse that, along with the font format I came up with. It's richer than I need for this, but 'done' is 'done', and there's so much other stuff to do. Also, I'll need to modify it to handle 'wide' mode and 'underline' as well. So there's still some new work to do in that area.
While I was somewhat dreading this activity as tedium -- and it will be -- there are several simplifications that I can avail myself to in this case. In particular, the HP printer is a line-by-line device, so I only need to rasterize one line's image before emitting it to the physical printer. Additionally, since the HP printer is principally a 5x7 text mode printer (i.e. 6x8 with the inter-character -line spacing), and graphics commands simply set a vertical column of pixels, this means that all my clipping logic will be trivial. Yay, it's the small things in life.
So really, I think that generating the font data is going to be the bulk of the work for this step.
I'm reusing a font format I concocted for a previous project. The gist of it is:
- a header with meta info
- an array of character descriptors; so variable character width is supported, along with partial character sets (and UCS-2LE if you really need it)
- an array of glyph bitmaps for those characters
This is certainly overkill for what I need here, but again, I've already written the code for blitting the characters and I'd really rather reuse that than write yet another blit routine.
FWIW, the font header is defined as:
ypedef struct FONT_HDR FONT_HDR;
struct FONT_HDR
{
uint32_t _nSignature; //indicates this is a font object
uint32_t _nVersion; //format version
uint32_t _nFlags; //various flags
uint16_t _arraylen; //how many glyphs in this font
uint16_t _height; //common glyph height (pel)
};
The signature looks like 'FONT' in a hex editor. The version is 1. The flags indicate the packing of the glyphs (byte, word, dword), whether it is MSB/LSB first, and whether the glyph is mirrored in X and/or Y (not needed here).
The character descriptor is defined as:
typedef struct FONT_CHARENT FONT_CHARENT;
struct FONT_CHARENT
{
uint16_t _charval; //UCS-2LE of this character
uint16_t _width; //this glyph width (pel)
uint32_t _offset; //relative offset from start of font image
};
So, to blit a character, you do a lookup of the character descriptor via binary search, and then you can determine the address of the glyph bitmap, the width, and the height for the blit operation.
For bitmaps, I generally prefer LSB first. The reason is that this gives me the freedom to choose 8-bit, 16-bit, or 32-bit IO operations directly from the buffer without having to bit shuffle. (Well, on a little-endian machine, but come on, little-endian is the one true way.) This will be a minor annoyance later when I transform the HP printer bitmap into physical printer output data, since that data is MSB first. However, doing bit reversal at that one last step will be a much simpler chore than complicating my blit routines (and reducing speed, though that is not paramount here).
As mentioned there are several simplification in this application:
- the Y address for output will always be 0, since it is one line at a time for text, and always one full column of pixels for graphics.
- only full characters will be printed, so clipping can be at the character level, meaning that a character is clipped out if the starting X position is greater than right-width. Simple logic, and no awkward buffer wrap-arounds to the next line.
- the glyph width is constant, and always one byte. This means I can implement support for single and double width simply by promoting a glyph raster line always to a uint16_t, and either copying the data verbatim (single wide), or pixel double (double wide) and the rest of the blit logic will simply work as-is. Yay!
One less obvious simplification is that by re-using my font format, I also potentially can reuse a separate tool I made that will rasterize a True Type Font into my format. Sooo... If I can find a TTF that someone might have produced already for the HP82240, then that will be a huge leg up. Otherwise I will be spending several days working with a magnifying glass to manually create bitmaps from sample printouts.
So, now I need to do a little research to try to find such a TTF out there. Who might have it? Maybe one of the calculator emulator guys might have such a thing, since they usually like stuff to be pretty. Hopefully I will score!
Next:
Aside from the font quest, I will tweak my character blitting code to incorporate the features/simplifications I mentioned, and also implement the state machine for processing the incoming HP printer data.
Ciao for now!
Discussions
Become a Hackaday.io Member
Create an account to leave a comment. Already have an account? Log In.