flat assembler
Message board for the users of flat assembler.

Index > Tutorials and Examples > drive a 16*4 lcd with lpt. real mode

Author
Thread Post new topic Reply to topic
edfed



Joined: 20 Feb 2006
Posts: 4347
Location: Now
edfed 15 Sep 2013, 16:29
Image
i am trying to adapt it for windows, then, i will be able to display 64 chars on this lpt lcd mount.

the code works under real mode, and v86 (win98 console)
but it fails in win32 application.

i do that:
Code:
testlptdrv:
dd lpt.frame,.buffer
.buffer: 
db "0123456789abcdef"
db "0123456789abcdef"
db "0123456789abcdef"
db "0123456789abcdef"
...
windows blaabla code
invoke something
...
call dword[testlptdrv]
...
invoke something_else
    


and it crashes because of direct access to port 3D8h

Code:
lptlcd:
.call=0
.txt=4
        push esi
        mov esi,[esi+.txt]
        call lcd.frame
        pop esi
        ret
;;;;;;;;;;; ;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;
;16 apparent chars, 24 virtual chars
;frame:  rb 16*4+8
;message:                          ;1st zone
;.0:     db 'INTO THE WILD CP' ; xxxxxxxxxxxxxxxx                         second zone
;.1:     db 'U, THE SIGNAL EV' ;                   third zone           xxxxxxxxxxxxxxxx
;.2:     db 'OLVE AND TRY TO ' ;                 xxxxxxxxxxxxxxx                         fourth zone
;.3:     db 'RESOLVE ........' ;                                  pad                   xxxxxxxxxxxxxxxx  pad
;.pad:   db '        '         ;                                xxxxxxxx                                xxxxxxxx
;.end:
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;---------------------------------------------------------------------------------
;LPT connection
;pin 1 = E = .ctrl bit0, 1 inverted
;pin 14 = R/W = .ctrl bit1, 2 inverted
;pin 16 = RS = .ctrl bit2, 4
;pins 2 to 9 = data = .data
;
;LCD connection
;pin 1 = gnd
;pin 2 = +5V
;pin 3 = contrast
;pin 4 = Register Select
;pin 5 = Read /Write
;pin 6 = Enable
;pins 7 to 14 = data
;---------------------------------------------------------------------------------
macro delay .t
{
        mov ecx,.t
local .a
.a:
        dec ecx
        jne .a
}
delaylong:
        delay 500'000
        ret
delayshort:
        delay 7'000
        ret
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
lcdmsg:
.0=0
.1=10h
.2=20h
.3=30h
.pad=40h
.end=48h
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
lcd:
.lpt=378h
.data=.lpt+0
.stat=.lpt+1
.ctrl=.lpt+2
.e=1
.rw=2
.rs=4
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
.frame:
;si=msg 64 bytes
        push esi
        call lcd.init
        call lcd.refresh
        pop esi
        ret
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
.refresh:
        push eax ebx esi
        xor ebx,ebx;lcdmsg.0    ;start at first char, i first zone
@@:
        mov ah,[esi+ebx]              ;load char
        call .putc            ;putchar in lcd
        inc ebx               ;next char
        cmp ebx,lcdmsg.1;message.1  ;next zone?
        jne @b
        mov ebx,lcdmsg.2;message.2  ;next zone, third zone
@@:
        mov ah,[esi+ebx]
        call .putc
        inc ebx
        cmp ebx,lcdmsg.3;message.3
        jne @b
        mov ebx,lcdmsg.pad;message.pad ;first virtual line padding
@@:
        mov ah,0
        call .putc
        inc ebx
        cmp ebx,lcdmsg.end;message.end
        jne @b
        mov ebx,lcdmsg.1;message.1
@@:
        mov ah,[esi+ebx]
        call .putc
        inc ebx
        cmp ebx,lcdmsg.2;message.2
        jne @b
        mov ebx,lcdmsg.3;message.3
@@:
        mov ah,[esi+ebx]
        call .putc
        inc ebx
        cmp ebx,lcdmsg.pad;message.pad ;second virtual line padding
        jne @b
@@:
        mov ah,0
        call .putc
        inc ebx
        cmp ebx,lcdmsg.end;message.end
        jne @b
        pop esi ebx eax
        ret
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
.putc:
        push eax ebx ecx edx
        call .writedatacheck
        pop edx ecx ebx eax
        ret
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
.init:
        push esi
        mov ah,38h        ;function set
        call .writeinstnocheck
        call delaylong
        mov ah,38h        ;function set
        call .writeinstnocheck
        call delaylong

        mov ah,0ch        ;display on
        call .writeinstcheck
        call delaylong

        call .clear

        mov ah,6          ;entry mode set
        call .writeinstcheck
        call delaylong
        pop esi
        ret
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
.p1:
        mov edx,.data
        ret
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
.p2:
        mov edx,.stat
        ret
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
.p3:
        mov edx,.ctrl
        ret
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
.clear:
        mov ah,1
        call .writeinstcheck
        call delayshort
        ret
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
.writedatacheck:
        call .busycheck
.writedatanocheck:
        call .dr
        call .send
        ret
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
.writeinstcheck:
        call .busycheck
.writeinstnocheck:
        call .ir
        call .send
        ret
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
.send:
        call .wr
        call .en
        call .p1
        mov al,ah
        out dx,al
        call delayshort
        call .dis
        call .p1
        mov al,0ffh
        out dx,al
        ret
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
.busycheck:
        call .ir
        call .rd
        call .en
        call .busy
        call .dis
        ret
.busy:
        call .p1
@@:
        in al,dx
        and al,80h
        je @b
        ret
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
.dr:
;.datareg:
        call .p3
        in al,dx
        or al,.rs
        out dx,al
        ret
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
.ir:
;.instreg:
        call .p3
        in al,dx
        and al,not .rs
        out dx,al
        ret
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
.dis:
;.disable:
        call .p3
        in al,dx
        or al,.e
        out dx,al
        ret
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
.en:
;.enable:
        call .p3
        in al,dx
        and al,not .e
        out dx,al
        ret
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
.wr:
;.write:
        call .p3
        in al,dx
        or al,.rw
        out dx,al
        ret
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
.rd:
;.read:
        call .p3
        in al,dx
        and al,not .rw
        out dx,al
        ret
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
    


it works fine under dos and any real mode interface. but now, it should work in protected mode os.
windows and linux required for fun application.

Image

i test it on a pIII 800Mhz, lpt connected to lcd directly, plus a 5Vdc power to supply energy to the lcd panel.

Image
as you can see, the cpu use is high, it is due to the lcd driver.
the future of this driver is to work inside the timer interrupt, or better, be buffered by a MCU between lpt and lcd.

one solution for the moment would be to call the lcd driver only 2 or 3 times per second, to avoid the saturation of the cpu during delay loops.

the box is made with bristol paper Smile

if it continues to fail, i will make a dos-like command line to do the job. :p
Post 15 Sep 2013, 16:29
View user's profile Send private message Visit poster's website Reply with quote
shoorick



Joined: 25 Feb 2005
Posts: 1614
Location: Ukraine
shoorick 14 Oct 2013, 13:29
try inpout32 to access lpt under windows Wink
this ISP programmer has an inpout32.dll in its package which works even under windows 7 Wink
and you are right: proper computer must have its sockets situated on the front side!
Post 14 Oct 2013, 13:29
View user's profile Send private message Visit poster's website Reply with quote
revolution
When all else fails, read the source


Joined: 24 Aug 2004
Posts: 20363
Location: In your JS exploiting you and your system
revolution 14 Oct 2013, 14:02
For 5vDC supply you can use a USB port and get 500mA minimum, and up to 1.5A if your mobo has a charging port. Just leave the two centre data lines floating and use the two outside lines for 5v power.
Post 14 Oct 2013, 14:02
View user's profile Send private message Visit poster's website Reply with quote
edfed



Joined: 20 Feb 2006
Posts: 4347
Location: Now
edfed 15 Oct 2013, 18:48
i pick the 5VDC on the motherboard and pass it via a standard powersupply connector. the two usb ports this pc have are still assigned for misc usages and cannot be affected permanentlly to this lcd.

yep, proper pc should have connectors on the front side, in this case, it is an old laptop motherboard mounted in a woodcase.
Post 15 Oct 2013, 18:48
View user's profile Send private message Visit poster's website Reply with quote
Display posts from previous:
Post new topic Reply to topic

Jump to:  


< Last Thread | Next Thread >
Forum Rules:
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum
You cannot attach files in this forum
You can download files in this forum


Copyright © 1999-2024, Tomasz Grysztar. Also on GitHub, YouTube.

Website powered by rwasa.