Wednesday, August 27, 2014

How not to do Code 39 barcodes...

I've always liked the program Photoimpact, and when fry's had it free after rebate, I couldn't resist. I hate doing rebates, especially when they make you do 3 x 30 dollar rebates. They give you the option of going to their website to "register" the rebate to speed the processing.

So I went to http://novadevelopment.com/rebate and typed in my rebate code of "UTW30", dutifully put in my details and got a form to print complete with barcode.

But the barcode wasn't done properly.




I thought it was kind of small so I tried to blow up the barcode and strangely enough, it wasn't black and white only, but had colored lines. Seriously?



Colored lines are sure to scan properly...

After some detective work, I established that it must be Code 39. However, it doesn't have the proper starting * and ending * characters.

This is what a proper Code 39 barcode looks like.




Methinks that whoever wrote the code to generate the barcode didn't bother to generate the start and stop codes and seems to have "shrunk" and scaled the barcode.

It may look like a good barcode but you always have to test with a real barcode reader...



I've got the two barcodes lined up, with the start stop code * shown below for reference.

Thursday, July 17, 2014

Serial Flow Control RTS in QBasic

Flow control is pretty important everywhere in life, and serial communications are no exception.




"Speed it up a little!"


Since my jx-80 simulator in Qbasic is slow and so is my old-school win98 laptop, it can't keep up with 9600 bps data. So I had to struggle to find a way to do it. I got a clue from the online help that had a little example of setting DTR with the INP function.

PRINT "set dtr"
x% = INP(&H3FC)
OUT &H3FC, (x% OR 1)

Well I tried this and it didn't work quite right, seeming to drop characters and get confused.

So I searched some more and came across a really nice book called "Interfacing the IBM-PC to Medical Equipment: The Art of Serial Communication" on Google Books.



On page 73 it has a nice diagram of the Modem Control Register and shows bit 0 is DTR and bit 1 is RTS. So I set and cleared the RTS and it worked great! My logic is to clear RTS when the buffer gets above 5000 bytes and set RTS when the buffer drops below 4000 bytes.

PRINT "set rts"
x% = INP(&H3FC)
OUT &H3FC, (x% OR 2)

PRINT "clear rts"
x% = INP(&H3FC)
OUT &H3FC, (x% AND (255-2))


Without the flow control, the buffer happily goes up to 65535 and overflows. Before this, I put some code in to watch the buffer when it hits 55000 and to stop drawing to the screen to speed it back up. But I think proper flow control is much better.

I think it really would not have been difficult to add commands to handle setting and clearing the RTS and DTR bits in QBASIC.



here you can see the clearing of RTS when we cross 5000 bytes and also the setting of RTS when we drop below 4000 bytes.



The picture finishes normally! The buffer display on the bottom line reads zero.

I see that on ebay they want an arm and a leg for the book. It's a good book, I'm not sure I'd pay $100-200 for it.





Anyway the latest version of my QBasic epson simulator (Epson91.BAS)



Friday, July 11, 2014

Okimate 20

Just for fun I thought I'd have a go at trying to render output from the Amiga Okimate 20 printer driver. This printer is a strange beast. Apparently, you issue ESC CHR(25) commands to reset the color to yellow, and then after you issue a CR it changes the color and prints in magenta, issue another CR and it switches to cyan. After those 3 passes you issue CR LF and then do a ESC CHR(25) again to restart the process.

It has a horizontal graphics resolution of 120 dpi for 960 pixels across. It has a 24 pin mode to print 24 pixel strips.

ESC % O puts you into graphics mode and then byte0 and byte1 for the number of horiz pixels (byte0 + byte1*256). Following this you have 3 bytes for each 24 dot vertical pixel strip.

I can feel the virtual thermal ribbons burning a hole in my virtual pocketbook as it renders the prints. Goodness, they must have been expensive to print full page graphics. 3 pages must have about wiped out a single ribbon. Reminds me of my old Casiowriter thermal typewriter that had these film ribbon cartridges that would be good for about 10 pages.

If you're curious I got the information about the printer from:

http://www.myokidata.com/om20ibm.nsf/InsideUsersManual

I think I only implemented 3 codes: ESC CHR(25), ESC %O, and ESC J (advance n/216).

All the ESC programming codes are nicely summarized on this page:

http://www.myokidata.com/om20ibm.nsf/MOCContents/F5982DA819FFFAAF8525634800547D3D?OpenDocument





Okimate 20 javascript interpreter

Thursday, July 10, 2014

Getting the Amiga to print to the Imagewriter 2

I got winuae to print to the windows com port hooked up to my old laptop running a simple qbasic serial capture program. Running "graphicdump 640:512" does a pretty good rendition of the 640x256 workbench screen at 640x512 printer resolution.




A simple QBasic program to capture the serial port data and write to a file.


I suppose I could always use the CMD utility on the Workbench disk to redirect the Amiga printer output to a file. But where's the fun in that?

Wednesday, July 9, 2014

ImageWriter Interpreter

I always liked the Apple imagewriter printers, probably because we used them at school, and because they were always closely matched with the apple ii. So I thought I'd see if I could interpret some of their ESC codes. The code just implements enough to make some pictures and maybe some pica 10 cpi text.

I seem to have some trouble getting the full 8 bits of data out of the Apple II version of the New Print Shop running under emulation. I was using AppleWin under Wine under knoppix to output the data. It probably didn't help that the New Print Shop would crash when trying out some of the different interface cards. I look at the data and it seems to be missing the high bit (MSB) and the maximum value has 7F.

The code is really ugly with plenty of vestigial junk from my jx80 interpreter. Again, just a proof of concept, and more for fun than anything else.

Looking closely at the ribbons I notice that they have Red, Blue and Yellow to make RYB colors, not CMYK. But I'll cheat a little and treat it as CMYK anyway. I can't wrap my head around the RYB to CMYK conversion just now.

It's interesting that the CUPS linux drivers don't seem to support the color printing ability of the Imagewriter II. Windows doesn't seem to support the color printing capability either with the C.Itoh 8510 driver. Where's the color printing love??? Maybe it's just too low-resolution. *sigh* Next step: Fire up winuae and see if I can make some color printouts.

Runs best under chrome, ok under firefox/iceweasel, and probably terrible under internet explorer (because I don't test it with internet explorer).




imagewriter javascript




Monday, June 30, 2014

Epson LQ-2550 interpreter

I wanted to generate some epson dot matrix color output in linux but it was much harder than I planned. For one thing, CUPS didn't want to let me output to a file. So I had to edit /etc/cups/cups-files.conf, adding the line "FileDevice Yes". Then I could set a destination device of "file:///home/knoppix/file_print_output.bin".


The drivers don't seem to want to make color output for most of the epson printers. However, I was able to find a couple of printers that would generate color with the epsonc driver. The Epson LQ-2550 and the Fujitsu 2400 or Fujitsu 3400. I wrote an interpreter that would render the printer test page as a proof of concept. It is by no means complete as it only implements just enough ESC codes to work.













Epson LQ-2550 Javascript Interpreter

Sunday, June 29, 2014

Running in molasses with firefox and getImageData(x,y,1,16)

I don't know why firefox is so slow processing in 1x16 chunks. Anyway, here's the slow version of the JX-80 javascript interpreter.

JX-80 Javascript Interpreter SLOW VERSION

Saturday, June 28, 2014

Epson JX-80 Javascript Interpreter

After writing a Epson JX-80 graphics interpreter in QBasic, I figured that I should make one in javascript. It only interprets the ESC L 120 dpi graphics and not regular text printing. If I wanted to do regular text I reckon I'd have to duplicate the Epson font in the rom. The manual gives a full table of the rom characters if I remember correctly.

I did find some javascript problems with firefox. Performance under firefox was abysmal when I was using canvas2d getImageData(x,y,1,16). It was horribly slow, in fact totally unusable. After trying to get it to work with firefox and failing, I tried Chromium and it absolutely flew in comparison. The slowdown under firefox was around 100x slower.

My workaround is to use getImageData on a larger block size and that seemed to help tremendously.

Another bug is that firefox seems to have some numerical precision problems as I get a single pixel blank line gap near the bottom of my text sample. Again, Chromium doesn't have this issue.


I can't figure out why it has a gap here...




When I have more time, I may make it work on more than a single page at a time so that when it hits an FF it'll clear the canvas for the next page in the stream. Maybe I'll also upload the super-slow version that brings firefox to a crawl so you can see the difference.



Sample text rendered with firefox, note the gap in the last line of text.



Chromium renders the sample text perfectly, with no gap line.



JX-80 Javascript Interpreter

Wednesday, June 25, 2014

Epson JX-80 simulator

I always lamented the day that my Epson JX-80 died back in 1994. I really liked that printer because it was a color dot matrix. Today, we have color inkjets and color laser printers, but back then, the JX-80 was awesome. Even more awesome was that the Amiga printer drivers supported the JX-80. I used to love printing my DeluxePaint creations in color.

I remember the day I brought it home, hooked it up and printed graphics in color for the first time. Wow! Somehow everything was more precious in those days. I think our brains are wired for scarcity, not for abundance.

After writing a simulator for the ptouch, I thought, why not try a regular dot matrix printer. So I tried the Panasonic KX-P2123. It was pretty easy, as all I had to implement was the ESC * command (at 180 dpi) and a few other ESC codes.

Since I had the benefit of a esc p reference document it was quite straightforward.

https://files.support.epson.com/pdf/general/escp2ref.pdf

Then I thought, why not try the Epson JX-80? I ran it a few times to see what codes I hadn't implemented and saw that it printed graphics using ESC L which is 120 dpi horizontal graphics at 72 dpi vertically. The printer printhead is 72 dpi and it shifts it down 2/216 of an inch and prints again to make 144dpi vertically. So I added an interleave so that it would print a row spaced with lines spaced 2 apart, then fill in the gaps on the next pass.

I also noticed that the driver printed 4 passes for color, CMYK. I pondered on how to implement that.

Fortunately the VGA color palette for SCREEN 12 has CMYK colors.

cyan = 3
magenta = 5
yellow = 14

red = 4 (m+y)
green = 2 (c+y)
blue = 1 (c+m)

black = 0 (c+m+y)
white = 7

so all I had to do was to make a function that would convert CMY into a vga screen color. When I would print a color, I just take the screen pixel, convert that color into CMY, "add" the C,M, or Y that I'm printing by doing a binary OR for each color component (c = old c OR new c), and the PSET the pixel back to the screen, converting CMY to a vga screen color. If we are printing black, treat that as setting C,M and Y.


Once I figure out how to speed it up, either by rewriting it with more table lookups or using QB64, I'll hook it up to my Amiga and try to generate some "retro" output.

Since it's rather slow, it won't keep up with a large output stream and get a buffer overflow error. But if you keep the picture small it will work.

I use the trick of setting the windows printer driver to send the output to COM1: instead of the LPT1: port in order to get the data to my qbasic program. I hope that the Amiga will work similarly by just choosing the serial port for output.

Hmmmm, now that I've uploaded the pictures I can see just how dingy white color 7 is. Maybe I'll set white to be color 15. I can't really tell on my lousy laptop screen.




setting up the CMY table, note that you don't see color 7 as it's black (c+m+y=black).



Epson4.BAS

Saturday, June 21, 2014

Wednesday, June 18, 2014

Adding QL-1060N

I added the QL-1060N to my PTSIM93.BAS program. Interestingly, the QL-1060N uses RLE compression with its graphics, unlike some of the other QL printers which use ULP uncompressed graphics. Also I added a sample of QL-1060 output to my javascript interpreter and fixed it to process the RLE data. Note that the output will be clipped unless you set the canvas to 1296 pixels high (for a 4x6 QL-1060 print at 300dpi).


for other QL printers,

g #1 #2 [data] 67 #1 #2 [data] Send raster line data consists of N=#2 bytes of uncompressed raster data

and for the QL-1060 it would be

g #1 #2 [data] 67 #1 #2 [data] Send raster line data consists of N=#2 bytes of RLE raster data after having been sent the M code to enable compression.

Friday, June 13, 2014

Pretending to be a Ptouch Printer in QBasic


I was always curious just exactly what the computer would actually send the PT-PC printer. So when I saw this webpage that stated that "the PTPC could only print 24 pixels wide" it piqued my interest.

"For arbitrary graphics, this printer can only print raster lines 24 pixels wide down the centre of the tape (and this way also arbitrary fonts in low resolution). It can print text using its built-in fonts, but that would require a special text-to-PT-PC driver."

I had to find some way to snoop the serial port and found this program:

Portmon for Windows v3.03 By Mark Russinovich

I fired it up, printed a couple of test labels, and then edited the output to make a binary file. I could see that it used only a few ESC commands, all of which were nicely documented in the PT-PC manual. It would be wonderful if every device that you bought came with complete technical documentation like that PT-PC. I remember my old Epson JX-80 printer included great technical documentation and tutorials. I really loved that old printer, horribly noisy but solid and most importantly, it had reinkable ribbons.

QBasic has always been kind of fun to hack with as it's very forgiving and gives you lots of feedback. I hacked up a little program that would open the binary file and draw the output on the screen.

Then I had an idea: Why not try to impersonate the PT-PC directly using the computer serial ports? All I have to do is to send a 32 byte sequence whenever the driver sends an "ESC i S" 1b 69 53 status request. QBasic supports up to 9600 baud serial communications which is great because the PT-PC uses 9600 baud.

The PT-PC uses a DB-9 serial port and I'm using a laplink cable to connect to it, so I've already got the cable.

So I wrote a little qbasic program to open the serial port and watch what it sent.

Unfortunately, it wouldn't send any bytes at all. I tried it over and over again and was totally stumped. I looked at the portmon snoop and how it opened the port. Somehow it was wanting to do a DSR handshake. I have a LED inline serial port display device and plugged that into the line. It looked exactly the same (the same leds were lit up) whether I plugged in the PT-PC or my laptop serial port. This was driving me crazy!!!

I left it for a day, came back to it, struggled again, left it for another day, came back, struggled again. It was horribly frustrating, like beating your head against the wall.

Then I had an insight: it's driving the PTCOM: port in the windows printer driver. Maybe I would specify the COM1: port instead! Once I selected COM1: it started sending bytes! WOO HOO!

The graphics looked funny because the MSB is not the lowest pixel of the byte. I got it to render the graphics properly by changing my renderdata routine to draw the ycoordinate with ypos+(7-bitpos) instead of ypos+bitpos.

There's something really cool and satisfying about watching it interpret the data and render the graphics to screen. Unfortunately, QBasic is terribly slow and it can't really keep up with 9600 baud data. For a decent sized PT-PC print job it can take many minutes (or more!!!). I suppose my junky 366 mhz laptop running win98 and qbasic could be swapped for something faster, but it works.

Then I said to myself, "hmmmm I've got other PTouch printers, why not try to simulate them?" Then after I got the PT2600 working I thought, "why not download the drivers for some of the PTouch printers I don't have?" So I got the PT-PC, PT2400, PT2600, PT9200, PT9500 and PT9700 drivers working with my QBasic program. The PT2600 is a USB printer and its USB printer drivers work fine with the COM1: port. But how to figure out what the printer code is that ESC i S is looking for?

First I snooped the USB port for the PT2600. Analyzing the print jobs gave the "B0H0" code.

Then I figured, why not just "try every combination". If I specify ptmodel$="UNKNOWN" in my code, every time it gets a status request it increments the ptunit$. So it tries "B000", then "B010"... If you keep pressing the "play" button in the windows print driver it cycles through and when it says "Wrong cassette inserted" instead of "Connected Ptouch is not the PT-2600" you know what the ptunit$ code is.

One thing to note is that QBasic can not keep up with the print job in realtime. So I've done a couple of things to compensate. I enlarged the serial receive buffer to the maximum 65535 bytes. Also, when it requests the status with (ESC i S) we reply with not just the 32 byte status block but also a few other 32 byte status blocks that it will expect later. Since it doesn't empty the receive buffer, those blocks will be there when it is ready to look for them. Otherwise it will timeout and give you a "Communication Error".

The sequence it looks for is

printstatus 0,0,0,0
printstatus 0,0,0,0
printstatus 6,1,0,0
printstatus 1,1,0,0
printstatus 6,0,0,0

A couple of the printer drivers will clear the receive buffer so we just put a little delay to wait until after it's done that. So the code looks like

printstatus 0,0,0,0
sleep 2 'wait for the buffer clear
printstatus 0,0,0,0
printstatus 6,1,0,0
printstatus 1,1,0,0
printstatus 6,0,0,0

Before I was able to get the timing right, I made it send the printstatus on hitting a "1" keystroke. It watches the INKEY$ and sends printstatus when inkey$="1". So I'd let the program respond to the initial ESC i S with a normal printstatus 0,0,0,0 and then midway through the print job I would type the "1" key.

You can send as many printstatus 0,0,0,0 as you like and the printer driver will gobble them without complaining.

So for the 7 people in the world who would be interested in this, here's my PTSIM.BAS qbasic program.

What good is this program? It could be very useful to someone developing printer drivers to check the output without burning up expensive Ptouch cartridges on test prints. It's also useful to "dump" the binary data coming over the COM1: port. Just set logfile$ to a valid filename and it will record every byte to a file. You may also set the inputfile$ to a filename if you want to take the input from a file on disk instead of the COM1: port. If you want the "perfect" printout without wasting a lot of ptouch cassettes, you can print to this simulator to see exactly what output will be generated, so you can try all of the different dithering styles.

For example, to take the input from a file:

ptmodel$ = "ql500"
ptunit$ = "O" 'uppercase Oscar
inputfile$ = "ql500.bin"
outputfile$ = ""
dorender = 1
tapewidth = 62 'for dk-1202
tapewidth = 29 'for dk-1201
mediatype = 10

To take the input from the COM1: port and just save it quickly to ql500.bin without rendering:

ptmodel$ = "ql500"
ptunit$ = "O" 'uppercase Oscar
inputfile$ = "com"
outputfile$ = "ql500.bin"
dorender = 0
tapewidth = 62 'for dk-1202
tapewidth = 29 'for dk-1201
mediatype = 10

My qbasic code isn't pretty and there's a lot of vestigial stuff, but it's not too complex to understand. Mostly I hate getting the indents right as the qbasic editor is worthless in that regard.

Oh, and the instructions for the "user interface": m to set the model, up and down arrow to change the selected item, t to set tape width, i to set input file, o to set output file, d to set the "dorender mode" (0, 1 or 2 to delay the render which makes two passes, first dorender=0 then dorender=1) and g to "go". Please watch the caps lock as it's not very clever about matching uppercase M.







PTSIM90.BAS

Wednesday, June 11, 2014

Ptouch Javascript Interpreter

Here's my Ptouch Javascript interpreter page. It's just a fun little javascript project to interpret the Ptouch protocol to generate an image from a binary printer file. I just print the label to a file and then browse to the saved file to render. The code is pretty simple and uses XMLHttpRequest to open up a file that resides in the webpage directory and FileReader to open a file with the file input box. It's a neat example of how to read and parse arbitrary binary data in javascript.

If you click on the row of buttons in the third row, there are demos of output from various P-Touch printers like the pt9200, pt9500 and the pt9700. Every time you click on one of these it will fetch the binary data and add an image at the end of the webpage. You can also scroll down and see how it processed the binary data.

If you click on the button that says 384 pixels or the one that says 720 pixels it will set the height of the canvas to 384 and 720 pixels respectively.

It's also kind of cool to right click on the canvas area and view it as an image.




PTouch Javascript Interpreter