How to print the characters in an ESC/POS printer code page

I’ve been working on software that interacts with ESC/POS receipt printers for some time, and a constant source of trouble is the archaic character encoding scheme used on these printers.

Most commonly, non-ASCII characters are accessed by swapping the extended range to a different 128-character code page. The main open source drivers (escpos-php and python-escpos) are both capable of auto-selecting an encoding, but they need a good database of known encodings to power this feature for each individual printer.

Today, I’ll share a small utility that can print out the contents of a code page, like this:

A printer’s documentation vaguely labeled this encoding as “[1] Katakana”. By printing it out, I can see that if I map single-byte half-width Katakana from Code Page 932, it will appear correctly in this code page. That’s type of information you need when you’re asked about it on an issue tracker!

Usage

You will generally find a list of code pages with a corresponding number for each one (0-255) in an ESC/POS printer’s documentation.

This command-line tool then takes a list of code pages to inspect, and will output raw binary that generates a table like the one above when sent to the printer:

php escpos-caracter-table.php NUMBER ...

So to print the code pages 1, 2 and 3 to a binary file, the command would be:

php escpos-character-tables.php 1 2 3 > code-page-1.bin

Next, you need to know how to do raw printing. Raw USB printing on Linux typically works like this:

cat code-page-1.bin > /dev/usb/lp0

For other platforms, it will be different! You will need to do a bit of research on raw printing for your platform if you haven’t tried it before.

The code: escpos-character-tables.php

<?php
/**
 * This standalone script can be used to print the contents of a code page
 * for troubleshooting.
 *
 * Usage: php escpos-caracter-table.php NUMBER ...
 *
 * Code pages are numbered 0-255.
 *
 * The ESC/POS binary will be send to stdout, and should be redirected to a
 * file or printer:
 *
 *   php escpos-caracter-table.php 20 > /dev/usb/lp0
 *
 * @author Michael Billington < michael.billington@gmail.com >
 * @license MIT
 */

/* Sanity check */
if(php_sapi_name() !== "cli") {
    die("This is a command-line script, invoke via php.exen");
}
if(count($argv) < 2) {
    die("At least one code page number must be specifiedn");
}
array_shift($argv);
foreach($argv as $codePage) {
    if(!is_numeric($codePage) || $codePage < 0 || $codePage > 255) {
        die("Code pages must be numbered 0-255");
    }
}

/* Reset */
$str = "\x1b@";
foreach($argv as $codePage) {
    /* Print header, switch code page */
    $str .= "\x1bt" . chr($codePage);
    $str .= "\x1bE\x01Code page $codePage\x1bE\x00\n";
    $str .= "\x1bE\x01  0123456789ABCDEF0123456789ABCDEF\x1bE\x00\n";
    $chars = str_repeat(' ', 128);
    for ($i = 0; $i < 128; $i++) {
        $chars[$i] = chr($i + 128);
    }
    for ($y = 0; $y < 4; $y++) {
        $row = "" . " ";
        $rowHeader = "\x1bE\x01" . strtoupper(dechex($y + 8)) . "\x1bE\x00";
        $row = substr($chars, $y * 32, 32);
        $str .= "$rowHeader $row\n";
    }
}

/* Cut */
$str .= "\x1dV\x41\x03";

/* Output to STDOUT */
file_put_contents("php://stdout", $str);

3 Replies to “How to print the characters in an ESC/POS printer code page”

  1. Hi Mike, im using your php-escpos soft, works execelent . but one problem i have is i cannot print anything above chr 127. any char i send comes out as a chinese character, no matter what codepage i set. i get different characters with different codepages, but everything is chinese complex characters

    is there a way to load different data into the resident character table ? or a user codepage or something ?

    thanks in advance
    Juanjo

  2. Hello,

    I am trying to get your script to work with one of these cheapo 58mm chinese thermal printers, but it won’t change the codepage and print garbage, there seem to be some wrong “n” at the end of some lines in the script. Can you please take a look and tell if if it’s the script or the printer?

    Thanks,
    Volker

  3. @Volker – It looks like my blogging platform removed the backslashes from this script at some point. I’ve corrected it now.

Leave a Reply

Your email address will not be published. Required fields are marked *