1. Interrupt driven serial read
Hi,
I tried to improve Serial.E V1.01 (C) 1997 from PJB Systems.
Unfortunately, I can't get it to work. If someone could have a look at the
code below and tell we what is wrong, it would be nice.
Jean-Marc
-- Start of code --
--
ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÂÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
-- ³ Serial.E V1.01 (C) 1997 PJB Systems ³ Serial RS232
lib ³
--
ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÁÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ
global integer PortIdx PortIdx = 1
global integer LocalEcho LocalEcho = 0
global sequence PortBase PortBase = {#3F8,#2F8,#3E8,#2E8}
include Ports.E -- Come on RDS ! Even GWBASIC has I/O Access !!!
include machine.e
atom handlerA_address, handlerB_address
sequence usual_address
atom code_segment
-- record the values of the data segment and code segment
atom segment, pointeur_ecr_2, pointeur_lect_2, tampon_rec_2
segment = allocate(4)
lock_memory(segment, 4)
pointeur_ecr_2 = allocate(4)
lock_memory(pointeur_ecr_2, 4)
poke4(pointeur_ecr_2, 0)
pointeur_lect_2 = allocate(4)
lock_memory(pointeur_lect_2, 4)
poke4(pointeur_lect_2, 0)
tampon_rec_2 = allocate(1024)
lock_memory(tampon_rec_2, 1024)
mem_set(tampon_rec_2, 0, 1024)
sequence save_segment_code
save_segment_code = {
#53, -- push ebx
#0E, -- push cs or #1E push ds -- only a 16-bit value
#5B, -- pop ebx
#89, #1D} & int_to_bytes(segment) & -- mov segment, ebx
{#5B, -- pop ebx
#C3 -- ret
}
-- note: there's no "pop cs" instruction
atom save_segment
save_segment = allocate(length(save_segment_code))
poke(save_segment, save_segment_code)
call(save_segment) -- save code segment
-- N.B. Only read the low order two bytes! - See data segment below
code_segment = peek(segment) + 256 * peek(segment+1)
poke(save_segment+1, #1E)
call(save_segment) -- save data segment
sequence GetSerialByte
GetSerialByte = {
#1E, -- push ds
#60, -- pushad
-- restore our data segment value:
#BB} & peek({segment, 2}) & {0,0} & -- mov ebx, data segment value
{#53, -- push ebx
#1F, -- pop ds
#FB, -- sti
#BA,#F8,#02,0,0, -- mov edx,0x2f8
#EC, -- in al,dx
#8B,#3E} & int_to_bytes(pointeur_ecr_2) & { -- mov
di,pointeur_ecr_2
#88,#85} & int_to_bytes(tampon_rec_2) & { -- mov
[di+tampon_rec_2],al
#A1} & int_to_bytes(pointeur_ecr_2) & { -- mov ax,pointeur_ecr_2
#99, -- cwd
#B9,#00,#04, -- mov cx,0x400
#F7,#F9, -- idiv cx
#92, -- xchg ax,dx
#40, -- inc ax
#A3} & int_to_bytes(pointeur_ecr_2) & { -- mov pointeur_ecr_2,ax
#A1} & int_to_bytes(pointeur_ecr_2) & { -- mov ax,pointeur_ecr_2
#3B,#06} & int_to_bytes(pointeur_lect_2) & { -- cmp
ax,pointeur_lect_2
#75,#12, -- jnz #12
#A1} & int_to_bytes(pointeur_lect_2) & { -- mov ax,pointeur_lect_2
#99, -- cwd
#B9,#00,#04, -- mov cx,0x400
#F7,#F9, -- idiv cx
#92, -- xchg ax,dx
#40, -- inc ax
#A3} & int_to_bytes(pointeur_lect_2) & { -- mov pointeur_lect_2,ax
#B0,#20, -- mov al,0x20
#E6,#20, -- out 0x20,al
#61, -- popad
#1F, -- pop ds
#CF -- iretd -- return from interrupt
}
atom InputAsm
sequence OrigVector
integer HookInstalled
HookInstalled = 0
global procedure InitCom2()
-- init code space for assembler routine
if HookInstalled then
return
end if
InputAsm = allocate(length(GetSerialByte))
lock_memory(InputAsm, length(GetSerialByte))
if not InputAsm then
puts(1,"Not enough memory !\n")
abort(1)
end if
OrigVector = get_vector(#0B)
poke(InputAsm,GetSerialByte)
set_vector(#0B,{code_segment,InputAsm})
HookInstalled = 1
end procedure -- InitCom2()
global procedure FreeCom2()
-- free memory occupied by assembler routines
if not HookInstalled then
return
end if
set_vector(#0B,OrigVector)
free(InputAsm)
HookInstalled = 0
end procedure -- FreeCom2()
integer diff
diff = -1
global function ReadPending()
integer plect, pecr
if not HookInstalled then
return -1
end if
plect = peek4u(pointeur_lect_2)
pecr = peek4u(pointeur_ecr_2)
if (plect-pecr) != diff then
printf(1,"Plect = %d, Pecr= %d\n",{plect, pecr})
diff = plect - pecr
end if
if pecr > plect then
return 1024 + plect - pecr
else
return plect - pecr
end if
end function
global function Com2Read()
if not HookInstalled then
return -1
end if
return peek4u(tampon_rec_2+pointeur_lect_2)
end function
global procedure SendSerialByte(integer p,integer b)
integer addr, lsr, ecd
if (p > 0) and (p < 5) then
if (b >= 0) and (b < 256) then
addr = PortBase[p]
ecd = 1000
lsr = 0
while (lsr = 0) and (ecd > 0) do
lsr = and_bits(Input(addr + 5),64)
ecd = ecd - 1
end while
Output(b,addr)
end if
end if
end procedure
global function GetPortBPDS(integer port)
integer addr,dlab,baud, dvsr,tmp1,tmp2,parity,data,stop
addr = PortBase[port]
dlab = Input(addr + 3)
tmp1 = dlab
dlab = or_bits(dlab,#80)
Output(dlab,addr + 3)
dvsr = Input(addr) + (Input(addr + 1) * 256)
dlab = and_bits(dlab,#7F)
Output(dlab,addr + 3)
if dvsr > 0 then
baud = floor(115200 / dvsr)
else
baud = 0
end if
tmp2 = and_bits(tmp1,#38)
parity = tmp2
if tmp2 = 8 then
parity = -1
elsif tmp2 = 24 then
parity = 1
end if
if and_bits(tmp1,4) > 0 then
stop = 2
else
stop = 1
end if
data = and_bits(tmp1,3) + 5
return {baud,parity,data,stop}
end function
global procedure SetPortBPDS
(integer port,integer baud,integer parity,integer data, integer stop)
integer ok,addr, dlab, dvsr, dl, dh, p, s
ok = 1
if (port < 1) or (port > 4) then ok= 0 end if
if (baud < 75) or (baud > 115200) then ok = 0 end if
if (data < 5) or (data > 8) then ok = 0 end if
if (stop < 1) or (stop > 2) then ok = 0 end if
if ok > 0 then
dvsr = floor(115200 / baud)
dl = and_bits(#FF,dvsr)
dh = floor(dvsr / 256)
addr = PortBase[port]
p = 0
if parity > 0 then
p = 24
elsif parity < 0 then
p = 8
end if
s = 0
if stop = 2 then
s = 4
end if
dlab = #80 + p + s + (data - 5)
Output(dlab,addr + 3)
Output(dl,addr)
Output(dh,addr + 1)
dlab = and_bits(dlab,#7F)
Output(dlab,addr + 3)
end if
end procedure
-- End of code --
-- Main program --
--
ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
¿
-- ³ E-Term.EX V1.01 by PJB Systems
³
--
ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
Ù
include Serial2.E
integer Port,Baud,Parity,Data,Stop,rx,tx,rcnt
sequence rbuff rbuff = {}
sequence BPDS
Port = 2 -- Change this if you like to 1, 2, 3 or 4
InitCom2()
puts(1,"Interrupt handler initiated !\n")
SetPortBPDS(Port,9600,0,8,1) -- You can change the baud,parity,data & stop
-- ³ ³ ³ ³ ÀÄÄÄÄ Stop bit 1 or 2
-- ³ ³ ³ ÀÄÄÄÄÄÄ Data bits 5,6,7 & 8
-- ³ ³ ÀÄÄÄÄÄÄÄÄ Parity 0 = None, 1 = Even, -1 = Odd
-- ³ ÀÄÄÄÄÄÄÄÄÄÄÄÄÄ Baud rate 75 ~ 115200
-- ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ Port COM1: to COM4:
tx = 0
while tx != 27 do
if ReadPending()>0 then
rx = Com2Read()
if rx >= 0 then -- Catch data as it comes in
printf(1,"%s",{rx})
end if
end if
tx = get_key() -- Get key presses
if tx > 0 then -- Send key
SendSerialByte(Port,tx)
end if
end while
FreeCom2()
puts(1,"Bye.\n")