[s1mp3-dev] HOWTO: figure out your LCD/OLED display

Alistair Buxton a.j.buxton at gmail.com
Thu Jun 22 08:09:01 CDT 2006


Okay, some people have been having trouble getting the loadram samples to
display anything on their screen. I've been investigating, and this is what
I found:

I had one player that worked perfectly and one that would only draw in a
thin band (actually it turns out this is a page.)

I looked in to the programming method for LCD displays, and learned they
have two modes: data mode, where you write the raw data to the screen, and
command mode, where you do things like position the cursor. The mode is
controlled by a GPIO line which must be turned on or off. Since we know that
manufacturers like to rewire the GPIO different in every player, I guessed
that this was the cause of the problem.

The first thing i found while playing around is that writing to any address
0x8000-0xFFFF ends up at the LCD data input. So it looks like the ATJ's CE3
line (also known as "LCD enable" in some docs) is wired directly to the
internal address bus highest bit.

So I disassembled every file in my player's firmware ( for i in `ls`; do
echo $i; z80dasm $i > $i.asm; done) and looked for writes (ld) to any
address above 0x8000 (inclusive.) (Using grep, of course.) Obviously there
were a lot. From looking at the examples I noticed that 0x8000 and 0x8001 is
normally used for accessing the LCD, so I narrowed the search to these
addresses. Only a few firmware modules actually had these addresses, most
notable the files UI_xxxx.DRV.

I looked more closely at the UI_L0724.DRV disassembly (L=latin?), and found
this:

    push   bc              ; 000805 C5
    in     a,($f4)         ; 000806 DB F4
    and    $fb             ; 000808 E6 FB
    out    ($f4),a         ; 00080A D3 F4
    ld     a,c             ; 00080C 79
    ld     ($8000),a       ; 00080D 32 00 80
    pop    bc              ; 000810 C1
    ret                    ; 000811 C9

    in     a,($f4)         ; 000812 DB F4
    or     $04             ; 000814 F6 04
    out    ($f4),a         ; 000816 D3 F4
    ld     a,(hl)          ; 000818 7E
    ld     ($8001),a       ; 000819 32 01 80
    inc    hl              ; 00081C 23
    djnz   $0818           ; 00081D 10 F9
    ret                    ; 00081F C9

These are clearly subroutines!

The first subroutine turns off a GPIO line, and the second turns one on...
just what we are looking for. Also, they both write to the LCD. The second
one writes the data from (hl) to (hl+b) so it looks like a routine to copy
graphics to the LCD. The first one only ever writes one byte, so it looks
like it's passing a command. It seems like a convention to use 0x8000 when
sending a command, and 0x8001 when sending data, although these addresses
are interchangable.

After googling for 8080 lcd programming commands for a while, I found this
PDF with some LCD commands:

http://serdisplib.sourceforge.net/ser/doc/sed1560.pdf

Sure enough, once I had the correct port and bit, these commands worked on
my display, at least the simple ones did.

BTW the display I was using is not actually LCD, but mono OLED. I just used
the term "LCD" cos I'm too lazy to type "display." I'm 99% certain all
display types will use exactly the same commands - although the pixels will
be packed differently on colour displays - you will still see something,
even if it looks like garbage...

I hope this is of some help to the people who were asking about LCD
programming in the IRC. Hopefully others will be able to follow my steps and
discover the gpio mapping of their display, and then we can get more people
coding :)

-- 
Alistair Buxton
a.j.buxton at gmail.com
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://s1mp3.org/pipermail/s1mp3-dev_s1mp3.org/attachments/20060622/1a997179/attachment.htm


More information about the s1mp3-dev mailing list