Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

COM1 interrupt for 16-bit OS

184 views
Skip to first unread message

Robert Pengelly

unread,
Nov 10, 2023, 11:50:50 AM11/10/23
to
Does anyone know how I get IRQ4 INT 0Ch working for a 16-bit OS? On https://wiki.osdev.org/Interrupts it has "8-15 Default mapping of IRQ0-7 by the BIOS at bootstrap", Is that only for 32-bit or is it for both 32 and 16 bit? Do I need to manipulate things to get IRQ4 INT 0Ch working for 16-bit?

wolfgang kern

unread,
Nov 11, 2023, 1:32:35 AM11/11/23
to
On 10/11/2023 17:50, Robert Pengelly wrote:
> Does anyone know how I get IRQ4 INT 0Ch working for a 16-bit OS? On https://wiki.osdev.org/Interrupts it has "8-15 Default mapping of IRQ0-7 by the BIOS at bootstrap", Is that only for 32-bit or is it for both 32 and 16 bit? Do I need to manipulate things to get IRQ4 INT 0Ch working for 16-bit?

old 16 bit hardware had jumpers on COM/LPT add-on boards for setup IRQ-
number and CS aka I/O address.
modern stuff have this all emulated in the south-bridge (in the chip-set
on main board) and may or may not allow modification of their defaults.

how much do you already know about IRQ-redirection ?

it depends on your hardware if you need to modify anything.

and what are you trying to achieve with IRQ4 ?
is there any COM-port connected to it at all ? my PC don't have any.
__
wolfgang

Robert Pengelly

unread,
Nov 11, 2023, 1:39:52 AM11/11/23
to
I'm trying to figure out how to get data from a serial mouse as most of the roms in pcem and 86box don't have a PS/2 option.

I have:

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Disable all interrupts.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
mov dx, HEX (03F9)
xor al, al
out dx, al

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Enable DLAB (set baud rate divisor).
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
mov dx, HEX (03FB)
mov al, HEX (80)
out dx, al

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Set divisor.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
mov dx, HEX (03F8)
mov al, HEX (03) ; 3 (lo byte) 38400 baud.
out dx, al

mov dx, HEX (03F9)
xor al, al ; (hi byte)
out dx, al

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; 8 bits, no parity, one stop bit.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
mov dx, HEX (03FB)
mov al, HEX (03)
out dx, al

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Enable FIF0, clear them, with 14-byte threshold.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
mov dx, HEX (03FA)
mov al, HEX (C7)
out dx, al

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; IRQs enabled, RTS/DSR set.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
mov dx, HEX (03FC)
mov al, HEX (0B)
out dx, al

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Set in loopback mode, test the serial chip.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
mov dx, HEX (03FC)
mov al, HEX (1E)
out dx, al

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Test serial chip (send byte 0xAE and check if serial
;; returns same byte).
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
mov dx, HEX (03F8)
mov al, HEX (AE)
out dx, al

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Check if serial is faulty (i.e. not same byte as sent).
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
mov dx, HEX (03F8)
xor ax, ax
in al, dx

cmp al, HEX (AE)
jne .setup_interrupts

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; If serial is not faulty set it in normal operation mode
;; (not-loopback with IRQs enabled and OUT#1 and OUT#2 bits enabled).
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
mov dx, HEX (03FC)
mov al, HEX (0F)
out dx, al

which I got from towards the bottom of https://wiki.osdev.org/Serial_Ports and converted it to assembly. That code works I'm getting 0xAE but I can't seem to read data from the mouse and I can't get an interrupt to work.

wolfgang kern

unread,
Nov 11, 2023, 2:50:06 AM11/11/23
to
getting AE from previously written port may not mean much :)
are you sure the mouse is connected to COM_1 and set to IRQ_4 ?
how does your IRQ-routine work ?
__
wolfgang

here some info from my RBIL-copy on port 03F8:

PORT 03F8-03FF - Serial port (8250,8250A,8251,16450,16550,16550A,etc.) COM1
Range: PORT 02E8h-02EFh (COM2), PORT 02F8h-02FFh (typical non-PS/2
COM3), and
PORT 03E8h-03EFh (typical non-PS/2 COM4)
Note: chips overview:
8250 original PC, specified up to 56Kbd, but mostly runs
only 9600Bd, no scratchregister, bug: sometimes shots
ints without reasons
8250A, 16450, 16C451: ATs, most chips run up to 115KBd,
no bug: shots no causeless ints
8250B: PC,XT,AT, pseudo bug: shots one causeless int for
compatibility with 8250, runs up to 56KBd
16550, 16550N, 16550V: early PS/2, FIFO bugs
16550A,16550AF,16550AFN,16550C,16C551,16C552: PS/2, FIFO ok
82510: laptops & industry, multi emulation mode
(default=16450), special-FIFO.
8251: completely different synchronous SIO chip, not compatible!
SeeAlso: INT 14/AH=00h"SERIAL"

03F8 -W serial port, transmitter holding register (THR), which
contains the
character to be sent. Bit 0 is sent first.
bit 7-0 data bits when DLAB=0 (Divisor Latch Access Bit)
03F8 R- receiver buffer register (RBR), which contains the received
character. Bit 0 is received first
bit 7-0 data bits when DLAB=0 (Divisor Latch Access Bit)
03F8 RW divisor latch low byte (DLL) when DLAB=1 (see #P0876)
03F9 RW divisor latch high byte (DLM) when DLAB=1 (see #P0876)
03F9 RW interrupt enable register (IER) when DLAB=0 (see #P0877)
03FA R- interrupt identification register (see #P0878)
Information about a pending interrupt is stored here. When the ID
register is addressed, thehighest priority interrupt is held, and
no other interrupts are acknowledged until the CPU services that
interrupt.
03FA -W 16650 FIFO Control Register (FCR) (see #P0879)
03FB RW line control register (LCR) (see #P0880)
03FC RW modem control register (see #P0881)
03FD R- line status register (LSR) (see #P0882)
03FE R- modem status register (MSR) (see #P0883)
03FF RW scratch register (SCR)
(not used for serial I/O; available to any application using 16450,
16550) (not present on original 8250)

(Table P0876)
Values for serial port divisor latch registers:
Some baudrates (using standard 1.8432 Mhz clock):
baudrate divisor DLM DLL
50 2304 09h 00h
75 1536 06h 00h
110 1047 04h 17h
134,5 857 03h 59h
150 768 03h 00h
300 384 01h 80h
600 192 00h C0h
1200 96 00h 60h
1800 64 00h 40h
2000 58 00h 3Ah
2400 48 00h 30h
3600 32 00h 20h
4800 24 00h 18h
7200 16 00h 10h
9600 12 00h 0Ch
19200 6 00h 06h
38400 3 00h 03h
57600 2 00h 02h
115200 1 00h 01h
Note: MIDI baudrate 32250Bd with 4Mhz quarz for c't MIDI interface
following c't 01/1991: '14400' 00h 08h

Bitfields for serial port interrupt enable register (IER):
Bit(s) Description (Table P0877)
7-6 reserved (0)
5 (82510) "timer"
(other) reserved (0)
4 (82510) "transmit machine"
(other) reserved (0)
3 modem-status interrupt enable
2 receiver-line-status interrupt enable
1 transmitter-holding-register empty interrupt enable
0 received-data-available interrupt enable
(also 16550(A) timeout interrupt)
Note: 16550(A) will interrupt with a timeout if data exists in the FIFO
and isn't read within the time it takes to receive four bytes or if
no data is received within the time it takes to receive four bytes
SeeAlso: #P0878

Bitfields for serial port interrupt identification register (IIR):
Bit(s) Description (Table P0878)
7-6 =00 reserved on 8250, 8251, 16450
=01 if FIFO queues enabled but unusable (16550 only)
=11 if FIFO queues are enabled (16550A only) (see also #P0879)
6-5 used by 82510 for bank select (00 = default bank0)
5-4 reserved (0)
3-1 identify pending interrupt with the highest priority
110 (16550,82510) timeout interrupt pending
101 (82510) timer interrupt (see #P0877)
100 (82510) transmit machine (see #P0877)
011 receiver line status interrupt. priority=highest
010 received data available register interrupt. pr.=second
001 transmitter holding register empty interrupt. pr.=third
000 modem status interrupt. priority=fourth
0 =0 interrupt pending. contents of register can be used as a pointer
to the appropriate interrupt service routine
=1 no interrupt pending
Notes: interrupt pending flag uses reverse logic, 0=pending, 1=none
interrupt will occur if any of the line status bits are set
THRE bit is set when THRE register is emptied into the TSR
SeeAlso: #P0877

Bitfields for serial port FIFO control register (FCR):
Bit(s) Description (Table P0879)
7-6 received data available interrupt trigger level (16550)
00 1 byte
01 4 bytes
10 8 bytes
11 14 bytes
6-5 =00 (used to enable 4 byte Rx/Tx FIFOs on 82510???)
=10 ???
5-4 reserved (00)
3 change RXRDY TXRDY pins from mode 0 to mode 1
2 clear XMIT FIFO
1 clear RCVR FIFO
0 enable clear XMIT and RCVR FIFO queues
4-0 (other purpose on 82510???)
Notes: bit 0 must be set in order to write to other FCR bits
bit 1 when set the RCVR FIFO is cleared and this bit is reset
the receiver shift register is not cleared
bit 2 when set the XMIT FIFO is cleared and this bit is reset
the transmit shift register is not cleared
due to a hardware bug, 16550 FIFOs don't work correctly (this
was fixed in the 16550A)
SeeAlso: #P0878

Bitfields for serial port Line Control Register (LCR):
Bit(s) Description (Table P0880)
7 =1 divisor latch access bit (DLAB)
=0 receiver buffer, transmitter holding, or interrupt enable register
access
6 set break enable. serial ouput is forced to spacing state and remains
there.
5-3 PM2 PM1 PM0
x x 0 = no parity
0 0 1 = odd parity
0 1 1 = even parity
1 0 1 = high parity (sticky)
1 1 1 = low parity (sticky)
x x 1 = software parity
2 stop bit length (STB/SBL)
0 one stop bit
1 2 stop bits with (word length 6, 7, 8)
1.5 stop bits with word length 5
1-0 (WLS1-0, CL1-0)
00 word length is 5 bits
01 word length is 6 bits
10 word length is 7 bits
11 word length is 8 bits
SeeAlso: #P0881,#P0882,#P0883

Bitfields for serial port Modem Control Register (MCR):
Bit(s) Description (Table P0881)
7-6 reserved (0)
5 (82510 only) state of OUT0 pin
4 loopback mode for diagnostic testing of serial port
output of transmitter shift register is looped back to receiver
shift register input. In this mode, transmitted data is received
immediately so that the CPU can verify the transmit data/receive
data serial port paths.
If OUT2 is disabled, there is no official way to generate an IRQ
during loopback mode.
3 auxiliary user-designated output 2 (OUT2)
because of external circuity OUT2 must be 1 to master-intr-enableing.
BUG: Some Toshiba Laptops utilize this bit vice versa, newer Toshiba
machines allow assignment of the bit's polarity in system setup.
82050: This bit is only effective, if the chip is being used with an
externally-generated clock.
2 =1/0 auxiliary user-designated output 1 (OUT1)
should generally be cleared!!
Some external hardware, e.g. c't MIDI interface (and compatibles) use
this bit to change the 8250 input clock from 1,8432 MHz to 4Mhz
(enabling MIDI-conformant baudrates) and switching to
MIDI-compatible current loop connectors.
1 force request-to-send active (RTS)
0 force data-terminal-ready active (DTR)
SeeAlso: #P0880,#P0882,#P0883

Bitfields for serial port Line Status Register (LSR):
Bit(s) Description (Table P0882)
7 =0 reserved
=1 on some chips produced by UMC
6 transmitter shift and holding registers empty
5 transmitter holding register empty (THRE)
Controller is ready to accept a new character to send.
4 break interrupt. the received data input is held in the zero bit
state longer than the time of start bit + data bits + parity bit +
stop bits.
3 framing error (FE). the stop bit that follows the last parity or data
bit is a zero bit
2 parity error (PE). Character has wrong parity
1 overrun error (OE). a character was sent to the receiver buffer
before the previous character in the buffer could be read. This
destroys the previous character.
0 data ready. a complete incoming character has been received and sent
to the receiver buffer register.
SeeAlso: #P0880,#P0881,#P0883

Bitfields for serial port Modem Status Register (MSR):
Bit(s) Description (Table P0883)
7 data carrier detect (-DCD)
6 ring indicator (-RI)
5 data set ready (-DSR)
4 clear to send (-CTS)
3 delta data carrier detect (DDCD)
2 trailing edge ring indicator (TERI)
1 delta data set ready (DDSR)
0 delta clear to send (DCTS)
Notes: bits 0-3 are reset when the CPU reads the MSR
bit 4 is the Modem Control Register RTS during loopback test
bit 5 is the Modem Control Register DTR during loopback test
bit 6 is the Modem Control Register OUT1 during loopback test
bit 7 is the Modem Control Register OUT2 during loopback test
SeeAlso: #P0880,#P0881,#P0882

eof


Robert Pengelly

unread,
Nov 11, 2023, 2:57:37 AM11/11/23
to
Yeah, the mouse is connected. I got some new code:

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Set DLAB on.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
mov dx, HEX (03FB)
mov al, HEX (80)
out dx, al

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Set baud rate (low).
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
mov dx, HEX (03F8)
mov al, HEX (60)
out dx, al

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Set baud rate (high).
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
mov dx, HEX (03F9)
mov al, HEX (00)
out dx, al

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; 8 bits, no parity, one stop bit.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
mov dx, HEX (03FB)
mov al, HEX (03)
out dx, al

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; FIFO Control Register.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
mov dx, HEX (03FC)
mov al, HEX (0B)
out dx, al

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Turn on DTR, RTS and OUT2.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
mov dx, HEX (03FA)
mov al, HEX (C7)
out dx, al

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Interrupt when data received.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
mov dx, HEX (03F9)
mov al, HEX (01)
out dx, al

and I'm able to get data when the mouse moves (in a timer handler):

timer_handler:

push ax
push dx
push di

mov dx, HEX (03FD)
xor ax, ax
in al, dx

test al, HEX (01)
jz timer_handler.done

mov di, 4
call writehex

mov al, ' '
call writechr

mov dx, HEX (03F8)
xor ax, ax
in al, dx

mov di, 4
call writehex

mov al, ' '
call writechr

mov dx, HEX (03F8)
xor ax, ax
in al, dx

mov di, 4
call writehex
call crlf

timer_handler.done:

pop di
pop dx
pop ax
iret

so that part is sorted I just don't know what interrupt get fired.

wolfgang kern

unread,
Nov 11, 2023, 3:15:49 AM11/11/23
to
On 11/11/2023 08:57, Robert Pengelly wrote:
...
> so that part is sorted I just don't know what interrupt get fired.

have you enabled and covered it by a routine where its address need to
be stored into the Interrupt Table ?
__
wolfgang
oh, and I forgot to mention that old hardware need delays between I/O
writes (2..5 mSec)

more info from RBIL about IRQ->INT and ENABLE:

port A0 work equal for IRQ 8..15

PORT 0020-003F - PIC 1 - PROGRAMMABLE INTERRUPT CONTROLLER (8259A)
SeeAlso: PORT 00A0h-00AFh"PIC 2",INT 08"IRQ0",INT 0F"IRQ7"

0020 -W PIC initialization command word ICW1 (see #P0010)
0020 -W PIC output control word OCW2 (see #P0015)
0020 -W PIC output control word OCW3 (see #P0016)
0020 R- PIC interrupt request/in-service registers after OCW3
request register:
bit 7-0 = 0 no active request for the corresponding int. line
= 1 active request for corresponding interrupt line
in-service register:
bit 7-0 = 0 corresponding line not currently being serviced
= 1 corresponding int. line currently being serviced

0021 -W PIC ICW2,ICW3,ICW4 immed after ICW1 to 0020 (see
#P0011,#P0012,#P0013)
0021 RW PIC master interrupt mask register OCW1 (see #P0014)

Bitfields for PIC initialization command word ICW1:
Bit(s) Description (Table P0010)
7-5 0 (only used in 8080/8085 mode)
4 ICW1 is being issued
3 (LTIM)
=0 edge triggered mode
=1 level triggered mode
2 interrupt vector size
=0 successive interrupt vectors use 8 bytes (8080/8085)
=1 successive interrupt vectors use 4 bytes (80x86)
1 (SNGL)
=0 cascade mode
=1 single mode, no ICW3 needed
0 ICW4 needed
SeeAlso: #P0011,#P0012,#P0013

Bitfields for PIC initialization command word ICW2:
Bit(s) Description (Table P0011)
7-3 address lines A0-A3 of base vector address for PIC
2-0 reserved
SeeAlso: #P0010,#P0012,#P0013

Bitfields for PIC initialization command word ICW3:
Bit(s) Description (Table P0012)
7-0 =0 slave controller not attached to corresponding interrupt pin
=1 slave controller attached to corresponding interrupt pin
SeeAlso: #P0010,#P0011,#P0013

Bitfields for PIC initialization command word ICW4:

Robert Pengelly

unread,
Nov 11, 2023, 3:21:17 AM11/11/23
to
What do you mean by:

"have you enabled and covered it by a routine where its address need to
be stored into the Interrupt Table ?"

I thought interrupts were "intno * 4 (+ 2)" so for INT 0Ch it would be:

mov [12 * 4], offset handler
mov [12 * 4 + 2], segment

but that doesn't work or am I missing something?

wolfgang kern

unread,
Nov 11, 2023, 4:49:55 AM11/11/23
to
perhaps the way IRQs and INTs were treated/handled.
have you enabled IRQ4 in the PIC port 0x20 (see above)

IRQ4 may not be at INT12, but let's assume it is there.
perhaps you already posted it, what is the code at Seg:Offset
__
wolfgang

Robert Pengelly

unread,
Nov 11, 2023, 5:18:04 AM11/11/23
to
I looked at your table stuff but I'm still a little confused how I enable it.

As for the code all I'm doing is changing my timer interrupt to the IRQ4 one (0x0C * 4 (+ 2) as that's what I think that's what the interrupt get fired).

wolfgang kern

unread,
Nov 11, 2023, 6:41:08 AM11/11/23
to
On 11/11/2023 11:18, Robert Pengelly wrote:
...

> "have you enabled IRQ4 in the PIC port 0x20"
> I looked at your table stuff but I'm still a little confused how I enable it.

only modify one:
in al,0x21
and al,0xEF ;reset bit 4
out 0x21,al

or all if your brave :)
mov al,00
out 0x21.al ;enables all 8 channels

and before you touch any part of the interrupt chain you should disable
IRQs with this single byte reserved for that, re-enable after done.

> As for the code all I'm doing is changing my timer interrupt to the IRQ4 one (0x0C * 4 (+ 2) as that's what I think that's what the interrupt get fired).

[PIT(timer)] fires IRQ_0 (INT08) at default setting 18.2 Hz then:
* PIT handler (either BIOS or DOS or your own) may satisfy the PIT by
reading port_0x40 (not required if set to auto repeat mode, default).
* PIT handler also increments the TIMER-variable
altering this may cause the system to hang.

[COM1 at IRQ4 aka INT!2] fires on your chosen serial-event.
* I'd chose INT on Buffer full for a mouse
* the mouse may send several bytes and each cause an interrupt, so
* the IRQ4 handler must read the com-port and must be aware of how many
bytes may come in addition so it fills a buffer (where is yours?) and
then respond to the result (can be button/wheel/x/y-motions or error).

I never abused the PIT-handler for a test, this is not good practice.
__
wolfgang

Robert Pengelly

unread,
Nov 11, 2023, 12:44:32 PM11/11/23
to
Awesome it works thanks. As for:

and before you touch any part of the interrupt chain you should disable
IRQs with this single byte reserved for that, re-enable after done.

Do you mean some like if I want to do something like:

mov [0x33 * 4], offset handler
mov [0x33 * 4 + 2], segment

then I should disable the IRQ first then re-enable it after I setup the interrupt.

As for the timer I'm using a handler for int 1Ch, is that bad practice or something?

wolfgang kern

unread,
Nov 11, 2023, 6:56:50 PM11/11/23
to
On 11/11/2023 18:44, Robert Pengelly wrote:
,,,
> Awesome it works thanks. As for:
>
> and before you touch any part of the interrupt chain you should disable
> IRQs with this single byte reserved for that, re-enable after done.
>
> Do you mean some like if I want to do something like:

CLI
mov [0x33 * 4], offset handler
mov [0x33 * 4 + 2], segment
;also during write to any PIT-I/O 0x20/A0 0x21/A1
STI

> then I should disable the IRQ first then re-enable it after I setup the interrupt.

yes, this prevents IRQs in the middle of a change which would make it
crash for sure.

> As for the timer I'm using a handler for int 1Ch, is that bad practice or something?

INT 1C is a software INT called by PIC-handler, so it's fine for tests.
But if you use it permanent your mouse is polled rather then interrupt
driven.

almost all my 16 bit IRQ-routines start with:

push ax
push ds
in al,port ;03F8 in case of COM_1 this read releases the IRQ-pin
mov buffer,al
inc buffer
cmp buffer,limit
ja ... ;to reset count and tell received packet is complete
cmp al,..
jz ...
__
wolfgang

Robert Pengelly

unread,
Nov 11, 2023, 7:15:08 PM11/11/23
to
The INT 1Ch was just temporary until I got the interrupt working, I've now moved the mouse stuff into INT 0Ch and it all works. Again thanks for the help to enable interrupts. I'm not exactly sure what I want to do in INT 1C at the moment so using it for tests is fine for now. As for the INT 0C handler I have:

mouse_handler:

push ax
push dx

mov dx, HEX (03FD)
xor ax, ax
in al, dx
nop

test al, 0b01000000
jz mouse_handler.done

test al, 0b00000001
jz mouse_handler.done

mov dx, HEX (03F8)
xor ax, ax
in al, dx
nop

mov dx, HEX (03F8)
xor ax, ax
in al, dx
nop

mov al, 'M'
call writechr

mouse_handler.done:

mov dx, HEX (20)
mov al, HEX (20)
out dx, al

pop dx
pop ax
iret

Also, still regarding mice I also have PS/2 support using INT 15h to set everything up and then I have:

mouse_callback:

push bp
mov bp, sp

push ax
push bx
push cx
push dx

mov al, [bp + 12]
mov bl, al
mov cl, 3
shl al, cl

sbb dh, dh
cbw

mov dl, [bp + 8]
mov al, [bp + 10]

neg dx

mov cx, cs:[mouse_y]
add dx, cx

mov cx, cs:[mouse_x]
add ax, cx

mov cs:[mouse_x], ax
mov cs:[mouse_y], dx

call writedec
mov al, ' '
call writechr
mov ax, dx
call writedec
call crlf

mouse_callback.done:

pop dx
pop cx
pop bx
pop ax
pop bp
retf

which works but I get values 0000 - FFFF from it when the screen is 80x25 initially so should I be capping the X and Y coordinates?

wolfgang kern

unread,
Nov 11, 2023, 8:14:22 PM11/11/23
to
> xor ax, ax ;this isn't required
> in al, dx
> nop ;NOPs wont delay
>
> mov dx, HEX (03F8) ;DX didn't change
> xor ax, ax
> in al, dx
> nop
>
> mov al, 'M'
> call writechr
>
> mouse_handler.done:
>
> mov dx, HEX (20)
> mov al, HEX (20)
> out dx, al

how about a shorter variant: MOV AL,0x20 OUT AL,[0x20]

> pop dx
> pop ax
> iret

you could imply button recognition here.
yes the mouse send only delta X/Y coordinates w/o knowing screen limits,
so it's on you to scale and clip to the current screen mode.
__
wolfgang
btw: I don't like your awful slow detouring HLL-styled mouse callback.

Robert Pengelly

unread,
Nov 11, 2023, 8:26:45 PM11/11/23
to
What do you mean by "HLL-styled"?

wolfgang kern

unread,
Nov 11, 2023, 10:04:32 PM11/11/23
to
>> btw: I don't like your awful slow detouring HLL-styled mouse callback.
> What do you mean by "HLL-styled"?

it looks like C-compiled bloatware crap copied from a C-library.
__
wolfgang

Robert Pengelly

unread,
Nov 11, 2023, 10:12:44 PM11/11/23
to
No, I found the code at https://stackoverflow.com/questions/54280828/making-a-mouse-handler-in-x86-assembly. Not sure where they got the code though.

Robert Pengelly

unread,
Nov 12, 2023, 6:11:57 AM11/12/23
to
I'm having a little bit of trouble with the cooridnates from the IRQ4. Going by https://roborooter.com/post/serial-mice/ I have:

mov dx, HEX (03FD)
xor ax, ax
in al, dx
nop

test al, 0b01000000
jz serial_handler.done

test al, 0b00000001
jz serial_handler.done

mov dx, HEX (03F8)
xor ax, ax
in al, dx
nop

mov si, ax
mov di, ax

and si, 0b00001100
and di, 0b00000011

mov cl, 4
shl si, cl

mov cl, 6
shl di, cl

mov dx, HEX (03F8)
xor ax, ax
in al, dx
nop

or di, ax
add di, cs:[mouse_x]

mov dx, HEX (03F8)
xor ax, ax
in al, dx
nop

or si, ax
add si, cs:[mouse_y]

but the initial values seem a bit off (e.g. for Y I have 205 and X is 77), have I mixed up the values or am I just doing the calculations wrong after I read the port?

wolfgang kern

unread,
Nov 12, 2023, 7:08:42 AM11/12/23
to
On 12/11/2023 12:11, Robert Pengelly wrote:
...
the mouse sends a sequence of bytes where every byte causes in IRQ.
so you first need to fill a buffer with the gotten bytes before you can
calculate/scale/interpret the values. mouse IRQs can easy come out of
sync, so checking always for the first byte mark is a good idea.
__
wolfgang


Robert Pengelly

unread,
Nov 12, 2023, 8:27:43 AM11/12/23
to
Oh I thought you had to get them all at the same time when the interrupt was fired. As for filling the buffer how would I tell the interrupts apart? I can test for 0x40 and 0x01 (which I'm already doing) I'm just a little confused how I would know whether it's the 1st, 2nd and 3rd bytes.

wolfgang kern

unread,
Nov 12, 2023, 8:46:59 AM11/12/23
to
> Oh I thought you had to get them all at the same time when the interrupt was fired. As for filling the buffer how would I tell the interrupts apart? I can test for 0x40 and 0x01 (which I'm already doing) I'm just a little confused how I would know whether it's the 1st, 2nd and 3rd bytes.

there is a mark for the first byte (reread the RBIL I posted)
I use one variable for count down (easier than count up) and use this
with BX as an index into my buffer.
and when the buffer is filled I adjust all my mouse-variables which I
later use on my mSec timer-base schedule to update cursor and act on
buttons.
__
wolfgang

Robert Pengelly

unread,
Nov 12, 2023, 9:34:37 AM11/12/23
to
Yeah, there's bit 6 for the initial bit, I weren't sure if there's anything identifying the others. So basically have two variables one being a counter and just write to the buffer until I get three (or if it's counting down then it would be until I hit zero)? As for:

> I use one variable for count down (easier than count up) and use this
> with BX as an index into my buffer.

How do you use it for the buffer if your counting down? If you were counting up you could shl by 8 and add that to the buffer offset.

wolfgang kern

unread,
Nov 12, 2023, 10:18:45 AM11/12/23
to
On 12/11/2023 15:34, Robert Pengelly wrote:
...
>>>> the mouse sends a sequence of bytes where every byte causes in IRQ.
>>>> so you first need to fill a buffer with the gotten bytes before you can
>>>> calculate/scale/interpret the values. mouse IRQs can easy come out of
>>>> sync, so checking always for the first byte mark is a good idea.
>>> Oh I thought you had to get them all at the same time when the interrupt was fired. As for filling the buffer how would I tell the interrupts apart? I can test for 0x40 and 0x01 (which I'm already doing) I'm just a little confused how I would know whether it's the 1st, 2nd and 3rd bytes.
>> there is a mark for the first byte (reread the RBIL I posted)
>> I use one variable for count down (easier than count up) and use this
>> with BX as an index into my buffer.
>> and when the buffer is filled I adjust all my mouse-variables which I
>> later use on my mSec timer-base schedule to update cursor and act on
>> buttons.

> Yeah, there's bit 6 for the initial bit, I weren't sure if there's anything identifying the others. So basically have two variables one being a counter and just write to the buffer until I get three (or if it's counting down then it would be until I hit zero)?

yes.

As for:
>> I use one variable for count down (easier than count up) and use this
>> with BX as an index into my buffer.

> How do you use it for the buffer if your counting down? If you were counting up you could shl by 8 and add that to the buffer offset.

no shift required here at all:

push ...ds,ax,bx,cx,dx
... ds become ptr to my data
IN AL,port
TEST AL,0x40
jz skip_init
xor bx,bx
MOV CX,3 ;(or eight in my case)
MOV [count],cl
MOV [index].bx
skip_init:
MOV BX,[index]
MOV [BX+buffer],AL
INC word[index] ;or: INC BX |MOV [index],BX
DEC byte[count]
pop ... dx,cx,bx
MOV AL,0x20
out 0xA0,AL
jnz done_it
got_all:
;store/modify, update only variables, actions are done in idle queue.
done_it:
pop ax
pop ds
iret
__
wolfgang

Robert Pengelly

unread,
Nov 12, 2023, 2:04:55 PM11/12/23
to
Ahh you have 3 variables instead of 2, right I think I understand. What should I do about the buffer though? Like should I get them in say a 1Ch handler to move the cursor in there?

Robert Pengelly

unread,
Nov 12, 2023, 2:13:16 PM11/12/23
to
That should have been "What should I do about the values though?" Like should I parse the buffer in say 1Ch and move the cursor in there?

Robert Pengelly

unread,
Nov 12, 2023, 3:31:34 PM11/12/23
to
Am I updating the x and y correctly with:

xor ax, ax
xor dx, dx
xor cx, cx
mov bx, offset buffer

mov al, [bx]
mov dl, [bx]

and al, HEX (0C)
and dl, HEX (03)

mov cl, 4
shl ax, cl

mov cl, 6
shl dx, cl

mov cl, [bx + 2]
or ax, cx
add ax, [mouse_y]

mov cl, [bx + 1]
or dx, cx
add dx, [mouse_x]

mov [mouse_x], dx
mov [mouse_y], ax

If I am how do I stop it wrapping around the screen as doing:

cmp ax, 80
jge .no_x_inc

cmp ax, 0
jl .no_x_inc

.inc_x:

mov cs:[mouse_x], ax

.no_x_inc:

cmp dx, 25
jge .done

cmp dx, 0
jl .done

.inc_y:

mov cs:[mouse_y], dx

doesn't seem to work.

wolfgang kern

unread,
Nov 12, 2023, 4:51:33 PM11/12/23
to
On 12/11/2023 21:31, Robert Pengelly wrote:
...
>>> Ahh you have 3 variables instead of 2, right I think I understand. What should I do about the buffer though? Like should I get them in say a 1Ch handler to move the cursor in there?
>> That should have been "What should I do about the values though?" Like should I parse the buffer in say 1Ch and move the cursor in there?

yeah, sorry for delayed response, I tend to sleep from time to time :)
if your screen is in text-mode then you need to scale all down by 8
because mice work on pixels rather than on character row/column.
I never supported a mouse in text mode, so my experience is limited to
graphic modes.
my clipping just used AND or CMOVcc w/o CMP/JUMP lines.

__
wolfgang

Robert Pengelly

unread,
Nov 12, 2023, 5:03:19 PM11/12/23
to
What values am I scaling down the values passed to the interrupt or the values I calculate after I got all three bytes?

> I never supported a mouse in text mode, so my experience is limited to
> graphic modes.

I'm only using text mode at the moment as a test case. The plan is to only have the mouse in graphics mode eventually. I didn't think of using AND, would I do something like "and [mouse_x], 319" and would that also work if the value is negative so it will stay at zero?

Robert Pengelly

unread,
Nov 12, 2023, 5:14:51 PM11/12/23
to
Also, how do I scale down a number in assembly?

wolfgang kern

unread,
Nov 12, 2023, 6:48:45 PM11/12/23
to
> What values am I scaling down the values passed to the interrupt or the values I calculate after I got all three bytes?

the latter. text character cells may be 16*8 so vertical need SHR,4
note that the screen coordinates are always positive 0,0 is top left.

>> I never supported a mouse in text mode, so my experience is limited to
>> graphic modes.
>
> I'm only using text mode at the moment as a test case. The plan is to only have the mouse in graphics mode eventually. I didn't think of using AND, would I do something like "and [mouse_x], 319" and would that also work if the value is negative so it will stay at zero?

319 may not be a good choice :)
my older standard mode was 1024x768x8 so my AND values were 03ff/2ff
this may not make it zero but keeps it on bottom/right edges.
I later used CMP 03f8/02f8 followed by CMOVa to clip it visible.

an AND with a positive value will always result in a positive.
__
wolfgang

wolfgang kern

unread,
Nov 12, 2023, 6:55:27 PM11/12/23
to
On 12/11/2023 23:14, Robert Pengelly wrote:
...
> Also, how do I scale down a number in assembly?

SHR 3 ;aka divide by 8
SHR 4 ;aka divide by 16
both rounds down, but who cares?

odd divide values can perform with a combination of SHR and MUL or even
with the famous awful slow DIV instruction.

__
wolfgang

Robert Pengelly

unread,
Nov 12, 2023, 7:01:18 PM11/12/23
to
So I was doing it right. I have:

xor ax, ax
xor dx, dx
xor cx, cx

mov al, [buffer]
and al, HEX (0C)

mov dl, [buffer]
and dl, HEX (03)

mov cl, 4
shl ax, cl

mov cl, 6
shl dx, cl

mov cl, [bx + 2]
or ax, cx
add ax, [mouse_y]

mov cl, 4
shr ax, cl

mov cl, [bx + 1]
or dx, cx
add dx, [mouse_x]

mov cl, 3
shr dx, cl

mov [mouse_x], dx
mov [mouse_y], ax

but I'm getting weird results, am I shifting in the right place?

wolfgang kern

unread,
Nov 12, 2023, 7:31:02 PM11/12/23
to
I'd keep mouse positions stored in pixels and only scale down for cursor
updates.
__
wolfgang

Robert Pengelly

unread,
Nov 12, 2023, 7:39:47 PM11/12/23
to
The following code gives weird results as well:

timer_handler:

mov bx, cs:[mouse_x]
shr bx
shr bx
shr bx

mov cx, cs:[mouse_y]
shr cx
shr cx
shr cx
shr cx

timer_handler.move:

mov ah, HEX (02)
xor bh, bh
mov dh, cl
mov dl, bl
int HEX (10)

I've removed the shifts from the irq handler but the cursor is dodgy.

wolfgang kern

unread,
Nov 12, 2023, 7:56:18 PM11/12/23
to
then I assume that it is off screen, so you may not clip it correct.
__
wolfgang

Robert Pengelly

unread,
Nov 12, 2023, 8:11:15 PM11/12/23
to
Can you see anything wrong with the irq handler I sent a few messages ago? Also, can you see anything that may be wrong in:

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Clear interrupts while we set other up.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
cli

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; We'll use the extra segment to offset the correct positions
;; so make sure it is zero.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
xor ax, ax
mov es, ax

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Setup INT 0Ch.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
mov word ptr es:[HEX (0C) * 4], offset serial_handler
mov word ptr es:[HEX (0C) * 4 + 2], cs

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Set DLAB on.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
mov dx, HEX (03FB)
mov al, HEX (80)
out dx, al

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Set baud rate (low).
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
mov dx, HEX (03F8)
mov al, HEX (60)
out dx, al

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Set baud rate (high).
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
mov dx, HEX (03F9)
xor al, al
out dx, al

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; 8 bits, no parity, one stop bit.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
mov dx, HEX (03FB)
mov al, HEX (03)
out dx, al

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; FIFO Control Register.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
mov dx, HEX (03FC)
mov al, HEX (0B)
out dx, al

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Turn on DTR, RTS and OUT2.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
mov dx, HEX (03FA)
mov al, HEX (C7)
out dx, al

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Interrupt when data received.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
mov dx, HEX (03F9)
mov al, HEX (01)
out dx, al

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Enable interrupts on IRQ4.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
in al, HEX (21)

and al, HEX (EF)
out HEX (21), al

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Restore interrupts.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
sti

wolfgang kern

unread,
Nov 12, 2023, 8:28:24 PM11/12/23
to
On 13/11/2023 02:11, Robert Pengelly wrote:
> On Monday, 13 November 2023 at 00:56:18 UTC, wolfgang kern wrote:

>>>>>>> Also, how do I scale down a number in assembly?
>>>>>> SHR 3 ;aka divide by 8
>>>>>> SHR 4 ;aka divide by 16
>>>>>> both rounds down, but who cares?
>>>>>>
>>>>>> odd divide values can perform with a combination of SHR and MUL or even
>>>>>> with the famous awful slow DIV instruction.

>>>>> So I was doing it right. I have:
>>>>>
>>>>> xor ax, ax
>>>>> xor dx, dx
>>>>> xor cx, cx
>>>>>
>>>>> mov al, [buffer]
>>>>> and al, HEX (0C)
>>>>>
>>>>> mov dl, [buffer]
>>>>> and dl, HEX (03)
>>>>>
>>>>> mov cl, 4
>>>>> shl ax, cl
>>>>>
>>>>> mov cl, 6
>>>>> shl dx, cl

>>>>> mov cl, [bx + 2]

when did you assign BX for point to buffer ??

>>>>> or ax, cx
>>>>> add ax, [mouse_y]
>>>>>
>>>>> mov cl, 4
>>>>> shr ax, cl
>>>>>
>>>>> mov cl, [bx + 1]
>>>>> or dx, cx
>>>>> add dx, [mouse_x]
>>>>>
>>>>> mov cl, 3
>>>>> shr dx, cl
>>>>>
>>>>> mov [mouse_x], dx
>>>>> mov [mouse_y], ax
>>>>>
>>>>> but I'm getting weird results, am I shifting in the right place?

>>>> I'd keep mouse positions stored in pixels and only scale down for cursor
>>>> updates.

>>> The following code gives weird results as well:
>>>
>>> timer_handler:
>>>
>>> mov bx, cs:[mouse_x]
>>> shr bx
>>> shr bx
>>> shr bx
>>>
>>> mov cx, cs:[mouse_y]
>>> shr cx
>>> shr cx
>>> shr cx
>>> shr cx
>>>
>>> timer_handler.move:
>>>
>>> mov ah, HEX (02)
>>> xor bh, bh
>>> mov dh, cl
>>> mov dl, bl
>>> int HEX (10)

>>> I've removed the shifts from the irq handler but the cursor is dodgy.
>> then I assume that it is off screen, so you may not clip it correct.

Robert Pengelly

unread,
Nov 12, 2023, 8:41:40 PM11/12/23
to
I forgot that I was using bx when I modified the code. That's been fixed but still having problems, did you see anything else wrong?

wolfgang kern

unread,
Nov 12, 2023, 11:16:17 PM11/12/23
to
I'll check on it but give me some more time, there are several layers of
dust on my memory and on the book shelf as well.
__
wolfgang

wolfgang kern

unread,
Nov 13, 2023, 3:37:18 AM11/13/23
to
On 13/11/2023 05:16, wolfgang kern wrote:
...
>>>>>>>> So I was doing it right. I have:

>>>>>>>> xor ax, ax
>>>>>>>> xor dx, dx
>>>>>>>> xor cx, cx
>>>>>>>>
>>>>>>>> mov al, [buffer]

I'd check here for the sync bit and reset IRQ4 variables if not.

>>>>>>>> and al, HEX (0C) get b7&6 Y into b3&2 AL
>>>>>>>>
>>>>>>>> mov dl, [buffer] get b7&6 X into b1&0 DL
>>>>>>>> and dl, HEX (03)
>>>>>>>>
>>>>>>>> mov cl, 4
>>>>>>>> shl ax, cl OK b7&6 Y are correct in AL
>>>>>>>>
>>>>>>>> mov cl, 6
>>>>>>>> shl dx, cl OK b7&6 X are correct in DL

I found my hand written notes from 1980 on Serial Mice now,
two button standard:
1200 baud, No Parity, 7(or8)bit, 1 stop bit
1st byte
7 * don't care
6 == 1 sync bit
5 Right Button Down
4 Left Button Down
3 b7 Y
2 b6 Y
1 b7 X
0 b6 X
2nd byte
7 *
6 == 0
5..0 b5..0 X
3rd byte
7 *
6 ==0
5..0 b5..0 Y
assume BX points to buffer yet
>>> mov cl, [bx + 2]

AND CL, 0x7f ;can't be sure for b7==0
;missed to sign extend AX,AL
CBW makes AX sign extended from AL
or ax, cx OK insert low 6 bits

ADD [mouse_y],AX it does a SUB if AX is negativ

mov cl, [bx + 1]
AND CX,0x7f
MOV AL,DL
CBW
OR AX,CX
ADD [mouse_x],AX
DONE:





>>>>>>> I'd keep mouse positions stored in pixels and only scale down for
>>>>>>> cursor
>>>>>>> updates.
>>>>>> The following code gives weird results as well:
>>>>>>
>>>>>> timer_handler:
>>>>>>
>>>>>> mov bx, cs:[mouse_x]
>>>>>> shr bx
>>>>>> shr bx
>>>>>> shr bx
>>>>>>
>>>>>> mov cx, cs:[mouse_y]
>>>>>> shr cx
>>>>>> shr cx
>>>>>> shr cx
>>>>>> shr cx
>>>>>>
>>>>>> timer_handler.move:
>>>>>>
>>>>>> mov ah, HEX (02)
>>>>>> xor bh, bh
>>>>>> mov dh, cl
>>>>>> mov dl, bl
>>>>>> int HEX (10)
>>>
>>>>>> I've removed the shifts from the irq handler but the cursor is dodgy.
>>>>> then I assume that it is off screen, so you may not clip it correct.
>>>> Can you see anything wrong with the irq handler I sent a few
>>>> messages ago? Also, can you see anything that may be wrong in:

I'll check on the following later on ...
YES
__
wolfgang

Robert Pengelly

unread,
Nov 13, 2023, 3:49:14 AM11/13/23
to
Just as I was going to reply you sent that last message. Anyways this seems to work:

xor ax, ax
xor dx, dx
xor cx, cx
mov bx, offset buffer

mov al, [bx]
and al, HEX (0C)

mov cl, 4
shl ax, cl

cbw

mov cl, [bx + 2]
or ax, cx
add [mouse_y], ax

mov al, [bx]
and al, HEX (03)

mov cl, 6
shl ax, cl

cbw

mov cl, [bx + 1]
or ax, cx
add [mouse_x], ax

but not sure if it's right or not. You did just have "CBW makes AX sign extended from AL" so maybe the code is right.

wolfgang kern

unread,
Nov 13, 2023, 4:01:29 AM11/13/23
to
On 13/11/2023 09:49, Robert Pengelly wrote:
> On Monday, 13 November 2023 at 08:37:18 UTC, wolfgang kern wrote:
...
...
> Just as I was going to reply you sent that last message. Anyways this seems to work:
>
> xor ax, ax
> xor dx, dx
> xor cx, cx
> mov bx, offset buffer
>
> mov al, [bx]
> and al, HEX (0C)
>
> mov cl, 4
> shl ax, cl
>
> cbw
>
> mov cl, [bx + 2]
> or ax, cx
> add [mouse_y], ax
>
> mov al, [bx]
> and al, HEX (03)
>
> mov cl, 6
> shl ax, cl
>
> cbw
>
> mov cl, [bx + 1]
> or ax, cx
> add [mouse_x], ax
>
> but not sure if it's right or not. You did just have "CBW makes AX sign extended from AL" so maybe the code is right.

Fine so far, you rely on b7=0 in first byte which may cause errors.
you could check of the first byte got a sync bit to avoid jumping mice.
__
wolfgang

Robert Pengelly

unread,
Nov 13, 2023, 4:11:24 AM11/13/23
to
I'm a little confused by :

you rely on b7=0 in first byte which may cause errors.
you could check of the first byte got a sync bit to avoid jumping mice.

You had:

1st byte
7 * don't care
6 == 1 sync bit
5 Right Button Down
4 Left Button Down
3 b7 Y
2 b6 Y
1 b7 X
0 b6 X

in your previous message, do you mean bit 6 (i.e. the sync bit). If you do should I do something like:

test al, 0x40
jnz .done

before the updating code

wolfgang kern

unread,
Nov 13, 2023, 4:38:25 AM11/13/23
to
yes, but you can do it already in the IRQ routine.
__
wolfgang

I posted this a few days ago:

Robert Pengelly

unread,
Nov 13, 2023, 4:39:30 AM11/13/23
to
Yeah, I have. Thanks for all the help.

wolfgang kern

unread,
Nov 13, 2023, 4:47:06 AM11/13/23
to
On 13/11/2023 10:39, Robert Pengelly wrote:

> Yeah, I have. Thanks for all the help.

You're Welcome,
this trip into the past confirmed that my brain still works,
almost all other body parts are either artificial or death :)
__
wolfgang
whenever you got more questions just ask away.

Robert Pengelly

unread,
Dec 1, 2023, 9:04:58 AM12/1/23
to
Can you figure out what I'm doing wrong with the following code:

serial_handler:

push ax
push bx
push cx
push dx
push ds

mov ax, cs
mov ds, ax

mov dx, HEX (03FD)
in al, dx

test al, HEX (40)
jz serial_handler.done

test al, HEX (01)
jz serial_handler.done

mov dx, HEX (03F8)
in al, dx

mov bx, [serial_index]
mov [serial_buffer + bx], al

inc word ptr [serial_index]

cmp bx, 2
jb serial_handler.done

serial_handler.got_all:

mov word ptr [serial_index], 0

xor ax, ax
xor dx, dx
xor cx, cx

mov bx, offset serial_buffer
mov al, [bx]

test al, HEX (40)
jz serial_handler.done

and al, HEX (0C)

mov cl, 4
shl ax, cl

cbw

mov cl, [bx + 2]
or ax, cx
mov [delta_y], ax

mov al, [bx]
and al, HEX (03)

mov cl, 6
shl ax, cl

cbw

mov cl, [bx + 1]
or ax, cx
mov [delta_x], ax

serial_handler.done:

mov al, HEX (20)
out HEX (20), al

pop ds
pop dx
pop cx
pop bx
pop ax
iret

If the "mov [delta_x], ax and mov [delta_y], ax" parts are changed from "add [mouse_x], ax and add [mouse_y], ax". The latter was working but for some reason the new code doesn't.

Robert Pengelly

unread,
Dec 1, 2023, 9:09:27 AM12/1/23
to
Also, forgot to mention that if I change "cmp bx, 2" to "cmp bx, 1" the x position seems to update like expected.

Robert Pengelly

unread,
Dec 1, 2023, 9:21:41 AM12/1/23
to
I reverted back to previous code:

serial_handler:

push ax
push bx
push cx
push dx
push ds

mov ax, cs
mov ds, ax

mov dx, HEX (03FD)
in al, dx

test al, HEX (40)
jz serial_handler.done

test al, HEX (01)
jz serial_handler.done

mov dx, HEX (03F8)
in al, dx

test al, HEX (40)
jz serial_handler.skip_init

xor bx, bx
mov cx, 2

mov [serial_count], cx
mov [serial_index], bx

serial_handler.skip_init:

mov bx, offset serial_buffer
add bx, [serial_index]

mov [bx], al
inc word ptr [serial_index]

dec word ptr [serial_count]
jnz serial_handler.done

serial_handler.got_all:
and things seem to be fixed but the Y position seems to be jumpy. Any ideas how to fix that.
0 new messages