Hi,
I am programming some kind of "alarm clock" to my OS (real mode). I've hooked a simple handler to INT 4Ah, enabled it through CMOS RTC status register B and activated through INT 1Ah,AH=06h. But the alarm interrupt doesn't execute at the specified time...
I use'd functions to convert BCD to byte and Byte to BCD to manage the time setting - they work flawlessly. And, when I try to execute INT 4Ah direct from OS, it will work flawlessly too.
Can you help me find the problem?
Any answers would be appreciated!
Thanx,
inflater
Alarm Interrupt
Alarm Interrupt
My web site: http://inflater.wz.cz (Slovak)
Derrick operating system: http://derrick.xf.cz (Slovak and English )
Derrick operating system: http://derrick.xf.cz (Slovak and English )
Well, here is the code. It is a bit complicated though.
Functions:
And here is the code that will enable the alarm. The code is shortened: Skipped the functions that will convert BCD to byte etc.:
BTW., the function "Alarm status" is not working on my machine.
inflater
Functions:
Code: Select all
function Byte2BCD(X : byte) : byte ;
begin
Byte2BCD := (X div 10)*16 + (X mod 10)
end;
function BCD2Byte(X : byte) : byte ;
begin
BCD2Byte := (X div 16)*10 + (X mod 16)
end;
procedure AlarmHandler(Flags, CS, IP, AX, BX, CX, DX,SI, DI,
DS, ES, BP: Word); interrupt;
var i,j: integer;
Begin
ClearScreen;
Cursor(0);
GotoXY(30,12);
WriteStr('Alarm - wait...');
for j := 0 to 1 do begin
for i := 600 to 1200 do begin
Sound(i);
Delay(2);
NoSound;
end;
for i := 1200 downto 600 do begin
Sound(i);
Delay(2);
NoSound;
end;
end;
for i := 600 downto 0 do begin
Sound(i);
Delay(2);
NoSound;
end;
ClearScreen;
GotoXY(30,12);
WriteStr('Press ENTER...');
ReadKey;
DeactivateAlarm;
Cursor(1);
end;
procedure ActivateAlarm;
begin
asm
mov al,0Bh
out 70h,al
jmp @@delay
@@delay:
xor ax,ax
or al,5
out 71h,al
end;
GetIntVec($4A,@oldalarm);
SetIntVec($4A,ADDR(AlarmHandler));
end;
procedure DeactivateAlarm;
begin
asm
mov al,0Bh
out 70h,al
jmp @@delay
@@delay:
xor ax,ax
and al,not 20
out 71h,al
end;
SetIntVec($4A,ADDR(@oldalarm));
asm
mov ah,07h
int 1Ah
end;
end;
function SetAlarm(HourBCD,MinuteBCD,SecondBCD: Byte): Integer;
var cflag: byte;
begin
asm
mov ah,06h
mov HourBCD,ch
mov MinuteBCD,cl
mov SecondBCD,dh
int 1Ah
jc @@chyba
jmp @@koniec
@@chyba:
mov cflag,1
@@koniec:
end;
SetAlarm := cflag;
end;
Code: Select all
var alstatus: byte;
code1: integer;
alhodb, alminb, alsekb: byte; {ALREADY converted BCD time}
alhod,almin,alsek: byte; {variables to convert}
begin
WriteStr('1: Set alarm' + CRLF + '2: Disable alarm' + CRLF + '3: DEBUG: Call INT 4Ah' + CRLF + '4: Back to OS');
WriteStr(CRLF + CRLF + 'Alarm status: ');
asm
mov ah,09h
int 1ah
push dx
@@again:
pop dx
cmp dl,00
je @@CMOSalNO
cmp dl,01
je @@CMOSalOFF
cmp dl,02
je @@CMOSalSET
jmp @@nezistene
@@cmosalno:
mov alstatus,0
jmp @@koniec
@@CMOSalOFF:
mov alstatus,1
jmp @@koniec
@@CMOSalset:
mov alstatus,2
jmp @@koniec
@@nezistene:
mov alstatus,3
@@koniec:
end;
if alstatus = 0 then WriteStr('Alarm disabled by CMOS.');
if alstatus = 1 then WriteStr('Alarm enabled by CMOS, but not set.');
if alstatus = 2 then WriteStr('Alarm is enabled and set.');
if alstatus = 3 then WriteStr('Unknown');
WriteStr(CRLF + CRLF + 'Command:');
ReadStr;
if rdstr = '1' then begin {just think: it is a command buffer}
WriteStr(CRLF + CRLF + 'Alarm hour: ');
ReadStr;
Val(rdstr,alhod,Code1);
if Code1 <> 0 then begin
WriteStr(CRLF + 'Unknown parameter! Press ENTER...');
ReadKey;
goto alarmcom;
end;
Alhodb := Byte2BCD(alhod);
WriteStr(CRLF + 'Alarm minute: ');
ReadStr;
Val(rdstr,almin,Code1);
if Code1 <> 0 then begin
WriteStr(CRLF + 'Unknown parameter! Press ENTER...');
ReadKey;
goto alarmcom;
end;
Alminb := Byte2BCD(almin);
WriteStr(CRLF + 'Alarm second: ');
ReadStr;
Val(rdstr,alsek,Code1);
if Code1 <> 0 then begin
WriteStr(CRLF + 'Unknown parameter! Press ENTER...');
ReadKey;
goto alarmcom;
end;
Alsekb := Byte2BCD(alsek);
if SetAlarm(alhodb,alminb,alsekb) = 1 then begin
WriteStr(CRLF + CRLF + 'Error: Alarm is already set, or there was' + CRLF + 'error when trying to set alarm.' +
CRLF + CRLF + 'Press ENTER...');
DeactivateAlarm;
Readkey;
goto alarmcom;
end;
ActivateAlarm;
WriteStr(CRLF + CRLF + 'Alarm set!' + CRLF + 'Press ENTER...');
ReadKey;
goto alarmcom;
end;
if rdstr = '2' then begin
DeactivateAlarm;
WriteStr(CRLF + CRLF + 'Alarm deactivated.'+ CRLF + 'Press ENTER...');
ReadKey;
goto alarmcom;
end;
if rdstr = '3' then begin
asm int 4Ah end; goto alarmcom; end;
if rdstr = '4' then begin
ClearScreen;
goto ShellLoop;
end;
inflater
My web site: http://inflater.wz.cz (Slovak)
Derrick operating system: http://derrick.xf.cz (Slovak and English )
Derrick operating system: http://derrick.xf.cz (Slovak and English )
I tried to change that order of parameters and registers:
mov ch,HourBCD
etc., but it wont work either...
Can INT 4Ah trigger when BIOS is waiting for keypress (ReadLn) ?
If not, maybe that is the problem. But i should somehow "disable" the command line? Weird...
inflater
mov ch,HourBCD
etc., but it wont work either...
Can INT 4Ah trigger when BIOS is waiting for keypress (ReadLn) ?
If not, maybe that is the problem. But i should somehow "disable" the command line? Weird...
inflater
My web site: http://inflater.wz.cz (Slovak)
Derrick operating system: http://derrick.xf.cz (Slovak and English )
Derrick operating system: http://derrick.xf.cz (Slovak and English )
Have tryed something like this:inflater wrote:I tried to change that order of parameters and registers:
mov ch,HourBCD
etc., but it wont work either...
Code: Select all
mov ch,byte ptr [HourBCD]
Not working either...
inflater
inflater
My web site: http://inflater.wz.cz (Slovak)
Derrick operating system: http://derrick.xf.cz (Slovak and English )
Derrick operating system: http://derrick.xf.cz (Slovak and English )