Code: Select all
; PIC16C73
LineL equ 0x20 ; Младший байт выходов (младшие 8 бит счетчика)
LineH equ 0x21 ; Старший байт выходов (старший бит счетчика + VBlank+VSync)
Mode equ 0x22 ; Режим
Temp equ 0x23 ; Времянка
;
#include p16c73.inc ; Выбор чипа
org 0x000 ; Начало кода
goto Start ; Переход на начало
org 0x004 ; Вектор прерывания
; Прерывание
bcf INTCON,INTF ; Подтвердим прерывание
; Первым делом выведем то, что есть (минимальные потери на реакцию)
movf LineL,0 ; Младшую часть в W
movwf PORTC ; Младшую часть на порт С
movf LineH,0 ; Старшую часть в W
movwf PORTA ; А старшую - на порт А
; Теперь смотрим режим
movf Mode,0 ; Считаем Режим в W
movwf Temp ; Сохраним значение счетчика
incf Temp,1 ; Temp +1
decfsz Temp,1 ; Temp -1
goto Check0 ; Не 0 - пропускаем
goto LowLoop ; У нас LowLoop
Check0
decfsz Temp,1 ; Temp -1
goto Check1 ; Не 0 - пропускаем
goto HighLoop ; У нас HighLoop
Check1
decfsz Temp,1 ; Temp -1
goto Check2 ; Не 0 - пропускаем
goto ExtraLoop ; У нас ExtraLoop
Check2
movlw 0x0C ; Начальное состояние
movwf LineH ; Выставим
clrf LineL ;
clrf Mode ; Режим =0
retfie ; Возврат из прерывания
; Выполняется первый круг (первые 256 строк растра)
LowLoop
incfsz LineL,1 ; Считаем до переполнения
retfie ; Возврат из прерывания
incf LineH,1 ; Следующий адрес
incf Mode,1 ; Следующий режим
retfie ; Возврат из прерывания
; Выполняется второй круг (вторые 256 строк растра)
HighLoop
incfsz LineL,1 ; Считаем до переполнения
retfie ; Возврат из прерывания
incf Mode,1 ; Следующий режим
movlw 0x06 ; Активен VBlank
movwf LineH ; Выставим
retfie ; Возврат из прерывания
; Расширенные круг
ExtraLoop
incf LineL,1 ; Считаем дальше
movf LineL,0 ; Считаем LineL в W
movwf Temp ; Сохраним значение счетчика
movlw 0x2B ; W=0x2D
subwf Temp,1 ; Вычтем константу синхроимпульса
decfsz Temp,1 ; Уже синхроимпульс?
goto ExtraCont ; Нет - идем дальше
movlw 0x12 ; Выставим синхроимпульс
movwf LineH ; Выставим
retfie ; Возврат из прерывания
ExtraCont
movf LineL,0 ; Считаем LineL в W
movwf Temp ; Сохраним значение счетчика
movlw 0x2F ; W=0x30
subwf Temp,1 ; Вычтем константу синхроимпульса
decfsz Temp,1 ; Уже кончился синхроимпульс?
goto ExtraExit ; Нет - идем дальше
movlw 0x06 ; Выставим синхроимпульс
movwf LineH ; Выставим
retfie ; Возврат из прерывания
ExtraExit
movf LineL,0 ; Считаем LineL в W
movwf Temp ; Сохраним значение счетчика
movlw 0x73 ; W=0x73
subwf Temp,1 ; Вычтем константу выхода
decfsz Temp,1 ; Уже выход?
retfie ; Возврат из прерывания
movlw 0x0C ; Вернем все на место
movwf LineH ; Выставим
clrf LineL ; Очистим счетчик
clrf Mode ; Обнуляем режим
retfie ; Возврат из прерывания
; Главный старт
Start
bcf STATUS,IRP ; Выберем банк 0
bcf STATUS,RP1 ; Выберем банк 0
bsf STATUS,RP0 ; Выберем банк 1
clrf TRISA ; Порт А на вывод
clrf TRISC ; Порт С на вывод
movlw 0xFF ; Значение 0xFF в W
movwf TRISB ; Порт В на ввод
movlw 0x80 ; Значение 0x80 в W
movwf OPTION_REG ; Выставим опции
bcf STATUS,RP0 ; Выберем банк 0
clrf PORTA ; Очистим порт А
clrf PORTC ; Очистим порт С
clrf W ; Очистим W
movwf T1CON ; Отключим TIMER1
movlw 0x0C ; Начальное состояние
movwf LineH ; Выставим
clrf LineL ;
clrf Mode ; Режим =0
bsf INTCON,INTE ; Установим прерывание
bsf INTCON,GIE ; Включим их
Loop
sleep ; Спим
goto Loop ; Крутим
END ; Канец!
;
Но не это главное. Когда я изучал датащит на PIC16C7x я нашел, что у PIC16C74 есть т.н. PSP - Parallel Slave Port. Он и есть то, что было у контроллера клавы - одна ячейка памяти на шине i8080/Z80. У него даже прерывание есть. Но нету адресов, т.е. их надо защелкивать сразу. Если он успеет на чтении, при прерывании обработать адреса (дополнительные 2 линии на портах) и выдать нужный байт на свой PSP, то на нем можно будет замутить ответную часть для эмулятора клавиатуры с ВВ55м чипом. Например, обработка PS2 и собственно эмуляция ВВ55 можно задать на какой-нить проц поумнее, например AVR или MCS51, который по быстрому аурту будет гадить в пик а тот уже работать с шиной. Хотя, я даже не знаю, может и сам пик справится? Они такие примитивные, блин, даже после MCS48 и 6502...