Sie sind auf Seite 1von 4

;

;
;
;
;
;
;
;
;
;
;
;
;
;
;

This 8051 program enables two interrupts and then sits in a


loop waiting for these interrupts. Everytime it gets the
external interrupt #1 (EXT1) it reads a new left-channel
audio sample from the SFR (special function register) P0
and a new right-channel audio sample from P1 (you can read
from P0 and P1 in any order). As the 8051 continues to read
the audio samples it computes the largest sample (the "peak")
that it has seen for both channels. For this particular
implementation we have arbitrarily decided to hold the detected
left channel peak in data memory address 16 (which we label
with the symbol "LeftPeak" via an EQU statement) and the
right channel peak in dma 17 (labeled as "RightPeak").
Don't choose dma 8 & 9 for LeftPeak and RightPeak as this
conflicts with the default location for the subroutine return
address stack.

LeftPeak

EQU

16

RightPeak

EQU

17

; use data memory addr 16 to hold the


; left channel peak
; use dma 17 to hold the right peak

;
;
;
;
;
;
;
;
;

Each time the external interrupt #0 (EXT0) interrupt occurs


the 8051 outputs the detected left-channel peak reading to
port P2 and the detected right-channel peak reading to port P3.
YOU MUST write to P2 before P3 because it is the act of
writing to P3 that causes the most recent values written to
both P2 and P3 to be transferred to the LED bar graph display.
At this same time this program resets both peak detectors back
to 0 (hence the very next audio sample will always be crowned
the new "peak" sample, at least momentarily).

;
;
;
;
;
;
;
;
;
;

If the .WAV file being played contains 16 bit samples, only


the MSByte of each sample is made available to the 8051. And
if the .WAV file being played is a mono recording, an identical
sample will be available from both P0 and P1. This way the
same 8051 program can handle any (uncompressed) .WAV file. The
left and right sample are both signed bytes, meaning that they
have a range from -128 to +127. What we want to display on the
LED bar graph is the largest excursion from quiet, which is a
reading of 0. As an example, consider the following sequence of
left channel samples:

;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;

LeftSample
---------0
4
3
7
0
-5
-8

excursion from quiet


-------------------0
4
3
7
0
5
8

new LeftPeak
-----------0
4
4
7
7
7
8

We see that the "excursion from quiet" is just the absolute value
of the sample. Some microprocessors have an absolute value
operation built in but the 8051 does not. We can compute the
absolute value by negating the sample when we detect that the
sample is negative. To "negate" a signed number means to take
its "twos complement". The 8051 does not have an instruction
that computes the twos complement but the CPL instruction computes
the "ones complement". You get the ones complement by
complementing each individual bit. You get the twos complement

; from a ones complement by adding 1. We can accomplish these


; two steps using the following 8051 instructions:
;
CPL A
;
INC A
; Some examples of ones complements and twos complements are shown
; below (where I use the "B" suffix to indicate a binary number):
;
;
original number
ones complement
twos complement
;
-------------------------------------------;
-1 = 11111111B
00000000B = 0
00000001B = 1
;
-2 = 11111110B
00000001B = 1
00000010B = 2
;
-3 = 11111101B
00000010B = 2
00000011B = 3
;
...
;
-127 = 10000001B
01111110B = 126
01111111B = 127
;
-128 = 10000000B
01111111B = 127
10000000B = -128
;
;
;
;
;
;
;
;
;

Note that the two step sequence:


CPL A
INC A
correctly negates all negative numbers between -1 and -127.
It fails only on -128 but this is because it is impossible to
express +128 as a signed 8 bit number. In the Help pages that
I distribute with my 8051 simulator I discuss other alternatives,
but in this program as written I just ignore the possibility
of an audio reading of -128.

; We need two data memory locations to hold the left and right
; "excursions from quiet" so we arbitrarily choose the following
; data memory addresses:
LeftSample EQU
RightSample EQU

18
19

; excursion from quiet

ORG 0
LJMP Start
Ext0Int:

ORG 0x03
LJMP Ext0ISR

Tmr0Int:

ORG 0x0b
SJMP Tmr0Int

Ext1Int:

ORG 0x13
LJMP Ext1ISR

; we accept the EXT1 interrupt

Tmr1Int:

ORG 0x1b
SJMP Tmr1Int

; infinite loop

SerInt:

ORG 0x23
SJMP SerInt

; infinite loop

Start:

MOV IE, #0x85

; we accept the EXT0 interrupt


; we should never get here and if
; we do we enter an infinite loop

; 10000101B, MSBit is the global intr


; enable, we enable the 2 external
; interrupts

MOV LeftPeak,#0 ; zero out the left peak reading


MOV RightPeak,#0 ; zero out the right peak reading
Loop:

SJMP Loop

; wait for an interrupt

Ext1ISR:
; This interrupt signals that a new left and right audio sample are
; available.
MOV LeftSample,P0 ; read the new left channel sample from P0
MOV A,LeftSample
JNB ACC.7,ItsPositive ; test the MSBit
ItsNegative:
; so we need to negate the value
CPL A
; form the "ones complement"...
INC A
; ...and then add 1 to form "twos comp"
MOV LeftSample,A
ItsPositive:
; at this point LeftSample will hold the
; "excursion from quiet" which is an
; unsigned (i.e., positive) number.
MOV

A,LeftSample ;
;
CLR C
;
;
SUBB A,LeftPeak
;
;
;
JC
Ahead1
;
;

load ACC with left-channel


excursion from 0
necessary prior to SUBB since
there is no SUB instr
compare new reading to prior peak,
the SUBB instr populates the ACC
with the prior value in the ACC - P0
SUBB sets the carry/borrow flag C if a
borrow is needed and clears C otherwise

NewLeftPeak:
MOV

LeftPeak,LeftSample

; remember new left-channel peak

Ahead1:
MOV
MOV
JNB
RightIsNegative:
CPL
INC
MOV
RightIsPositive:

RightSample,P1 ; read the new right channel sample from P1


A,RightSample
ACC.7,RightIsPositive ; test the MSBit
; so we need to negate the value
A
; form the "ones complement"...
A
; ...and then add 1 to form "twos comp"
RightSample,A
; at this point RightSample will hold the
; "excursion from quiet" which is an
; unsigned (i.e., positive) number.

MOV

A,RightSample ; load ACC with left-channel excursion


; from 0
CLR C
; necessary prior to SUBB
SUBB A,RightPeak ; compare new reading to prior peak
JC
Ahead2
NewRightPeak:
MOV

RightPeak,RightSample ; remember new right-channel peak

RETI

; return from the interrupt

Ahead2:
Ext0ISR:
; This interrupt signals that it's time to update the LED bar graph
; and then to reset the detected left and right peak reading.
MOV P2,LeftPeak ; write the left-channel peak reading to
; the left-channel peak meter
MOV P3,RightPeak ; write to the right-channel peak meter

; Now reset the two peak detectors.


MOV LeftPeak,#0 ; zero out the left peak reading
MOV RightPeak,#0 ; zero out the right peak reading
RETI

; return from the interrupt

Das könnte Ihnen auch gefallen