I read the code example in page 621 of "The Indispensable PC Hardware Book", Fourth Edition, by Hans Peter Messmer. The code I produced is almost exactly the same, but mine is more reusable and packed in a clean routine.
I have made a manual test and it looks like I can replay the default speaker beep sound if I feed it back the countdown or counter MSB:LSB value from channel 1 that I get with this function. It's supposed that the speaker PIT channel should be set to work in binary mode, not BCD, and one should ensure that it has previously been programmed. But if we know that it's present then it should be already preconfigured by the BIOS.
So it seems that the following routine is capable of saving the current countdown value of the speaker:
Code: Select all
;Return value:
; AH:AL -- MSB:LSB countdown value
;;
PC_Speaker__Save_Current_Countdown_Value:
pushf
push widebx
;Read the frequency of counter 1
;(indicated in bits 7-6),
;supposedly the speaker PIT counter:
;;
mov al,01000000b ;Specify channel 1
out 0x43,al
in al,0x42 ;Read LSB of countdown and put in BL
mov bl,al
in al,0x42 ;Read MSB of countdown and put in BH
mov bh,al
;Put MSB:LSB in AX:
;;
xchg bx,ax
pop widebx
popf
retwide
It would need extensive testing to ensure that this is actually the right code the PC hardware expects, but in the test I made, it worked.
Here is the full test program I made for my kernel. It allowed me to manually test if it was channel 2 that I had to read, channel 1 or channel 0, but it seems to be channel 1 for the speaker:
Code: Select all
;v2017-06-27
;
;Beep for a moment with the PC speaker.
;;
;If our program base address is 0, it will tell the kernel
;to relocate it elsewhere. If it's not 0, then the kernel
;will load the program to that physical address:
;;
APPBASE equ 1048576*4
bits 32
org APPBASE
_x86_Portable__PLATFORMBITS_ equ 32
%define _x86_Portable__PLATFORMBITS_ 32
%include "00000000__x86_Portable.asm"
;Our kernel must read this address, jump
;to it and then skip it:
;;
IntendedBaseAddress dq APPBASE
NumberOfFieldsBelow dq 8
CommandLinePtr dq 0
CommandLineLength dq 0
CommandLineParamsPtr dq 0
KernelFnExportsTable dq 0
KernelVrExportsTable dq 0
AppFnImportsTable dq myImportsFunctionsTable
AppVrImportsTable dq 0
RawExeEntryPoint dq _ENTRY
SimpleCodeRelocationsTable:
SimpleCodeRelocationsCount ww (SimpleCodeRelocationsTable_SZ/WIDEWORD_SZ)-1
;ww MainProgram__coderelocation_0000_clearScreen
SimpleCodeRelocationsTable__END:
SimpleCodeRelocationsTable_SZ equ (SimpleCodeRelocationsTable__END-SimpleCodeRelocationsTable)
SimpleDataRelocationsTable:
SimpleDataRelocationsCount ww (SimpleDataRelocationsTable_SZ/WIDEWORD_SZ)-1
;ww
SimpleDataRelocationsTable__END:
SimpleDataRelocationsTable_SZ equ (SimpleDataRelocationsTable__END-SimpleDataRelocationsTable)
%include "00000000__x86_Portable_2.asm"
%include "include/external_exported_variables.inc"
%include "include/external_exported_functions.inc"
;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
align 16
db "START Debug Strings"
align 16
_ENTRY:
;Clean the screen:
;;
;MainProgram__coderelocation_0000_clearScreen equ $
call wideword[clrscr]
call beep
;Return control to the kernel:
;;
ret
beep:
; pusha
; pushf
;Read the frequency of counter 2 (bits 7-6),
;supposedly the PIT counter:
;;
mov al,01000000b
out 0x43,al
in al,0x42
mov bl,al
in al,0x42
mov bh,al
;Write the sound frequency:
;;
mov al,0xB6 ;Command -- Write MSB:LSB countdown value
out 0x43,al
;mov al,00h ;Port byte LSB
mov al,bl ;Port byte LSB
out 0x42,al
;mov al,128 ;Port byte MSB
mov al,bh ;Port byte MSB
out 0x42,al ;;;;;MSB:LSB
;Configure the state of the status port:
;;
in al,61h ;Read the state of the port
or al, 00000011b ;Set to 1 bits 0 and 1 to enable the speaker
out 61h,al ;Write the new value
ret
;A short delay:
;;
mov cx,0FFFFh
l1:
loop l1
;Disable the port:
;;
in al,61h ;Read the state of the port
and al,11111100b ;Clear to 0 bits 0 and 1, to disable the speaker
out 61h,al
popf
popa
ret
align 16
db "Debug Strings END"
align 16
myImportsFunctionsTable:
ImportsCount ww 1
clrscr ww clrscr@KernelCore
align 16
db 0,0,0,0,0,0,0,0,0,0,0,0,"EOF",0
;EOF