Skip to content

Latest commit

 

History

History

Folders and files

NameName
Last commit message
Last commit date

parent directory

..
 
 
 
 
 
 
 
 
 
 

README.md

ict_sp1

Command builder for the ICT SP1 thermal receipt printer, an ESC/POS-style printer used in kiosks and payment machines. Pure C99, no dependencies, no -lm.

This module turns high-level calls — set font, align text, print, a QR code, commit the job — into the exact ESC/POS byte sequences the SP1 expects, and emits them through a caller-supplied write function pointer. That pointer is the only seam to hardware: no I/O, no allocation, no globals. It is a port of go-ict/sp1 with the goroutine write-queue stripped out.

#include "ict_sp1.h"

static void uart_tx(const uint8_t *p, size_t n, void *cookie)
{
    (void)cookie;
    my_uart_write(p, n);
}

st_sp1 d;
sp1_init(&d, uart_tx, NULL);

sp1_init_printer(&d);                              /* ESC # then ESC @ */
sp1_print_aligned(&d, SP1_LARGE, SP1_CENTER, "SHOP NAME");
sp1_line_feed(&d);
sp1_print_aligned(&d, SP1_NORMAL, SP1_RIGHT, "TOTAL  120.00");
sp1_line_feed(&d);
sp1_qr_size(&d, 6);
sp1_qr(&d, "https://pay.example/abc123");
sp1_execute(&d);                                   /* CR commits the job */

Timing the caller owns

The Go driver used a background queue to space bytes out; this module emits immediately, so two firmware timing rules become your responsibility:

  • after sp1_execute() (a CR commits the job) leave the printer idle ~3 s before sending more bytes;
  • after sp1_qr_size() give the QR engine ~1 s before the next command.

Functions

Function ESC/POS Purpose
sp1_init(d, write, cookie) Store the output seam.
sp1_activate_escpos(d) ESC # Enter ESC/POS mode (first after power-on).
sp1_reset(d) ESC @ Restore factory defaults.
sp1_init_printer(d) ESC # ESC @ Activate + reset in one call.
sp1_disable_autoclear(d) ESC c 5 Stop buffer auto-clear on status changes.
sp1_set_font_size(d, size) ESC M n SP1_SMALL / SP1_NORMAL / SP1_LARGE.
sp1_set_underline(d, on) ESC - n Toggle underline.
sp1_highlight(d, on) GS B n Toggle inverted (highlighted) text.
sp1_print(d, text) Emit text verbatim.
sp1_print_aligned(d, size, align, text) ESC M n + spaces Set font, software-align with leading spaces, print.
sp1_line_feed(d) LF One newline.
sp1_execute(d) CR Commit the current print job.
sp1_qr_size(d, size) GS ( k … QR module size, clamped to 1..7.
sp1_qr(d, data) GS k … Emit a QR code holding data.
sp1_get_system_info(d) ESC ( T Request the printer's identification (reply on your RX path).

Alignment helpers (no I/O)

Alignment is done in software by prepending spaces, which works at every font size. Width is counted in code points, so a Thai or accented character takes one column just like ASCII.

Function Purpose
sp1_utf8_runes(s) Count UTF-8 code points in s.
sp1_align_pad(size, align, text, out, cap) Build the space-padded line into out; returns its length, or 0 if it would not fit. SP1_LEFT (or text already filling the line budget) is copied unchanged.

Per-font budgets: SP1_MAX_SMALL_CHARS 48, SP1_MAX_NORMAL_CHARS 24, SP1_MAX_LARGE_CHARS 16.

Build the self-test

make test

Builds example/check.c, runs it, prints ict_sp1: All OK. on success and exits zero. The check wires the write seam to a capture buffer and asserts:

  • every setup / styling / text / QR command emits its exact ESC/POS byte sequence (e.g. sp1_set_font_size(SP1_LARGE)1B 4D 32, sp1_qr("AB")1D 6B 48 02 00 41 42).
  • sp1_qr_size clamps to 1..7.
  • sp1_print_aligned emits the font command, then the right number of leading spaces, then the text.
  • sp1_utf8_runes counts code points for ASCII, accented, and Thai input; sp1_align_pad centres / right-aligns, leaves Left and over-budget text unchanged, and reports 0 on a too-small buffer.

Use in another project

Drop ict_sp1.h and ict_sp1.c into your sources. No other module dependencies, no libc beyond <string.h>.

License

MIT.