OSDev.org

The Place to Start for Operating System Developers
It is currently Fri Apr 19, 2024 5:39 pm

All times are UTC - 6 hours




Post new topic Reply to topic  [ 5 posts ] 
Author Message
 Post subject: How to Read the Speaker Countdown Value to Store It?
PostPosted: Tue Jun 27, 2017 10:59 pm 
Offline
Member
Member
User avatar

Joined: Tue Mar 06, 2007 11:17 am
Posts: 1225
How can I read the current value of the PC speaker? I want to be able to reuse the default sound frequency.

Is there some command for it?

Where can I find a list of commands for the speaker device?

I only seem to know about the command to write the countdown value, something like this, but I specifically want to retrieve and save the current MSB:LSB countdown values for the speaker by reading ports or using some speaker command:
Code:
beep:
  pusha
  pushf

;Write the sound frequency:
;;
mov al,0xB6  ;Command -- Write MSB:LSB countdown value
out 0x43,al
mov al,00h    ;Port byte LSB
out 0x42,al
mov al,128      ;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


;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


_________________
Live PC 1: Image Live PC 2: Image

YouTube:
http://youtube.com/@AltComp126/streams
http://youtube.com/@proyectos/streams

http://master.dl.sourceforge.net/projec ... 7z?viasf=1


Last edited by ~ on Tue Jun 27, 2017 11:06 pm, edited 1 time in total.

Top
 Profile  
 
 Post subject: Re: How to read the Speaker Countdown Value?
PostPosted: Tue Jun 27, 2017 11:06 pm 
Offline
Member
Member
User avatar

Joined: Sat Dec 27, 2014 9:11 am
Posts: 901
Location: Maadi, Cairo, Egypt
I'm not sure about this as I myself have never tried playing with it, but you might want to read the Wiki entry on the PIT, specifically sections Counter Latch Command and Reading The Current Count.

_________________
You know your OS is advanced when you stop using the Intel programming guide as a reference.


Top
 Profile  
 
 Post subject: Re: How to Read the Speaker Countdown Value to Store It?
PostPosted: Wed Jun 28, 2017 12:03 am 
Offline
Member
Member
User avatar

Joined: Tue Mar 06, 2007 11:17 am
Posts: 1225
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:
;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:
;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


_________________
Live PC 1: Image Live PC 2: Image

YouTube:
http://youtube.com/@AltComp126/streams
http://youtube.com/@proyectos/streams

http://master.dl.sourceforge.net/projec ... 7z?viasf=1


Top
 Profile  
 
 Post subject: Re: How to Read the Speaker Countdown Value to Store It?
PostPosted: Thu Jun 29, 2017 10:35 am 
Offline
Member
Member
User avatar

Joined: Tue Mar 06, 2007 11:17 am
Posts: 1225
I have other speaker-controlling functions here. Please tell me if you can see some problem or weakness.

The only question I have is, can the speaker really be set to BCD countdown mode or the different generator modes of the regular PIT? If so, maybe some other functions will need to be written to ensure that it's working in binary countdown mode at least usually. I seem to remember that the speaker could be programmed in different modes for more automatic sound reproduction, so these functions wouldn't be enough.

Code:
;Inputs:
;            AH:AL -- MSB:LSB countdown value
;;
PC_Speaker__Set_Sound_By_Countdown:
pushf
push wideax

;Write the countdown value:
;
;                 1193180
;    COUNTDOWN = ---------
;                FREQUENCY
;
;
;                 1193180
;    FREQUENCY = ---------
;                COUNTDOWN
;
;;
  push wideax
  mov al,0xB6  ;Command -- Write MSB:LSB countdown value
  out 0x43,al  ;Write PIT Mode/Command register (W)
  pop wideax



out 0x42,al   ;Write LSB to PIT channel 2 data port (R/W)

shr wideax,8  ;Get MSB in AL
out 0x42,al   ;Write MSB to PIT channel 2 data port (R/W)



pop wideax
popf
retwide




Code:
;Inputs:
;            EAX -- Frequency value
;            ECX -- 1 round up
;;
PC_Speaker__Set_Sound_By_Frequency:
pushf
push wideax
push widebx
push widedx

;Calculate the countdown for the frequency value:
;
;              1193180
; COUNTDOWN = ---------
;             FREQUENCY
;
;;
  xor  edx,edx      ;Form EDX:EAX with EDX to 0, EDX:EAX==1193180
  xchg eax,ebx      ;Put EAX argument, in EBX, EBX==FREQUENCY
  mov  eax,1193180  ;Use default PIT frequency, EDX:EAX==1193180
  div  ebx          ;  EDX:EAX / EBX -- EAX result, EDX remainder

  cmp ecx,1         ;See if we want to round up
  jne .noroundup    ;If not, skip adding 1
  cmp edx,0
  je  .noroundup    ;If remainder==0, don't round up
   inc eax          ;If so, add 1 to round up

  .noroundup:




;Write the countdown value:
;
;                 1193180
;    COUNTDOWN = ---------
;                FREQUENCY
;
;
;                 1193180
;    FREQUENCY = ---------
;                COUNTDOWN
;
;;
  push wideax
  mov al,0xB6  ;Command -- Write MSB:LSB countdown value
  out 0x43,al  ;Write PIT Mode/Command register (W)
  pop wideax



out 0x42,al   ;Write LSB to PIT channel 2 data port (R/W)

shr wideax,8  ;Get MSB in AL
out 0x42,al   ;Write MSB to PIT channel 2 data port (R/W)



pop widedx
pop widebx
pop wideax
popf
retwide






Code:
PC_Speaker__enable:
pushf
push wideax

;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
                   ;of the KBC Port B Control Register (system control port).
                   ;Bits:
                   ;    0 -- PIT channel 2 gate used to enable/disable the speaker.
                   ;    1 -- Speaker Data Enable.

  out 61h,al       ;Write the new value.



pop wideax
popf
retwide





Code:
PC_Speaker__disable:
pushf
push wideax

;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
                   ;of the KBC Port B Control Register (system control port).
                   ;Bits:
                   ;    0 -- PIT channel 2 gate used to enable/disable the speaker.
                   ;    1 -- Speaker Data Enable.

  out 61h,al       ;Write the new value.


pop wideax
popf
retwide


_________________
Live PC 1: Image Live PC 2: Image

YouTube:
http://youtube.com/@AltComp126/streams
http://youtube.com/@proyectos/streams

http://master.dl.sourceforge.net/projec ... 7z?viasf=1


Top
 Profile  
 
 Post subject: Re: How to Read the Speaker Countdown Value to Store It?
PostPosted: Thu Jun 29, 2017 12:59 pm 
Offline
Member
Member

Joined: Thu Aug 13, 2015 4:57 pm
Posts: 384
Did I misunderstand, or why would you ever want to use BCD (Binary Coded Decimal)?

AFAIK BCD's main use is for displaying to humans, you're driving a PIT, why would you use BCD?


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 5 posts ] 

All times are UTC - 6 hours


Who is online

Users browsing this forum: Bing [Bot] and 177 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group