Skip to content

Commit

Permalink
First release
Browse files Browse the repository at this point in the history
  • Loading branch information
tinue committed Nov 11, 2023
0 parents commit 895b3eb
Show file tree
Hide file tree
Showing 83 changed files with 4,824 additions and 0 deletions.
24 changes: 24 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# IDE
.idea/
target/
*.iml

# Compiled class file
*.class

# Log file
*.log
Hp8224-Image.png
Hp8224-Text.txt

# Package Files #
*.jar
*.war
*.nar
*.ear
*.zip
*.tar.gz
*.rar

# Mac OS
**/.DS_Store
674 changes: 674 additions & 0 deletions LICENSE

Large diffs are not rendered by default.

124 changes: 124 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
# hp82240

# General

The Java based HP 82240 is a command line printer simulator for the Hewlett Packard HP-82240A/B
infrared printer. It will decode printer commands received via a serial port, and produce
a text and a bitmap file.

The printer commands are text strings, escape sequences and line feeds, encoded in a character
set as defined by HP. See [Printer Character Sets](documentation/charactersets/charactersets.md)
for details.

Note that the simulator does not understand the raw infrared pulses generated by the
HP calculators. It needs special hardware (see below) that interprets these pulses and
converts them into bytes.

The output of the simulator consists of two files:
* `Hp8224-Text.txt`: Any text that was sent to the printer, converted from the HP character set into UTF-8.
* `Hp8224-Image.png`: Text and graphics as they would look on the printer paper.

To illustrate, see the actual printer on the left, and the generated bitmap file on the right:

| Printer | Simulated Output |
|-------------------------------------------------------------------------------------|--------------------------------------------------------------------------------------------------------|
| <img src="documentation/pictures/HP82240A.jpg" width="320" alt="HP 82240A printer"> | <img src="documentation/pictures/HPSelfTestFromSimulator.png" width="320" align="top" alt="Self Test"> |

More examples are available [here](documentation/examples.md) and
[here](documentation/validation/validation.md).

# Acknowledgements
* Thanks to <a href="http://hp.giesselink.com/">Christoph Gießelink</a>: He develops
a Windows based simulator of the HP printers 82240A/B and 82143A. The bitmaps for the
printer characters directly come from this simulator (See
<a href="https://www.hpcalc.org/details/7386">hpcalc.org</a>
for the full source code)
* Thanks to [Martin Hepperle](https://www.mh-aerotools.de): He developed the first
"Red Eye" reader, see "Hardware" section below.
* Thanks to [Meindert Kuipers](https://www.hpmuseum.org/forum/user-215.html): His version
of the "Red Eye" receiver is the one that I am using.
* Thanks to Christian Vogel; His [avr-redeye](https://github.com/vogelchr/avr-redeye) project allowed me to send any print commands
that I like to my real HP 82240A printer and observe its behaviour.

# Installation
Copy the `hp82240.jar` file to a convenient location. Make sure to have a Java 17 or higher
runtime available on your system. Then, start the simulator with:
`java -jar hp82240.jar [-p=comport]`
This will start the simulator and open the com port for reading. Any existing output files
(`Hp8224-Text.txt` and `Hp8224-Image.png`) will be overwritten on application startup.
When you are done with your session stop the simulator with `Ctrl-C`. Save away the output
files for later use.
If you omit the com port, the simulator will attempt to auto-detect the correct port.

## Quick testing
For some quick testing, the simulator can work with input files. To produce a self test,
one can use this: `java -jar hp82240.jar -i selftest.yaml`. The files are the same ones as used
in the Red Eye sender (see below). The file format is not explicitly documented, but should
be self explanatory when looking at the provided samples.

## Receiver Hardware
To receive the infrared pulses from an actual calculator, and convert this data to a serial stream,
special hardware is required. I built a receiver based on
[this](https://www.hpmuseum.org/forum/thread-14858.html) guideline, which in turn is a
modified version of
[this](https://www.mh-aerotools.de/hp/red-eye/HP-IR%20Receiver%20with%20Arduino.pdf)
guideline.

# Comparison with other simulators
This simulator is currently limited in functionality, supporting only the HP 82240A/B printer,
and lacking a graphical user interface. Its main advantage is that it runs on all platforms
supporting a Java 17 or higher runtime, including ARM devices such as the Raspberry Pi.

# Validation on a real HP82240A printer
To [validate](documentation/validation/validation.md) and compare any output generated by
this simulator with the output from a real
HP 82240A printer, one needs to be able to send very specific strings / graphic codes to
the printer. The real calculators are only of limited use here, because their firmware
prevents certain issues to happen. For example, lines that are too long (longer than the
printers buffer) get Line Feeds added by the firmware.

Therefore, a tool has been developed that allows to send any sequence of bytes that one wants
to a serial port. On this serial port a piece of hardware is required that generates the
"Red Eye" pulses that the printer understands.

## Sender Hardware

I am using this project with an Arduino clone and a simple IR diode:
[avr-redeye](https://github.com/vogelchr/avr-redeye). The project is a few years old, but it works perfectly right out of
the box. Note that you can't use the Arduino IDE to compile / send, because this is pure
C code and not an Arduino sketch. On the Mac I installed two tools:
* `brew install avrdude`
* `brew install avr-gcc`

I had to slightly adapt the `PROGRAMMER_DUDE` part of the `Makefile`
to
`PROGRAMMER_DUDE = -P/dev/cu.usbmodem4101 -carduino -b57600`, and then it worked right away.

For the first test I used a genuine Arduino Uno, and found that this device sends spurious
bytes (`0xF0`) when the serial port gets closed (which happens automatically at the end of
the application). So if you see strange characters on your printer, try with a different
type of Arduino. Here is the device that I am using now:

<img src="documentation/pictures/Sender.jpg" alt="IR Sender">

## Sending print commands

The tool is invoked as follows:
`java -cp hp82240.jar ch.erzberger.emulation.sender.RedEyeSender`. It will then tell you
the necessary parameters. Some sample files are provided in the
`documentation/sampleoutput` directory.


# Stdin, Stdout
The simulator can read from Stdin instead of from a serial port. Use this if you have e.g.
an emulator of a calculator that sends print output to Stdout. To test, use the RedEyeSender,
sending to StdOut:
`java -cp hp82240.jar ch.erzberger.emulation.sender.RedEyeSender -p=stdout -i=selftest.yaml | java -jar hp82240.jar -p stdin`

# License
HP82240 - A Java based HP 82240A/B Printer Simulator
Copyright (C) 2023 Martin Erzberger.

This program is free software; you can redistribute it and/or modify it under the terms
of the GNU General Public License Version 2 or any later version, as published by the Free
Software Foundation.
Binary file added documentation/aspect/HP82240a.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added documentation/aspect/Laserprinter.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added documentation/aspect/Preview.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added documentation/aspect/QuickView.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added documentation/aspect/Rectangle.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added documentation/aspect/Rectangle.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
57 changes: 57 additions & 0 deletions documentation/aspect/aspect-ratio.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
# Aspect Ratio and Pixel Dimensions

## The HP 82240A Printer

The HP 82240A printer has somewhat oval / rectangular pixels, because it is an analog device. Also,
horizontal neighbouring pixels tend to bleed over because the printer head can't cool down quickly enough.

This is how the printout looks under a microscope:

<img src="HP82240a.jpg" width="160">

## Digital pixels

Digital pixels are abstractions that only become visible when shown on a device, or printed out on
a computer printer. How these pixels are represented differs from device to device, and from application
to application. Here are just three examples of the same letter "i".

| Quick View | Preview | Laser |
|---------------------------------------|-------------------------------------|------------------------------------------|
| <img src="QuickView.png" width="200"> | <img src="Preview.png" width="200"> | <img src="Laserprinter.jpg" width="200"> |

The laser-printer shows the closest result, because the aspect ratio is actually correct. Unlike the
HP printer, the vertical pixels merge together, though.

## One pixel per pixel, or many?

Because the original HP 82240a pixels are not perfect squares, the simulated printer output might look
different from the original. One can deal with this in two ways:
1. Use multiple pixels to assemble small ovals, and then use one oval for each printer pixel. For absolutely
perfect results, one would need different ovals, depending on the neighbouring pixels.
2. Use one pixel per printer pixel, and define at least the correct aspect ratio in the file's metadata.

Option one gives the closest look to the original, at the cost of increasing the file size significantly, and of
limiting the flexibility in using the resulting file. Because there is no universally "better" option,
it would be best to support both options and have the user decide.

For now, only option two is supported, though. The rest of this document explains how the aspect ratio and the
pixel density have been determined.

## Figuring out the pixel dimensions of the HP 84440a printer

First, we print a perfect 166 x 166 pixel rectangle, using the file [dimensions.yaml](../sampleoutput/dimensions.yaml).

The printed output can then be measured, and the resulting width/height is:
* Width: 46.1mm, which is 92dpi horizontal resolution
* Heigth: 55.2mm, which is 76dpi vertical resolution

These dpi values are written into the `png` output file as metadata. As one can see above, the laser-printer
uses the annotation to correct the aspect ratio of the printout.

So far I found no application or browser that will correct the aspect when displaying the image on screen.
Please let me know if the left picture (from the simulator) looks the same as the right one
(from the HP 82240a printer).

| Simulator | HP 82240a |
|---------------------------------------|---------------------------------------|
| <img src="Rectangle.png" width="300"> | <img src="Rectangle.jpg" width="300"> |
Binary file added documentation/charactersets/Focal.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added documentation/charactersets/HP82240A-Roman8.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added documentation/charactersets/HP82240B-RPL.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added documentation/charactersets/HP82240B-Roman8.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
44 changes: 44 additions & 0 deletions documentation/charactersets/charactersets.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
# Printer Character Sets

## Acknowledgment
Creating a bitmap character set is tedious work. It needs to be assembled dot by dot
from enlarged original printouts. Luckily, I did not have to do this. The bitmaps
are copied from [Christoph Gießelink's](http://hp.giesselink.com/) simulator, available
[here](www.hpcalc.org/details/7386).

I performed my own validation with enlarged printouts, and found a number of differences
in the HP 82240A's Roman 8 character set (e.g. in the number "3", or the letter "J").
These have been changed to match the original printer.
TODO: Validate the two HP82240B character sets.

## HP Modified Roman 8 Character Set
The original HP 82240A printer uses a modified HP Roman 8 character set. See
[Wikipedia](https://en.wikipedia.org/wiki/HP_Roman#Modified_Roman-8) for details.
The successor HP82240B also supports this character set, in order to be compatible
with the A model. Even though the B model supports the same charset, it is rendered
quite differently. For example, all capital letters haven been shortened by one row
compared to the A model.

## RPL Character Set
The newer HP 82240B model additionally supports the "RPL" character set, see
[Wikipedia](https://en.wikipedia.org/wiki/RPL_character_set). This character set is used by HP calculators that came after the HP 28,
such as the HP 48 or 50 series.
This character set is enabled with `ESC-0xF9` and disabled with `ESC-0xF8`.
The "A" model ignores this escape sequence.

## Examples (generated by the simulator)

| HP 82240A Roman 8 | HP 82240B Roman 8 | HP 82240B RPL |
|---------------------------------------------|---------------------------------------------|------------------------------------------|
| <img src="HP82240A-Roman8.png" width="300"> | <img src="HP82240B-Roman8.png" width="300"> | <img src="HP82240B-RPL.png" width="300"> |

## FOCAL character set
The FOCAL character set (see [Wikipedia](https://en.wikipedia.org/wiki/FOCAL_character_set)) is
used by the HP 41C calculator and its printer, the HP 82143A. It contains 128 characters.
The simulator does not currently support this printer. The character set is part of the
class "HpPrinterFonts", but it's not currently in use. The bitmaps for the characters were
converted from the original printer ROM, see the `CharRomToJavaArray.java` file for more details.

| Focal Characterset |
|-----------------------------------|
| <img src="Focal.png" width="300"> |
57 changes: 57 additions & 0 deletions documentation/examples.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
# Example outputs
## Screenshot from an HP 50g calculator
The HP50g calculator can send a screenshot to the printer. For this to work, the
print output must be directed to infrared ("Mode", "Flags": Number 34 must be "Print via IR").
To print, press "APPS", "2", "Enter", "3", "Enter".
All of the output is sent in graphics mode, even if it appears to be text or numbers.

|Calculator|Printer Output|Simulator Output|
|-|-|-|
|<img src="pictures/HP50g.jpg" width="340">|<img src="pictures/ScreenshotFromPrinter.jpg" width="640">|<img src="pictures/ScreenshotFromSimulator.png" width="640">|

## Self test
The printer can perform a self test. This is initiated by holding the paper feed key while
turning on the printer, or by sending ESC + 0xFE to the printer. The self test is emulated
as well, and will output both a text file and a png file. The text file is in UTF-8 and
contains all of the printer's characters.

|Printer Output|Simulated Output|
|-|-|
|<img src="pictures/HPSelfTestFromPrinter.jpg" width="640">|<img src="pictures/HPSelfTestFromSimulator.png" width="644">|

This is the emulated self test output in text form:
[SelfTest.txt](pictures/SelfTest.txt)

## HP 41C Printing
The original printer for the HP 41C calculator is the HP 82143A. This printer is connected via
cable to one of the expansion slots. The connector also contains the printer commands
in ROM, such as `PRA` or `PRPLOT` (see below). This printer supports 128 characters, numbered
from 0 to 127.

The HP 82240A came later, and contains a different character set. It has printable characters
from 32 up to 255. To print to this printer, an IR emitting diode is needed, which is plugged
into an expansion slot of the HP 41C (the HP 82242A module). Just like with the 82143A
printer, this module contains the printer ROM.

Even though the newer printer has more printable characters, the older printer still has
about 15 characters that do not exist on the newer printer. The ROM takes care of some things:
* It translates the 82143A character codes into equivalent 82240A codes
* It converts the flag for double wide into escape sequences
* For three of the not existing characters (up and down arrow, and diamond), it transparently
uses the 82240A graphic mode to generate the output. This routine seems to be buggy,
though, because if a full line of 32 characters is printed, the last two do not print
correctly.
* The other unsupported characters are replaced with a `¤` character.

## PRPLOT
The [HP 82143A printer manual](https://literature.hpcalc.org/community/hp82143a-oh-en.pdf)
explains how to use the interactive plotting function of the printer ROM. The interesting
part is that the printer ROM of the DM41X uses a mix of text and graphics output,
because it simulates non existing characters via graphics mode (see paragraph above).
This is the text output: [Prplot-Wiggle.txt](pictures/Prplot-Wiggle.txt). Note that it misses
the down arrow on the second line, because this arrow is generated in graphics mode. The
right arrow on line 3 is visible though, because this arrow is part of the character set
of the 82240A printer.

The simulated output is here:
<img src="pictures/Prplot-Wiggle.png" width="320">
39 changes: 39 additions & 0 deletions documentation/hp82240.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
# Facts about the HP 82240A printer
## Paper and Print head
* One line (head movement) has 166 columns and is 8 pixels high.
* Lines are printed directly adjacent, i.e. in graphics mode, 100% of the paper can be covered
* One character box is 5x8 dots. Usually the bottom row is not filled, so that the rows look separated.
* Some characters use the bottom row, e.g. "g" or other chars with descenders.
* Left and right of a character a blank column is printed, except left- and rightmost column.
* 24 chars fit on a line (22 times 7 plus 2 times 6).
* Underline mode fills the bottom row, no matter what (also space between chars and graphics mode).
* Double wide prints each column twice, no matter what (chars, space between chars, graphics bytes)
* 12 double wide chars fit on one line (10 times 14 plus 2 times 12), leaving two pixels empty at the end

### Questions
* Can the 2 pixels be filled after 12 double wide chars?
* If 2 pixels are inserted in-between, will the last char print or overflow?
* Will a char overflow in total, or will it be vertically split?

## Buffer
* Print buffer is 200 bytes
* Printing will start (and the buffer starts to drain) when a line feed is received
* After max. 1.8 seconds the line is printed and the buffer for the line is empty
* Once the buffer overflows, this happens:
* As soon as space is available, a special "overflow" marker is put into the buffer
* After this, everything is thrown away until a linefeed is received.

### Questions
* Some sort of special character is printed when the buffer overflows. How does it look?
* What happens if >200 chars are sent without a line feed? There is no room for the special overflow char.
* Does the linefeed itself count against the 200 bytes?

# Timing
* One byte needs 12.82 Milliseconds to transmit (roughly 78 bytes / sec).
* A full line of graphics (166) will need 2.13 Seconds, i.e. more than the printer needs to print.
* One line of regular text needs 308 Milliseconds to transmit, and 1.8 Seconds to print. Even with
line feeds after 24 chars, the buffer will eventually overflow.

### Questions
* Can graphics lines really be sent at full speed? Note: The Arduino also has a limited buffer, and
with 115200 bits/sec this buffer can easily overflow.
Binary file added documentation/pictures/HP50g.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added documentation/pictures/HP82240A.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added documentation/pictures/HPSelfTestFromPrinter.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added documentation/pictures/Prplot-Wiggle.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
44 changes: 44 additions & 0 deletions documentation/pictures/Prplot-Wiggle.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@

PLOT OF WIGGLE
X <UNITS= 1.>
Y <UNITS= 1.> →
-1.10 1.10
0.00
-----------------
0. ×
10. ×
20. ×
30. ×
40. ×
50. ×
60. ×
70. ×
80. ×
90. ×
100. ×
110. ×
120. ×
130. ×
140. ×
150. ×
160. ×
170. ×
180. ×
190. ×
200. ×
210. ×
220. ×
230. ×
240. ×
250.×
260.×
270.×
280.×
290.×
300. ×
310. ×
320. ×
330. ×
340. ×
350. ×
360. ×
Binary file added documentation/pictures/ScreenshotFromPrinter.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added documentation/pictures/ScreenshotFromSimulator.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading

0 comments on commit 895b3eb

Please sign in to comment.