Jump to content
IGNORED

QR Code Generator for TI


BJGuillot

Recommended Posts

QR Code Generator for TI-99/4A

B.J. Guillot

Marysville, Washington

4/30/2016

 

https://www.youtube.com/watch?v=A2m8rr4sA88

 

Released at TI-99/4A PNW Fest West 2016 (“Version 0.9”).

 

Uses Bitmap Mode (“Graphic 2”) (256x192)

with 3 Pattern Tables (6144 bytes) and 1 Color Table (2048 bytes)

 

Smallest QR Code (“Version 1”) is 21x21 pixels

Largest QR Code (“Version 40”) is 177x177 pixels

 

Learned how to build QR codes by following the very detailed Thonky.com Tutorial

http://www.thonky.com/qr-code-tutorial/

 

Developed on Mac OSX using xdt99 TI 99 Cross-Development Tools and JS99’er TI-99/4A JavaScript emulator on Google Chrome. I started by writing a C program on my Mac to validate my understanding of the QR Tutorial, and then manually ported that to TMS-9900 assembler.

 

To simplify the project, several limitations are in place:

  • Hard-coded to use Quality Mode “Q” (QR has Low, Medium, “Q”, and High Error Correction, Q is the 2nd best). Felt “Q” (“Medium-High”) was the best compromise.
  • Hard-coded to use encoding scheme for 8-bit byte data (QR has numeric-only, alphanumeric-only, Byte, and Kanji). Felt Byte was the most useful.
  • Hard-coded to use Mask 1 (the bits of every even row are flipped). This is probably a bad thing and is against the QR specification. You are supposed to try each of the 8 available mask types, calculate a “penalty score” for each mask, and then, for the final rendering, use the mask that had the lowest penalty. The penalty is based on number of consecutive blocks having same color, etc. It’s designed to make it easier on scanning equipment. In reality, I don’t think it matters—everything generated by my program should be a valid QR, it may just not be the “best” QR possible.

 

Maximum message size using 8-bit Byte encoding with Version 40-Q is 1,663 bytes. It takes about 11 seconds to generate the 177x177 pixel V40-Q QR Code.

 

Message size after Reed-Solomon error correction for a 40-Q message is 3,706 bytes (or 29,648 individual bits that get drawn on QR code, not counting bits used for finder patterns, alignment patterns, timing patterns, mask info, and other format and version info).

 

Also tested on real console with NanoPEB, with F18A (VGA output).

Also tested on real console with NanoPEB, without F18A (composite output).

I confirmed that the QR code was readable by my Android phones even with non-F18A machines using composite output. I was somewhat worried about it because the composite output is pretty noisy on my television (dot crawl, visible colors where it should be black-and-white, etc.) It could still scan it, but it sometimes took a tiny bit of additional effort for the Android QR app to scan and decode the display.

 

The two Android apps I used for testing:

  • QR Scanner from Kaspersky Lab (version 1.1.0.228).
  • QR Droid (version 6.6)

 

In general, QR Droid’s default scanning engine (“Zapper”), seemed to be able to scan the generated QR codes faster than QR Scanner; however, above QR Version 20, the Zapper engine seemed to be unable to capture data, and I had to switch over to the alternate “ZXing” engine that isn’t quite as fast.

 

For future: Want to test on bare console with cartridge, but need to figure out how to build one.

 

If a F18A is detected when the program starts, the “text editor” will start in 80 column mode. Otherwise, the editor starts in 40 column mode. In 40 column mode, total user input possible is 40 columns * 22 rows = 880 characters, which is well under the maximum 1,663 possible characters. In 80 column mode, total input possible is 80 columns * 22 rows = 1760 characters. In that case, only the first 1663 characters will be used and the remaining will be truncated.

 

There is only one “page”, so while it is a full screen editor, it does not allow the user to scroll.

 

Commands available in the full screen editor:

Function-S - Left

Function-D - Right

Function-E - Up

Function-X - Down

Function-6 - Proceed – Draw a QR code for the entered text

Function-9 - Draw Demo QR Code (Fest West 2016 note)

Function-0 - Draw Stress-Test QR Code (part, Declaration of Independence)

 

Fn-9 info: QR Version 12 (65x65 pixels) with original input of 183 bytes

After error correction, total output is 466 bytes (3,728 pixels)

 

Fn-0 info: QR Version 40 (177x177) with original input of 1,639 bytes

After error correction, output is 3,706 bytes (29,648 pixels)

Future versions may potentially remove the Function-9 and -0 to save space.

 

For future: I understand there is an undocumented 2-color only bitmap mode called (“Bitmap text mode”, aka “the mode that TI forgot to tell us about”) that could be useful to get more available VDP RAM since it doesn’t use a color table, nor use extra space for sprite tables, etc. I’m not sure if emulators or the F18A support this undocumented mode, though.

 

I had been doing all my testing on my Android Smartphone, but as I packed up all my gear for Fest West, it occurred to me that I could use a USB handheld laser barcode scanner to read the QR codes as well. Theoretically, if the USB barcode wand is compatible with jedimatt42’s USB keyboard adapter, you could use a future version of my QR Code generator to grab files from one TI an transfer them to another TI “wirelessly”, i.e.,

 

TI #1 -> generate QR code -> Scan with USB barcode wand -> keyboard input into USB keyboard adapter -> save keystrokes as a file on TI #2.

 

One problem with this scenario is that I designed the QR code to transmit data as 8-bit bytes, which wouldn’t be mapped to all keyboard characters. Perhaps if the data were mapped to 7-bit BASE64 encoding first.

 

Intention is to run on Non-Expanded TI (uses only VDP RAM and scratchpad RAM), and it had been working earlier this week, but some of the other changes I made later on seemed to break it running on a non-32K console. Need to investigate.

 

There’s probably lots of room for improvement in terms of performance. Portions of the code I was trying to code to be as performant as possible, and for other portions, my brain was sufficiently fried to the point that I just wanted to make the code work and I threw performance out the window to just “get it done”.

 

The code seems mostly bug-free, though I have occasionally noticed rendering errors. If you do happen to see an invalid QR code rendered, please send me a screenshot. I’ve addressed each repeatable bug I’ve found. Non-reproducible bugs have been harder to address.

 

I adapted snippets assembly source code I found on the Internet from various sources. Acknowledgments:

  • Matthew Hagerty’s public domain “Yin/Yang” code from March 2006 served as an awesome “tutorial” for using bitmap graphics. I used some of his VDP routines.
  • Matthew Hagerty’s F18A unlock/detection code from March 2012.
  • TurboForth’s GPLLNK routine, that TurboForth adapted from the July 1986 edition of “Smart Programmer”. I needed this routine to grab the character set from GPL to load for the 40- and 80- column modes.
  • TurboForth’s lowercase character font set.
  • Tim Tesch’s public domain KSCAN routine from S&T Software’s Backup-Bit Remover v1.0.

 

I’m releasing a RPK fie and DSK file. I have tested both with Js99er.net. The DSK file contains a program called “DEMO” that is an EA5 image.

 

I will release the source code under the MIT License once I clean up the comments.

 

qr.rpk

demo.dsk

  • Like 19
Link to comment
Share on other sites

For future: I understand there is an undocumented 2-color only bitmap mode called (“Bitmap text mode”, aka “the mode that TI forgot to tell us about”) that could be useful to get more available VDP RAM since it doesn’t use a color table, nor use extra space for sprite tables, etc. I’m not sure if emulators or the F18A support this undocumented mode, though.

 

I have never seen this mode in use - probably because the 6-pixel wide characters are really awkward for bitmap drawing. I don't think it's supported by the F18A and I know it's not supported by JS99'er. Instead you can save 4K VDP RAM by using the hybrid bitmap mode with one color table and three pattern tables.

Link to comment
Share on other sites

Since you surprised us by proving that the bar code wand was compatible with the USB keyboard adapter, I am curious what kind of wand was it?

 

The one I brought with me was a Symbol Technologies DS6707-SR20007ZZR model. I have a much cheaper one I bought somewhere that I'll have to dig up and try it sometime. From what I understand, most USB barcode wands simulate a USB keyboard, so I think almost any will work with your adapter.

Link to comment
Share on other sites

I have never seen this mode [(“Bitmap text mode”, aka “the mode that TI forgot to tell us about”) ] in use - probably because the 6-pixel wide characters are really awkward for bitmap drawing. I don't think it's supported by the F18A and I know it's not supported by JS99'er. Instead you can save 4K VDP RAM by using the hybrid bitmap mode with one color table and three pattern tables.

 

Good to know. Probably not worth looking into then.

 

Yeah, I'm already using the hybrid mode with one color table and three pattern tables. While it appears to work for my demo, I'm technically using part of the VDP RAM I shouldn't be using. The VDP memory layout is:

  • Three pattern tables using total of 6,144 bytes from >0000 to >17FF (0 to 6143)
  • Screen image table using 768 bytes from >1800 to >1AFF (6153 to 6911) -- not really sure what this is for bitmap mode
  • Sprite attribute table at >1B00 to ? (6912 to ?) -- I'm a little fuzzy about this, as I'm not using sprites, not sure if I can use it
  • Color table using 2048 bytes from >2000 to >27FF (8192 to 10239)
  • Interleaved QR Data Words and Error Correction Code Words, length 3706 bytes, from >2800 to >3679 (10240 to 13945)
  • User Input Message and First Stage Data Coding, length 1666 bytes, from >367A to >3CFB (13946 to 15611)

I've read that the last bullet could be using "illegal" memory for various disk system DSR's and/or buffers, and that you shouldn't really use anything at or after >37D1 (14289).

 

It appears to work fine, probably because I'm not using disk access in the current version, but I probably need to try moving that 1666 byte structure somewhere else. I did some earlier testing where I tried using it at >2000 (where my color table is) before switching to graphics mode, and while it run OK in the emulator, it seemed to crash when running on real hardware. (The user input pre-coding step happens during the "please wait..." message and isn't needed once we switch to Bitmap mode. Now that Fest West is over, and I'm not in a time crunch, I'll have more time to experiment to try doing things in a "better" way.

  • Like 1
Link to comment
Share on other sites

Cool! I was playing with the idea to implement QR codes on a Commodore PET earlier this year, but never went beyond proof of concept. I was planning to precalculate desired QR codes and include those in the program for just drawing, using semi graphics to get up to 47x47 or whatever is closest in the world of QR.

 

I had two ideas how to use it:

1. Demo kiosk with miniature encyclopedia. You store short articles on disk, which are linked together like a wiki. In each article, you display a QR code to point you to a web resource (e.g. Wikipedia) to read a bigger version of the same article in your smartphone. Perhaps a bit dull, but it might be popular at an exhibition. If run on a graphically more advanced computer like the TI-99/4A or a C64, you could add more high resolution graphics, colours, sprites, sound to enhance the small articles.

 

2. Menu of games available to play, and for each menu entry you get a QR code pointing to a scanned manual of said game. It saves having papers next to the machine, and you can read on the controls in your phone while playing the game on the vintage computer.

 

Perhaps you have even more ideas where to take your application.

Link to comment
Share on other sites

Perhaps you have even more ideas where to take your application.

 

Nice ideas. I really liked the one about embedding a link to a scanned copy of the instruction manual, as I know I personally have trouble remembering all the keyboard commands across the various different games.

 

One thing I'd like to do is compute a Bitcoin private address for a cold storage wallet. I needed to be able to generate the QR code for that, but implementing all the other cryptography, math, and random number functions may be a pretty big challenge. The goal behind that thinking is that most modern computers can pretty much assumed to be compromised by other the government or blackhats. Even if you aren't connected to the Internet, if your machine has WiFi or Bluetooth, there could be a malware embedded in the BIOS or in the firmware of the WiFi radio, disk controller, printer, keyboard, etc. that allows people to interrupt data, keystrokes, etc. There are just so many attack vectors on modern PC's it's not secure at all. My thinking is that old PC's like the TI-99/4A provide an extremely "secure" environment if I can make modern cryptography code run fast enough to be useful. I think modern crypto plus old hardware = mega-secure. (At least until quantum computers come out and destroy modern crypto.)

 

My QR code generation demo is just the very first step into this long process of developing a cryptography and cryptocurrency suite. I choose the TI for this project as it was my first computer, and also, the consoles are readily available for very cheap prices. Other vintage machines of the era might have more memory, etc., but they are much more expensive to acquire (C64's, Apple //e, etc.) I've managed to buy TI consoles for $0.99 or so before.

  • Like 2
Link to comment
Share on other sites

I've read that the last bullet could be using "illegal" memory for various disk system DSR's and/or buffers, and that you shouldn't really use anything at or after >37D1 (14289).

 

You should not go above the VRAM location stored in scratchpad RAM at >8370. You can run the DSR's subroutine >016 (FILES) to change the maximum number of simultaneously open files to 1 (>8370 will contain >3BE3). I am not sure real iron will allow you to set FILES = 0 with a disk controller attached, but you could try. That would give you all of VRAM (>8370 will contain >3FFF).

 

...lee

Link to comment
Share on other sites

I have never seen this mode in use - probably because the 6-pixel wide characters are really awkward for bitmap drawing. I don't think it's supported by the F18A and I know it's not supported by JS99'er. Instead you can save 4K VDP RAM by using the hybrid bitmap mode with one color table and three pattern tables.

We knew about it during F18A dev, but never had any test code so I'm not sure if Matt built it. The mode is supported in Classic99 but untested.

Link to comment
Share on other sites

I am not sure real iron will allow you to set FILES = 0 with a disk controller attached, but you could try. That would give you all of VRAM (>8370 will contain >3FFF).

Zero is not legal on the TI disk controller or any controller that is based on its code. :)

  • Like 1
Link to comment
Share on other sites

I used it to make a new Atari Age avatar... gallery_35324_1001_247.jpg

 

Nice! By the way, hopefully in the next week or two or three I'll release a new version that fixes the bug with it running on a non-expanded system. Also, I hope to get the source code out with example programs and documentation that will allow people to assemble their own programs that can call the QR routine to display it on-screen.

Link to comment
Share on other sites

That's a cool idea. I'm getting so used to big sharp pixels from the TI gear, that I was surprised it scanned, since it looks softened to me.

 

Some of the blurriness is caused by the web browser itself. Chrome, for example, tries its best at making all the images on the page appear pretty and smooth. Google had to introduce a new CSS property to tell the browser to better control itself in this situations. See the blog entry at https://developers.google.com/web/updates/2015/01/pixelated?hl=en for a bit of information on it. One of the examples they refer to specifically there relates to QR Code images.

  • Like 1
Link to comment
Share on other sites

  • 4 months later...

I'd love to see this program develop a print feature some day. It would be so cool to spit the QR code out on an old dot-matrix printer even on a modern printer using the HDX's print feature.

 

One way around this is to run the program under emulation, grab a screen shot and print it. Not the greatest solution but it does work...

Link to comment
Share on other sites

Sorry I just discovered this thread... Super cool! I can see having QR codes on disk sleeves with a long description of the disk contents or even a mini-manual of the program on disk!

 

Vorticon, if you missed his presentation at Fest 2016... you can catch the re-run. :)

https://www.youtube.com/watch?v=-b3NXNqeQm8

 

 

 

One way around this is to run the program under emulation, grab a screen shot and print it. Not the greatest solution but it does work...

 

Yes, I've done that... it's cheating though...

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...