LPRINTing from psBASIC on a DevTerm

I have wanted to write about this but I apparently killed my DevTerm’s “ext” module by an errant dot of solder. I was working on getting an RTC plugged into I2C bus exported on the camera port. There is a spec of a capacitor that apparently I splashed a micro dot of solder on, of course turning it into a “trace”. :cry: Well after my failed attempt to contact Clockwork in the support forum and then a two week long wrestling match with them via email, a replacement board arrived!!! :partying_face:

So now I can write about printing on the thermal printer using psBASIC, with confidence. This ties into two other topics I wrote:

  1. I have created "Pi Shack BASIC"
  2. Printing with human sized characters

Printing to a “printer” is done with the BASIC LPRINT command, so named because we used to call them “Line PRINTers”, the idea being that the hardware worked with a line at a time. In that light most modern printers are best described as “Page Printers”, since they work on a page at a time. This is especially true of laser printers due to the mechanics of rolling toner on to a sheet of paper and then melting it to affix it there.

Printing on the thermal printer in psBASIC is pretty straight forward. To get setup you use the OPTION LPRINT command to connect the LPRINT command with your particular printing device and / or software. As explained in the DevTerm documentation we can connect to their printer through their software via the /tmp/DEVTERM_PRINTER_IN symlink. Technically we could also use the command to print to the CUPS driver, but why waste even more compute resources.

The command is this:

OPTION LPRINT "/tmp/DEVTERM_PRINTER_IN"

In theory that is all you need. But #2 above comes into play and to be useful we need to explain to their driver we want printing suitable for something other than microdots. So going back to topic #2 above we need to format the control codes in psBASIC like this:

LPRINT chr$(27);"!";chr$(1);chr$(29);"!";chr$(3);

The trailing semicolon (‘;’) is to prevent burning a line of paper every time this code is run.

Here is a more verbose program with a print example, some useful subroutines and documentation:

 10 ' Setup `LPRINT` to go to the DevTerm printer
 20 OPTION LPRINT "/tmp/DEVTERM_PRINTER_IN"
 30 ' Setup human size fonts
 40 norm_prt
 50 ' LPRINT the standard test message 3 times
 60 FOR x=1 TO 3
 70    LPRINT "The quick brown fox jumped over the lazy dog";x;"times!"
 80 NEXT
 90 feed
    
130 SUB feed : LPRINT string$(14,10) : END SUB : ' 15 LFs - feed for tear off
140 SUB norm_prt : print_size(3) : END SUB
150 SUB large_prt : print_size(4) : END SUB
160 SUB small_prt : print_size(2) : END SUB
    
170 ' NOTE: invisible characters screw up TAB() operation.
180 ' NOTE: print driver does not understand CR
190 ' Font sizes: 0-4, 3 is readable
200 SUB print_size(sz%)
210    LPRINT chr$(27);"!";chr$(1); : '   Select UNICODE font
220    LPRINT chr$(29);"!";chr$(sz%); : ' Select font size
230 END SUB

NOTE: psBASIC doesn’t need line numbers. I used them here to make discussing the code simpler. I also told psBASIC to format it so keywords are capitalized. I like this since I don’t like twiddling the caps lock and I type most things in lower case. The capital keywords then become a poor man’s syntax-highlighting. :laughing:

Lines 140-230 are a suite of subroutines that are likely to be useful for working with the printer. They consist of three print sizes:

  • ln140 norm_prt: normal size print
  • ln150 large_prt: the largest sized print
  • ln160 small_prt: the smallest print I can almost read without a magnifier. :smiley:

ln200-230 is the engine behind those, taking a raw font size number (0-4). ln130 prints a useful number of blank lines, at norm_prt size that allows tearing the paper tape off, analogous to a “form feed”. Note the remark says there are fifteen and the string$() function only calls for fourteen. The extra one is the default action of the LPRINT command, unless it ends with a semicolon (‘;’).

ln10 sets up the LPRINT command. ln40 sets human sized print. and lns60-80 print the traditional test lines. Finally ln90 feeds the tape out to be torn off.

With these simple subroutines you can use the DevTerm to log all manner of data onto the thermal paper.

NOTE: Using a teensy print size, like “0”, could be useful for low res graphing or graphics. Break out your “ASCII art” hat!

Since the DevTerm has a built-in printer, assuming you haven’t removed it ;-), it makes sense to have psBASIC boot up already connected to it. When psBASIC starts it looks for a BASIC program named ~/.psbasic.bas. This has the same purpose as something like BASH’s ~/.bashrc or the more generic ~/.profile. It is loaded at start by psBASIC and can pretty much do anything psBASIC will do. But not all things are useful. Like, don’t put a SYSTEM command in it. psBASIC will simply appear to crash out at every start. I usually do a few things with my ~/.psbasic.bas, even setting screen colors to a blue background, with white text, just like my MSX machine (SV-328 & SV-318) had back in the day. :slight_smile:

A sample file might look like:

10 OPTION LPRINT "/tmp/DEVTERM_PRINTER_IN"
20 LPRINT chr$(27);"!";chr$(1);chr$(29);"!";chr$(3);
30 vm.case(-1)  : ' Format keywords in UPPER case
40 vm.indent$("   ") : ' Indent by three spaces
50 ENVIRON "EDITOR=geany -si"
   
60 IF command$(0)="" THEN
70    COLOR 7,1 : ' white on blue color scheme.
80    CLS : ' clear and paint the screen with the colors
90 END IF

ln10-20 sets up the LPRINT command and printer as discussed. ln30-40 set my preferred code formatting options. These affect how psBASIC writes out code in LIST, EDIT and SAVE commands. It also affects code shown during an error. ln50 sets the environment variable EDITOR to geany -si. This environment variable sets the editor command used by psBASIC’s EDIT command to allow you to edit your code. I prefer to set this in my ~/.profile so that all terminal tools have the opportunity to know my editor preference. This is especially useful with git commit ..., crontab -e, … You could set this to nano, joe, vm, emacs, … or any GUI editor that takes a file name on its command line, assuming you are running psBASIC under X (the default for DevTerm).

But if you want psBASIC to have its own setting then putting it in the ~/.psbasic.bas is the solution. ln60 and the terminating ln90 create an area that is only executed if psBASIC was launched interactively. If psBASIC was launched with a program file on the command line or via the “shebang” (‘#!/usr/bin/psb’) then command$(0) won’t be empty. I use ln70 and 80 to set my preferred color scheme for interactive mode.

NOTE: You could use IF environ$("DISPLAY")<>"" THEN ... to detect when running under X. If $DISPLAY is empty (“”) than an X server is not normally available. Otherwise it usually is, unless someone is messing with your environment. I also use this technique in my ~/.profile to intelligently set $EDITOR to a GUI or terminal based editor.

A note about BASIC program names: The “.bas” extension is not a mandatory extension for psBASIC programs. It is voluntary like “.sh” for shell scripts. I use it for convenience, occasionally vasilating to a shorter “.b”. But for me old habits die hard and I’ve written a ton of “.BAS” file names over the years.

NOTE: Lots of additional information of the commands and functions covered here are available with the HELP command within psBASIC or the reference manual (professional edition).

NOTE: Additional psBASIC resources and the free edition of psBASIC are available at the Pi Shack. The free edition is capable of everything covered here. Information on the inexpensive “professional” edition is also available there.

Anyhow I’m now ready to write time logs to receipt tape or maybe even a cash register app! Maybe a WiFi signal grapher, … :smiley:

3 Likes