Tuesday, February 21, 2023

MPS803 Poster Generator

Some time ago I restored old Commodore MPS 803 dot matrix printer. It is quite basic 7 dot printer. When reading user manual I noticed that this printer have bitmap graphics mode available. This printer is able to print 80 column text using 6x7 dot fonts so after short calculation I realized that I should be able to print images with 480 horizontal resolution which sounds quite nice in comparison to C64 graphics resolution. So I get idea to make simple application that can generate PRG files which I can load on actual C64 machine and print posters on my old MPS803 printer.

Well... I was not aware how hard printing on this type of printers might be.

Let check if we can fit into C64 RAM. Each byte contain data for 7 dots.
So 480(cols) * 480(rows) / 7(dot matrix row data) = 32kB. We are good.

Lets start with some assembly code that would be able to sent correct commands to the printer.
Below you can find listing of the program I wrote. This code use small trick to send big memory block to the printer. It use self modifying code. It increase address in 'lda imageX' instruction in loop.


// 480x588 BMP Printing on MPS803 printer.
// ----- @Start@ -----
:BasicUpstart2(start)    // 10 sys$0810
start:
    lda #4          // open 4, 4, 0
    tax
    ldy #0
    jsr $ffba
    lda #0
    jsr $ffbd
    jsr $ffc0
 
    ldx #4          // print#4,
    jsr $ffc9
    lda #8          // chr$(8) 
    jsr $ffd2
    lda #13         // chr$(13)
    jsr $ffd2

    // BMP1 block
load1:
    lda image1
    beq !end+
    jsr $ffd2
 
    clc
    inc load1 + 1
    bne !skip+
    inc load1 + 2
!skip:
    jmp load1
!end: 
 
    // BMP2 block
load2:
    lda image2
    beq !end+
    jsr $ffd2
 
    clc
    inc load2 + 1
    bne !skip+
    inc load2 + 2
!skip:
    jmp load2
!end: 
 
    ldx #4          // print#4,
    jsr $ffc9
    lda #15         // chr$(15)
    jsr $ffd2
    lda #13         // chr$(13)
    jsr $ffd2
    lda #10         // chr$(10)
    jsr $ffd2
    lda #4          // close 4
    jsr $ffc3
    jmp $ffcc
 
.pc = $1000 "BMP1"
image1:

.byte 0 
.pc = $c000 "BMP2"
image2:

.byte 0
  
At start I should choose image to test. What image is most popular for testing? How I could forget. Of course. Lenna.


I wrote simple program that loads any image then scale it to correct size and convert it to black and white image. I implemented feature to change contrast and brightness with real time preview to get best results. Below you can find example result.


I lost a lot of colors details of course. Since we have quite good resolution of prints I decided to implement basic dithering algorithm. First choice of course Floyd-Steinberg. Below you can find result image.

Looks good. Right? Then I try to print this image on MPS 803 dot matrix printer. How I was disappointed with results.

 
Contrast was so bad that it was almost impossible to tell what is on picture. This was one big gray rectangle. I decided to experiment with other types of dithering and try to increase contrast as much as possible. I implemented "fade" feature to image preview in my software to get as much final result preview as I can.

If you are interested in used dithering algorithms check this two link below:

http://www.tannerhelland.com/4660/dithering-eleven-algorithms-source-code/
https://web.archive.org/web/20131022220241/http://michal.is:80/projects/image-dithering-in-matlab/

Below you can find shots from my application. Best results I get using Artkinson dithering and adjust contrast and brightness to the levels where I get as many solid b&w regions as possible.  This looks like b&w image but with some blend on the edges. Each image need to be adjusted to get good results. Using live preview is quite handy here.


This is time for first quite good print. Results are below.


Image is much better however still not so great contrast because of not fully black ink used on printer tape. This was original old stock tape so not much we can help on hardware side. After some time I decided to print image using same 2 passes on one image. This should make black color more dark. Below are results from printing.



As a result of my journey I get small tool to print posters using old C64 and MPS 803 dot matrix printer. I hope it will be useful for somebody thet have this printer still. Below whole history of my prints on this device so far.