Смекни!
smekni.com

Апаратно–програмний комплекс GSM-МТМ (стр. 11 из 11)

; відновлення векторів переривань

_restore_com PROC FAR

push bp

mov bp,sp

push si

; відзначаємо COM порт як не активний

mov si,CURRENT_AREA

mov installed[si],0

; відновлюємо вектор переривання

mov ah,25H

mov al,int_com[si]

mov dx,old_com_off[si]

mov bx,old_com_seg[si]

push ds

mov ds,bx

int 21h

pop ds

pop si

mov sp,bp

pop bp

ret

_restore_com ENDP

; відкрити COM порт

; скидання буферів передавача і приймача,

; ініціалізація регістрів UART 8250

; дозвіл переривань від UART 8250

; (програмування контролера переривань)

; [bp+6] = швидкість обміну

; [bp+8] = спосіб з'єднання - M(Модем), D(Нуль-модем)

; [bp+10] = парність - N(ONE), O(DD), E(VEN), S(PACE), M(ARK)

; [bp+12] = кількість стопових бітів 1, 2

_open_com PROC FAR

push bp

mov bp,sp

push si

mov si,CURRENT_AREA

; забороняємо переривання

cli

mov ax,[bp+6]

mov baud_rate[si],ax

mov bh,[bp+8]

mov device_conn[si],bh

mov bl,[bp+10]

mov parity[si],bl

mov ch,[bp+12]

mov stop_bits[si],CH

; скидаємо буфери і покажчики

mov start_s_data[si],0

mov end_s_data[si],0

mov start_r_data[si],0

mov end_r_data[si],0

mov size_s_data[si],0

mov size_r_data[si],0

; чи перевіряємо установлений вже оброблювач переривань

test installed[si],1

jnz reset_uart

jmp exit_open

reset_uart:

; установлюємо регістри UART 8250

; скидаємо регістр керування модемом

mov al,0

mov dx,MCR[si]

out dx,al

jmp $+2

; скидаємо регістр стану лінії

mov dx,LSR[si]

in al,dx

jmp $+2

; скидаємо регістр даних

mov dx,DATREG[si]

in al,dx

jmp $+2

; скидаємо регістр стану модему

mov dx,MSR[si]

in al,dx

; визначаємо дільник частоти тактового генератора

mov ax,50

mul DIV50

div baud_rate[si]

mov bx,ax

; переключаємо регістир даних і регістр керування перериваннями

; для введення дільника частоти тактового генератора

mov dx,LCR[si]

mov al,80H

out dx,al

jmp $+2

; уводимо молодший байт дільника частоти тактового генератора

mov dx,WORD PTR DLL[si]

mov al,bl

out dx,al

jmp $+2

; уводимо старший байт дільника частоти тактового генератора

mov dx,WORD PTR DLH[si]

mov al,bh

out dx,al

jmp $+2

; визначаємо парність і кількість стоп-бітів

mov al,03H

cmp parity[si],'O'

jne next1

mov al,0ah

jmp short next3

next1:

cmp parity[si],'E'

jne next2

mov al,1ah

jmp short next3

next2:

cmp parity[si],'M'

jne next3

mov al,2ah

next3:

test stop_bits[si],2

jz stop1

or al,4

stop1:

mov dx,LCR[si]

out dx,al

; дозволяємо переривання для 8259 і 8250

; установлюємо регістр маски переривань щоб

; дозволити переривання від асинхронного порту

in al,IMR

and al,d_irq[si]

out IMR,al

; дозволяємо генерацію переривань при готовності прийнятих

; даних, по стані "BREAK" і помилково

mov dx,IER[si]

mov al,0Dh

out dx,al

jmp $+2

; установлюємо DTR, RTS, OUT2

mov dx,MCR[si]

mov al,0bh

out dx,al

exit_open:

sti

pop si

mov sp,bp

pop bp

ret

_open_com ENDP

; забороняємо переривання від асинхронного порту

_close_com PROC FAR

push bp

mov bp,sp

push si

mov si,CURRENT_AREA

test installed[si],1

jz exit_close

; забороняємо переривання UART 8250

mov dx,IER[si]

mov al,0

out dx,al

; маскуємо переривання від UART

mov dx,IMR

in al,dx

or al,e_irq[si]

jmp $+2

out dx,al

exit_close:

pop si

mov sp,bp

pop bp

ret

_close_com ENDP

;процедура повертає 1 якщо з МТМ надійшов дзвінок

_com_ring proc far

push bp

mov bp,sp

push si

mov si,CURRENT_AREA

test installed[si],1

jz exit_com_ring

xor ax,ax

mov al,BYTE PTR RING[si]

nop

mov RING[si],0

nop;

exit_com_ring:

pop si

mov sp,bp

pop bp

ret

_com_ring endp

; ДОПОМІЖНІ ФУНЦІЇ

; знімаємо сигнал DTR

_dtr_off PROC FAR

push bp

mov bp,sp

push si

pushf

push ax

push dx

push si

mov si,CURRENT_AREA

test installed[si],1

jz exit_dtr_off

; установлюємо регістр керування модемом,

; скидаємо сигнали DTR і RTS

mov dx,MCR[si]

mov al,08H

out dx,al

exit_dtr_off:

pop si

pop dx

pop ax

popf

pop si

mov sp,bp

pop bp

ret

_dtr_off ENDP

; установлюємо сигнал DTR

_dtr_on PROC FAR

push bp

mov bp,sp

push si

pushf

push ax

push dx

push si

mov si,CURRENT_AREA

test installed[si],1

jz exit_dtr_on

; установлюємо регістр керування модемом,

; установлюємо сигнали DTR, RTS, OUT2

mov dx,MCR[si]

mov al,0bh

out dx,al

exit_dtr_on:

pop si

pop dx

pop ax

popf

pop si

mov sp,bp

pop bp

ret

_dtr_on ENDP

;

; повертаємо в регістрі ax число байтів у регістрі приймача,

; а в регістрі dx загальний розмір буфера приймача

_r_count PROC FAR

push bp

mov bp,sp

push si

pushf

push si

mov si,CURRENT_AREA

mov ax,0

mov dx,R_SIZE

test installed[si],1

jz exit_r_count

; записуємо в регістр ax число символів у буфері приймача

mov ax,size_r_data[si]

exit_r_count:

pop si

popf

pop si

mov sp,bp

pop bp

ret

_r_count ENDP

; одержуємо черговий символ з буфера приймача,

; отриманий символ віддаляється з буфера

_receive_com PROC FAR

push bp

mov bp,sp

push si

pushf

push bx

push si

mov si,CURRENT_AREA

mov ax,-1

test installed[si],1

jz exit_receive_com

; повертаємося якщо буфер приймача порожній

cmp size_r_data[si],0

je exit_receive_com

mov ah,0

mov bx,start_r_data[si]

mov al,reciave_buf[si][bx]

cmp parity[si],'N'

je no_parity

; якщо виробляється перевірка на парність, то маскуємо старший біт

and al,7FH

no_parity:

inc bx

cmp bx,R_SIZE

jb rec_ptr_no_max

mov bx,0

rec_ptr_no_max:

mov start_r_data[si],bx

dec size_r_data[si]

exit_receive_com:

pop si

pop bx

popf

pop si

mov sp,bp

pop bp

ret

_receive_com ENDP

; функція повертає в регістрі ax число вільних байт у

; буфері передавача, а в регістрі dx загальний розмір буфера передавача

_s_count PROC FAR

push bp

mov bp,sp

push si

pushf

push si

mov si,CURRENT_AREA

mov ax,0

mov dx,S_SIZE

test installed[si],1

jz exit_s_count

mov ax,S_SIZE

sub ax,size_s_data[si]

exit_s_count:

pop si

popf

pop si

mov sp,bp

pop bp

ret

_s_count ENDP

; помістити символ у буфер передавача

; [bp+6] - символ

_send_com PROC FAR

push bp

mov bp,sp

push si

mov al,[bp+6]

pushf

push ax

push bx

push dx

push si

mov si,CURRENT_AREA

test installed[si],1

jz exit_send_com

cmp size_s_data[si],S_SIZE

jl no_s_EOVFLOW

; відбулося переповнення буфера передавача

inc WORD PTR EOVFLOW[si]

jmp short exit_send_com

no_s_EOVFLOW:

mov bx,end_s_data[si]

mov send_buf[si][bx],al

inc bx

cmp bx,S_SIZE

jl no_send_ptr_max

mov bx,0

no_send_ptr_max:

mov end_s_data[si],bx

inc size_s_data[si]

; зчитуємо регістр керування перериваннями

mov dx,IER[si]

in al,dx

; завершуємо функцію якщо дозволені переривання після передачі байта

test al,2

jnz exit_send_com

; дозволяємо переривання після передачі байта, після прииема байта,

; при виявленні стану "BREAK" і при виникненні помилки

mov al,7

out dx,al

exit_send_com:

pop si

pop dx

pop bx

pop ax

popf

pop si

mov sp,bp

pop bp

ret

_send_com ENDP

; передаємо вилученому модему сигнал "BREAK"

_break_com PROC FAR

push bp

mov bp,sp

push si

pushf

push ax

push cx

push dx

mov si,CURRENT_AREA

test installed[si],1

jz exit_break_com

; передаємо сигнал "BREAK"

mov dx,LCR[si]

in al,dx

jmp $+2

or al,40h

out dx,al

mov cx,0C000h

do_BREAK:

loop do_BREAK

and al,0BFh

out dx,al

exit_break_com:

pop dx

pop cx

pop ax

popf

pop si

mov sp,bp

pop bp

ret

_break_com ENDP

; повертаємо в dx:ax покажчик на лічильники помилок

_com_errors PROC FAR

push bp

mov bp,sp

mov ax,OFFSET DGROUP:CURRENT_AREA

add ax,error_block

mov dx,ds

mov sp,bp

pop bp

ret

_com_errors ENDP

; заповнюємо лічильники помилок

set_err PROC NEAR

test al,2

jz test1

inc WORD PTR EOVRUN[si]

test1:

test al,4

jz test2

inc WORD PTR EPARITY[si]

test2:

test al,8

jz test3

inc WORD PTR EFRAME[si]

test3:

test al,16

jz exit_set_err

inc WORD PTR EBREAK[si]

exit_set_err:

ret

set_err ENDP

; протокол модему для передачі даних

modem_protocol PROC NEAR

cmp device_conn[si],'M'

jne no_modem

; установлюємо сигнали DTR, RTS і OUT2

mov dx,MCR[si]

mov al,00001011B

out dx,al

jmp $+2

; очікуємо поки модем відповість про готовність сигналом DSR

mov cx,1000

mov dx,MSR[si]

wait_dsr:

in al,dx

test al,20H

jnz test_cts

loop wait_dsr

; модем не відповів сигналом DSR

inc WORD PTR EDSR[si]

jmp short no_modem

test_cts:

; очікуємо поки модем відповість про готовність сигналом CTS

mov cx,1000

wait_cts:

in al,dx

test al,10H

jnz test_lcr

loop wait_cts

; модем не відповів сигналом CTS

inc WORD PTR ECTS[si]

test_lcr:

no_modem:

; чи перевіряємо порожній регситр збереження передавача

mov dx,LSR[si]

in al,dx

test al,20H

jnz s_reg_empty

; помилка при передачі

inc WORD PTR EXMIT[si]

s_reg_empty:

ret

modem_protocol ENDP

; оброблювач переривань від COM1

int_hndlr1 PROC FAR

push si

mov si,OFFSET DGROUP:AREA1

jmp short handle_int

; оброблювач переривань від COM2

int_hndlr2 PROC FAR

push si

mov si,OFFSET DGROUP:AREA2

jmp short handle_int

; оброблювач переривань від COM3

int_hndlr3 PROC FAR

push si; SAVE si

mov si,OFFSET DGROUP:AREA3

jmp short handle_int

;

; оброблювач переривань від COM4

int_hndlr4 PROC FAR

push si; SAVE si

mov si,OFFSET DGROUP:AREA4

;

; оброблювач переривань

handle_int:

push ax

push bx

push cx

push dx

push bp

push di

push ds

push es

mov ax,DGROUP

mov ds,ax

next_pr:

; передаємо контролеру переривань команду кінця обробки

; переривання

mov dx,OCR

mov al,eoi[si]

out dx,al

next_inter:

; зчитуємо значення регістра ідентифікації переривання

mov dx,IIR[si]

in al,dx

; визначаємо причину переривання

; виявлено сотояние "BREAK" чи відбулася помилка

cmp al,0

je MSTAT_int

; дані прийняті і доступні для читання

cmp al,4

je RX_int

; буфер передавача порожній

cmp al,2

je TX_int

; змінився стан ліній CTS, RI, DCD, DSR

cmp al,6

je LSTAT_int

; завершуємо обробку переривань

jmp FAR PTR exit_handler

LSTAT_int:

; зчитуємо регістр стану лінії і викликаємо функцію

; set_err, що визначить причину переривання

mov dx,LSR[si]

in al,dx

mov al,0FFh

mov RING[si],al

call set_err

jmp next_inter

MSTAT_int:

; зчитуємо регістр стану модему

mov dx,MSR[si]

in al,dx

mov al,0FFh

mov RING[si],al

jmp next_inter

TX_int:

; дивимося їсти чи дані для передачі модему

cmp size_s_data[si],0

jg have_data_for_send

; якщо буфер передавача порожній переустановлюємо регістр

; керування перериваннями

mov dx,IER[si]

mov al,0Dh

out dx,al

jmp next_inter

have_data_for_send:

; передаємо символ модему відповідно до стану

; ліній RS-232-З

call modem_protocol

; передаємо черговий символ з буфера передавача

mov bx,start_s_data[si]

mov al,send_buf[si][bx]

mov dx,DATREG[si]

out dx,al

inc bx

cmp bx,S_SIZE

jb ptr_no_max

mov bx,0

ptr_no_max:

mov start_s_data[si],bx

dec size_s_data[si]

jmp next_inter

; дані прийняті і доступні для читання

RX_int:

; зчитуємо прийнятий байти із регістра даних UART

mov dx,DATREG[si]

in al,dx

cmp size_r_data[si],R_SIZE

jl no_r_EOVFLOW

; буфер приймача переповнений, збільшуємо відповідний

; лічильник помилок

inc WORD PTR EOVFLOW[si]

jmp next_inter

no_r_EOVFLOW:

mov bx,end_r_data[si]

mov reciave_buf[si][bx],al

inc size_r_data[si]

inc bx

cmp bx,R_SIZE

jb no_max_r_ptr

mov bx,0

no_max_r_ptr:

mov end_r_data[si],bx

jmp next_inter

exit_handler:

mov al,20h

out 20h,al

pop es

pop ds

pop di

pop bp

pop dx

pop cx

pop bx

pop ax

pop si

iret

int_hndlr4 ENDP

int_hndlr3 ENDP

int_hndlr2 ENDP

int_hndlr1 ENDP

COM_TEXT ENDS

END