Reproducing this color print shop demo on youtube:
It's interesting how the bitmap colors differ from the output pdf where the pdf looks more authentic.
I also got the file size a bit smaller (like 10x smaller) by not setting the color for every output dot and by using strokes instead of fills to make the dots.
So then you can modify the variables directly, like manager:machine().lp[1].xpos = 200
Code
[MAME] function listlp()
[MAME]>> print("listlp() list of luaprinters:")
[MAME]>> print("------------------------------")
[MAME]>> for i,j in pairs(manager:machine().lp) do
[MAME]>> print("lp["..i.."] = "..j:getprintername())
[MAME]>> end
[MAME]>> print("------------------------------")
[MAME]>> end
[MAME]>
[MAME]> listlp()
listlp() list of luaprinters:
------------------------------
lp[1] = 2020-10-12 10-36-18 apple2e-sl1-parallel-pic_ctx-luaprinter
lp[:sl1:parallel:pic_ctx:luaprinter] = 2020-10-12 10-36-18 apple2e-sl1-parallel-pic_ctx-luaprinter
------------------------------
[MAME]> print(manager:machine().lp[1].name)
2020-10-12 10-36-18 apple2e-sl1-parallel-pic_ctx-luaprinter
[MAME]> manager:machine().lp[1].name = "hi_there"
[MAME]> print(manager:machine().lp[1].name)
hi_there
And I was also experimenting with being able to execute lua code from inside the ap2000 driver, so I could call a lua function to say, generate dots for a pdf. So how to execute lua code? Just call load_string.
[MAME]> manager:machine().lp[1].loadstring('print("IT WORKS")')
Trying print("IT WORKS")
IT WORKS
[MAME]> function dude(x) print ("This is a function that prints "..x) end
[MAME]> manager:machine().lp[1].loadstring('dude("IT WORKS")')
Trying dude("IT WORKS")
This is a function that prints IT WORKS
So now I need to figure out how to make it possible to call the luaengine from inside the driver.
It'd also be cool if you could load_string a string from the debugger, so you could do something complex in lua, so do something similar to a printf but make it lua code to execute.
I use the if to check if the drawdot routine has been defined.
Code
Trying callloadstring if drawdot then drawdot( 971.000000, 170.333333 ) end
Trying callloadstring if drawdot then drawdot( 971.000000, 171.333333 ) end
Trying callloadstring if drawdot then drawdot( 971.000000, 172.333333 ) end
Trying callloadstring if drawdot then drawdot( 971.000000, 173.333333 ) end
Trying callloadstring if drawdot then drawdot( 971.000000, 174.333333 ) end
and if I define the drawdot routine from the console:
Code
function drawdot(x,y) print("DRAWDOT !!! "..x.." "..y) end
Trying callloadstring if drawdot then drawdot( 35.000000, 60.000000 ) end
DRAWDOT !!! 35.0 60.0
Trying callloadstring if drawdot then drawdot( 35.000000, 61.000000 ) end
DRAWDOT !!! 35.0 61.0
Now I need to figure out how the ap2000 does 240 dpi because the steppers seem to step at 120 dpi, perhaps you have to watch the timing of when the printhead is fired, firing it when it's moving in-between stepper positions.
Now I need to figure out how the ap2000 does 240 dpi because the steppers seem to step at 120 dpi, perhaps you have to watch the timing of when the printhead is fired, firing it when it's moving in-between stepper positions.
The firmware was beautifully written and calculated down to the microseconds it takes for the printhead to hit the paper. Look for two comments which have "417 microseconds" in epson_lx810l.cpp.
In epson_lx810l_device::co0_w():
Quote
The firmware expects a 300 microseconds delay between the fire signal and the impact of the printhead on the paper. This can be verified by the timings of the steps and fire signals for the same positions with different directions (left to right or right to left). We don't simulate this delay since it is smaller than the time it takes the printhead to travel one pixel (which would be 417 microseconds), so it makes no difference to us. It is interesting to note that the vertical alignment between lines which are being printed in different directions is noticeably off in the 20+ years old printer used for testing =).
In epson_lx810l_device::device_timer()
Quote
The firmware issues two half-steps in sequence, one immediately after the other. At full speed, the motor does two half-steps at each 833 microseconds. A timer fires the printhead twice, with the same period as each half-step (417 microseconds), but with a 356 microseconds delay relative to the motor steps.
Thanks for the pointers. I stuck some instrumenting in to see the delay between changes to the stepper and the timers.
yes the write to co0_w is 417 ms apart: (2525-2107 = 418)
Code
POS = 0 DATA=0
POS = 1 DATA=0
STEPPER:d
CR_STEPPER_MSECS: time = 835.9782 microsecs
CR_STEPPER current pos: -49
POS = 0 DATA=0
POS = 1 DATA=0
CR_TIMER_MSECS: time = 835.978
POS = 0 DATA=0
POS = 1 DATA=44
Fractional time co0_w: 152107.340486
Trying callloadstring if drawdot then drawdot( 33.000000, 25.333333 ) end
Fractional time co0_w: 152107.340486
Trying callloadstring if drawdot then drawdot( 33.000000, 29.333333 ) end
STEPPER:8
CR_STEPPER_MSECS: time = 830.0781 microsecs
CR_STEPPER current pos: -48
POS = 0 DATA=0
POS = 1 DATA=38
Fractional time co0_w: 152525.024406
Trying callloadstring if drawdot then drawdot( 33.000000, 26.333333 ) end
Fractional time co0_w: 152525.024406
Trying callloadstring if drawdot then drawdot( 33.000000, 27.333333 ) end
Fractional time co0_w: 152525.024406
Trying callloadstring if drawdot then drawdot( 33.000000, 28.333333 ) end
CR_TIMER_MSECS: time = 830.078
and checking the time since the last stepper change, it says 337 usec and 755 usec (755-337 usec = 418 usec) so yes very close to expected
Code
POS = 0 DATA=0
POS = 1 DATA=20
Fractional time co0_w: 110442.708325
Time since last step: 757.446289
Trying callloadstring if drawdot then drawdot( 83.000000, 26.333333 ) end
STEPPER:5
CR_STEPPER_MSECS: time = 833.9437 microsecs
CR_STEPPER current pos: -98
POS = 0 DATA=0
POS = 1 DATA=8
Fractional time co0_w: 110857.137036
Time since last step: 337.931315
Trying callloadstring if drawdot then drawdot( 83.000000, 28.333333 ) end
CR_TIMER_MSECS: time = 833.944
POS = 0 DATA=0
POS = 1 DATA=20
Fractional time co0_w: 111274.210604
Time since last step: 755.004883
Trying callloadstring if drawdot then drawdot( 82.000000, 26.333333 ) end
STEPPER:d
CR_STEPPER_MSECS: time = 831.5023 microsecs
CR_STEPPER current pos: -97
POS = 0 DATA=0
POS = 1 DATA=8
Fractional time co0_w: 111690.470369
Time since last step: 339.762370
Trying callloadstring if drawdot then drawdot( 82.000000, 28.333333 ) end
CR_TIMER_MSECS: time = 831.502
POS = 0 DATA=0
POS = 1 DATA=2
Fractional time co0_w: 112107.543937
Time since last step: 756.835937
Trying callloadstring if drawdot then drawdot( 81.000000, 30.333333 ) end
STEPPER:8
CR_STEPPER_MSECS: time = 833.3333 microsecs
Reading this makes me realize how much a dot-matrix printer is like a write-only floppy drive, except it controls the exact media position instead of waiting for it to come around to the right spot.