Yesterday (and today when I confirmed this), I noticed that it can be helpful
to actually understand what you’re doing. :)
What I didn’t knew when I was
POKEB-ing bytes in my Psion Organiser’s address
space at first, is that when you access addresses
actually addressing the HD44780 LCD controller in the Organiser.
0x180 is the instruction register of the HD44780 LCD controller,
0x181 is its data register.
I should have wondered already why it was possible to write subsequent rows in
a UDG to the same address
0x181 to define a character.
If we look at the code of defining a user defined character again:
udg:(udgnum%, b0%, b1%, b2%, b3%, b4%, b5%, b6%, b7%) pokeb $180, 64 + udgnum%*8 pokeb $181, b0%; pokeb $181, b1% pokeb $181, b2%; pokeb $181, b3% pokeb $181, b4%; pokeb $181, b5% pokeb $181, b6%; pokeb $181, b7%
You see that first the argument
64 + udgnum%*8 is written to the address
0x40) is the instruction to the HD44780 LCD controller to set
the CG (character generator) RAM address.
The least significant 6-bits of the instruction contain the address itself, this is
udgnum% * 8 term.
udgnum% In this case, is the character to define.
A character contains 8 rows of pixels, so to reach the next character you multiply
this by 8.
0x181 writes the bit pattern poked to this address in the CG RAM, the
magic part is that after writing this pattern, the CG RAM address is automatically
incremented by the controller!
Knowing this, I realized that it must be possible to use this to read from the CG RAM as well as writing, but it’s not possible to use the autoincrement magic then. This morning, in the train to work I wrote a small OPL program to test this assumption:
rlcdreg: local char%, row%, byte% rem dump UDGs from HD44780 CG RAM char% = 0 while char% <= 7 row% = 0 while row% <= 7 rem hd44780 instr reg is at 180h rem instr 40h addresses CG RAM pokeb $180, $40 + char%*8 + row% rem data reg is at 181h byte% = peekb($181) print "chr"; char%, print "row"; row%, print "val"; byte% row% = row% + 1 endwh char% = char% + 1 endwh
And the character definitions came scrolling down my Psion’s little screen!
Pretty useless, maybe. But it means that it is possible to manipulate the UDG definitions in the LCD controller directly, without using some shadow copy in the Psion’s RAM. I think that I will experiment with this in OPL first and when succesful port it to machine code instead for speed, would be a nice opportunity to learn the instruction set of an ancient processor. ;)
To be continued.