Alarm Interrupt

Question about which tools to use, bugs, the best way to implement a function, etc should go here. Don't forget to see if your question is answered in the wiki first! When in doubt post here.
Post Reply
User avatar
inflater
Member
Member
Posts: 1309
Joined: Thu Sep 28, 2006 10:32 am
Location: Slovakia
Contact:

Alarm Interrupt

Post by inflater »

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
My web site: http://inflater.wz.cz (Slovak)
Derrick operating system: http://derrick.xf.cz (Slovak and English :P)
User avatar
Dex
Member
Member
Posts: 1444
Joined: Fri Jan 27, 2006 12:00 am
Contact:

Post by Dex »

If we can not see the code, we can not workout the problem ;), but it sounds like a setting up problem.
User avatar
inflater
Member
Member
Posts: 1309
Joined: Thu Sep 28, 2006 10:32 am
Location: Slovakia
Contact:

Post by inflater »

Well, here is the code. It is a bit complicated though.

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;
And here is the code that will enable the alarm. The code is shortened: Skipped the functions that will convert BCD to byte etc.:

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;
BTW., the function "Alarm status" is not working on my machine.

inflater
My web site: http://inflater.wz.cz (Slovak)
Derrick operating system: http://derrick.xf.cz (Slovak and English :P)
User avatar
Dex
Member
Member
Posts: 1444
Joined: Fri Jan 27, 2006 12:00 am
Contact:

Post by Dex »

To me it looks like you may have "function SetAlarm" the vars and the regs the wrong way round ?.
User avatar
inflater
Member
Member
Posts: 1309
Joined: Thu Sep 28, 2006 10:32 am
Location: Slovakia
Contact:

Post by inflater »

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
My web site: http://inflater.wz.cz (Slovak)
Derrick operating system: http://derrick.xf.cz (Slovak and English :P)
User avatar
Dex
Member
Member
Posts: 1444
Joined: Fri Jan 27, 2006 12:00 am
Contact:

Post by Dex »

inflater wrote:I tried to change that order of parameters and registers:

mov ch,HourBCD

etc., but it wont work either...
Have tryed something like this:

Code: Select all

 mov  ch,byte ptr [HourBCD]
I am not too sure about the way turbo pascal lay its inline code out.
User avatar
inflater
Member
Member
Posts: 1309
Joined: Thu Sep 28, 2006 10:32 am
Location: Slovakia
Contact:

Post by inflater »

Not working either... :(

inflater
My web site: http://inflater.wz.cz (Slovak)
Derrick operating system: http://derrick.xf.cz (Slovak and English :P)
Post Reply