EE265 Lab 2: Working with Hardware
Winter 2007-2008
Instructor: Teresa Meng
I. Purpose:
This lab
introduces real-time programming on the C5509 EVM board. Hardware-related
issues, real-time programming concepts, constraints, and limitations will be
discussed. We will take a closer look at the EVM board by generating a waveform
and observing the output. The waveform that is generated will also be fed back
to the input of the EVM board to be digitized and analyzed. This effectively
measures the distortion introduced by the Analog Interface Circuitry (AIC) on
the EVM board. This lab will attempt to relate these experiments to what you learned
from the lecture on analog interface and signal reconstruction. Finally, this
lab will introduce some experiments on sampling theory and quantization to give
you an idea of how they affect the signals.
II. Introduction:
A. Real-Time Processing
The main
purpose of this lab is to introduce real-time programming on the TI C5509
evaluation module (EVM) board. The method we introduce here will be used in the
rest of this lab course. In order to do real-time programming, we must be able
to acquire real-time inputs and generate real-time outputs. In the lab
exercises we will do, we want to use analog signals (such as an audio source)
as our input and we would like to generate analog signals (audio signal) as our
output. The C5509 itself does not have any analog inputs or outputs, so it can
only deal with digital input and outputs. This means that any inputs must be
converted to digital form before being passed to the C5509. Also, any output
from the C5509 can only be digital, so some external hardware must be needed to
convert the digital output to analog form. This means that the analog
interfacing is actually handled by hardware on the EVM board.
- Hardware for Real-Time
Processing:
- EVM Board:
The
EVM board contains many devices other than the C5509, which allows for
much more functionality than the C5509 alone. In fact, the EVM board is
very expensive and is not often sold as a consumer product. It is
intended to be used by system engineers to test and evaluate DSP
algorithms before integrating the DSP processor with the peripheral
hardware. The EVM board gives you access to the hardware and tells you
exactly what the processor can do (more than what the simulator can show
you, especially with real-time interrupts). This facilitates
hardware-level debugging and confirms interoperability between the DSP
processor and peripheral components. Furthermore, the EVM board works
with physical (analog) inputs and outputs that are acquired, processed,
and generated in real-time. This allows the designer to identify the limitations
of real-time signal processing through implementation.
- Analog Interface Circuitry
(AIC):
The
EVM board's Analog Interface Circuitry (AIC) converts the physical
signals to digital signals and vice versa. The AIC can sustain a sampling
rate of up to 96 KHz. TI's C5509 DSP processor runs at a clock rate of
200 MHz. As a result, real-time development using the C5509 EVM is most
suitable for data communications and audio signal processing as opposed
to image or video processing.
- Low-level details of Signal
Acquisition and Generation:
- Interconnected Components:
The
concept of real-time coding is quite simple, but in practice it involves
coordinating several different components (not just the C5509) and you
have to consider how these different components communicate data to each
other. On the EVM board, the C5509 DSP chip is the primary computational
component. Its job is to process digitized data. Real-time signal
processing applications typically make use of peripheral ADC and
digital-to-analog (DAC) converters optimized for the particular
application. The EVM provides these and other input-output (I/O)
peripherals.
- Communicating with
Peripherals:
- Serial Ports:
The
C5509a has a variety of I/O capabilities, including general purpose
(GPIO), parallel, and serial ports. Serial ports are commonly used to
handle asynchronous chip-to-chip data communication. Serial ports
communicate data at the bit level. The Multichannel Buffered Serial
Ports (McBSP) of the C55x DSPs actually comprise six pins: clock, frame-sync,
and data for both transmit and receive paths. In addition to
functioning as traditional buffered serial ports (a complete frame of
data is buffered in the serial port before the DSP has to deal with it),
the C55x McBSPs also have a direct memory access (DMA) interface.
- Interrupts:
It is possible to program the DSP to interface with the serial port
using a polling interface, where the DSP periodically asks the serial
port, Have you received data (input) or are you ready to transfer more
(output)?, and then either transfers available data or waits before
asking again. This technique has two flaws - first, if the DSP waits too
long before polling the serial port, data can be lost. Second, if the
DSP polls too frequently, it is wasting valuable computational cycles
unnecessarily. Thus, we typically use interrupts to communicate with
peripherals. For example, an interrupt may be used to notify the C5509
that a frame of data has been received by the serial port. (The interrupt process is described in detail in Lab 1. Please
refer to the Lab 1 web page for additional information.)
- Direct Memory
Access (DMA):
Common DSP processing requires a block of data to be transferred from
some external source (e.g., an external memory). This can be implemented
using a block repeat of the DSP code required to transfer each word of
data. However, an attractive alternative is the DMA interface. Using
DMA, rather than executing each move instruction, the CPU needs only
specify source, destination, and the amount of data to be transferred.
Then, the DMA controller takes secondary control of the memory bus,
using it to transfer data without the active control of the CPU. In
addition to external memories, as mentioned above, the McBSP ports allow
DMA control for block data transfer through the serial ports.
- Process from
Analog to Digital:
Thus,
in our implementation, the entire process of going from an analog signal
to DSP processing in software goes as follows:
- First, analog data is sampled
by the AIC unit on the EVM board. In most cases, each data sample is
digitized as two (stereo) 16-bit words.
- Once a data sample is
acquired, the AIC transmits the data to the C55x DSP chip. The data are
serialized and transmitted one bit at a time on the receive serial line
of one of the C55x's serial ports. The C55x DSP chip's serial port unit
detects that there is data on the serial line and proceeds to buffer
the bits one bit at a time. When a full word (8,16, or 32 bits) is
received, the word is copied into another register (so that the
original register can be reused to buffer new incoming bits).
- If DMA access has been
enabled, the serial port copies the received data to the receive memory
buffer specified by the DMA pointer, and increments the pointer.
- When the specified block
of output memory has been filled, the DMA controller uses a hardware
interrupt to signal the CPU that a block of input samples has been
received. (Not using DMA is equivalent to a block size of one - in this
case, the McBSP triggers the interrupt rather than the DMA controller.)
Note that this interrupt stops data transfer.
- The hardware interrupt
breaks the processing that is currently taking place. This is done by
first pushing the PC (program counter) onto the stack, setting the INTM
bit (the global interrupt mask used to disable servicing of additional
hardware interrupts from interrupting), and then jumping to a
predefined hardware interrupt vector corresponding to the DMA
controller. The hardware interrupt vector addresses are predefined so
as to allow immediate handling of the hardware interrupts. Each
interrupt's interrupt vector is only 4 words long. This is enough for
performing simple calculations that requires less than 4 instruction
words. What is more commonly done is to implement a branch in the
interrupt vector to branch to a larger routine for servicing the
interrupt. This larger routine is commonly referred to as the interrupt
service routine (ISR).
- The new data sample is
handled by the ISR for the DMA controller, which reads the data stored
in the receive memory buffer and then processes it. Normally, the ISR
simply needs to reset the DMA controller to point to a new receive
buffer and re-enable data transfer. The ISR also typically signals the
interrupted code that new data is available to be processed.
- After the ISR completes
(which could be a simple store into memory), it returns control to the
processor, resets the INTM bit (enables servicing of hardware
interrupts), and the interrupted process is then resumed.
- Process from
Digital to Analog:
A
similar process may occur in going from a digital output to an analog
signal. In general, the DSP algorithm produces an output buffer in
digital form which is transferred to the AIC over a serial port using
DMA. The output word could be sent directly to the AIC for
digital-to-analog conversion as soon as it is ready, but this is not
usually done. Rather, most real-time systems usually operate with DAC at
a fixed sampling rate, so they should be output at this fixed rate (not
as soon as they are ready). The fixed sampling rate is enabled by the
initial setup of the AIC, which requests samples from the transmit
serial port at the appropriate intervals. The transmit McBSP uses DMA to
read data from a block of memory in contrast the receive (ADC) McBSP
which uses DMA to write data.
- Possible
pitfalls:
The concept of interrupts is fairly straight-forward, but implementation
of the process can be difficult to implement. One catch is that
real-time data require real-time handling. If the above hardware
interrupt was unable to be serviced, then the data stored in the copy
register would have been completely overwritten by next data sample.
Another potential problem is that real-time interrupts are hard to
simulate and it is hard to see what actually goes on in the chip.
Consider the case where a hardware interrupt occurs while you are still
servicing one (which does not have to be for the same device). How would
you handle this? Since interrupts are automatically disabled while
servicing an interrupt, you would automatically lose data. It is
possible to enable servicing interrupts in an ISR but is not
recommended. (You will encounter many more interrupt related issues
throughout this course. A good imagination and experience is key to
writing a working code.)
- Dealing with Signal
Acquisition/Generation at a Higher Level:
- DSP/BIOS
Library:
To
help make the job of developing DSP applications easier, TI has provided
the DSP/BIOS, which is a library of functions that perform tasks related
to real-time coding. This library helps the developer perform many
low-level functions so that you don't have to worry about all the
details. The capabilities of the DSP/BIOS include memory partitioning,
configuring the processor upon startup, handling interrupts, and
handling serial communication between the processor and peripherals
(such as the AIC). By helping perform some of the programming tasks, the
DSP/BIOS lets the programmer operate at a slightly higher level, which
can make things much easier to deal with.
- Software
Interrupts:
One
of the capabilities provided by the DSP/BIOS is a structure of software
interrupts. Software interrupts are like hardware interrupts in that
when one is triggered, execution of lower level processes stops until
the software interrupt returns. However, they are triggered in software
rather than being triggered by a peripheral signal such as the DMA
controller or a timer. The benefit of software interrupts lies in code
organization. Higher priority or real-time processes can occur as
necessary and independently of lower priority process such as user
interface. We will use a software interrupt to handle full blocks
generated by DMA transfer from ADC and to fill blocks for DMA transfer
to DAC.
- Synchronization
Details (Mailboxes):
While ADC and DAC are initialized to operate at the same sampling rates,
the reading and writing processes may take different amounts of time to
fill the input buffer and empty the output buffer. However, you will
process input and output buffers synchronously. The DSP/BIOS solves this
problem of synchronizing multiple events by using something called a
mailbox. The mailbox keeps track of multiple events by using its bits as
flags. The mailbox process works as follows:
- The mailbox is initialized
to some non-zero value, where each 1 bit corresponds to an event that
needs to occur. These bits can be viewed as flags.
- Each event is associated
with a particular flag. Whenever an event occurs, its associated flag
is cleared to 0 in the mailbox.
- When all the necessary
events occur, the mailbox value finally becomes 0. When this occurs, a
software interrupt is generated to notify the application that all
conditions are now met.
- After the software
interrupt is issued, the mailbox is reset to its initial value and the
entire process is repeated.
This
process ensures that the application is not notified until all required
conditions are met, so the input and output pipes are effectively synchronized.
B. Analog Interface
The C5509 EVM board
uses the AIC23B. Detailed information on the AIC is given in TLV320 AIC23B Data Sheet. You will
not need most of the information given in the data sheet as the data sheet is
intended for the board designers.
III. Readings:
- Read the entire lab and pay
special attention to places where you need to write your own code. Have
some of your code ready before you come in to do the lab. You may need to
spend time debugging!
- An Audio Example
Section 2.2, "Pipe or PIP Module"
Section 3.1, "About the Example"
Section 3.3.2 "Audio Sampling Rate"
IV. Lab Exercises:
This lab will
take you step by step through setting up a real-time DSP code capable of
processing audio-band signals. Once the framework for handling real-time data
is setup, you will then implement a waveform generator to generate a sine wave
to the output of the DSP. You will also write a waveform recorder to record
signals and see the effect of the sampling/quantization process on their
spectrum. Finally, you will play with different sampling rates and quantization
schemes to see for yourself what kind of effects they introduce.
A. Setup
Although the
DSP/BIOS can assist you in configuring the processor, the interrupts, and the
serial ports, the DSP/BIOS still requires a fair amount of setup work in order
to get it working correctly. This section goes through the setup step by step.
We could have provided you an entire project template with all of this done for
you, but it is important for you to understand what goes on behind the scene
since you will be repeating the same procedure in later labs. The following
sections describe how to set up the DSP/BIOS to read data to/from the analog
interface chip, and how to configure the various program elements that are used
for the rest of the lab.
Setting up
the Project
Follow the procedure given in lab 1 to start CCS.
Create
a new project in the lab2/audio directory
and call it audio.
The assembly
template is provided in audio_tmpl.zip.
First, download and decompress these
files to your
lab2/audio directory.
Do not put the files in an "audio_tmpl" subfolder.
Add the
following source files to the project. Select Project->Add
Files to Project... to add source files. If you don't see the source
files listed, change the field Files of type: to
the appropriate type. For example, for .s55 (linear
assembly) codes, set the type as Asm Source Files (*.a*,*.s*).
- audio.c
- adc_setup.c
- aic23.c
- audio.cdb
- userlinker.cmd
Notice that the
automatically generated audiocfg* files are added to your
source code when you add audio.cdb.
Select Project->Scan All Dependencies. What this does is it
updates the include folder to reflect any header files that you have included
in your source codes. If you expand the include folder by clicking on the plus next to the Include folder, you will
see a very long list of files. Most of this is from DSP/BIOS. Remark:
From here on for the sake of conciseness, the term "expand" will be
used to denote the action of clicking on the "plus" symbol next to the item to be
expanded.
Completing
the DSP/BIOS Configuration
We need to
finish configuring the DSP/BIOS. Double click on the
audio.cdb file (located
under the DSP/BIOS Config folder).
- Under Scheduling,
expand the HWI - Hardware Interrupt Service Routine
Manager. This will list the interrupt vector table.
- Change the properties of HWI_INT14, (by right clicking). If you look up the
interrupt table C5509, this interrupt corresponds to the DMA #0 receive
interrupt.
- Enter _dmaHwiRcv
for the function: field.
Explanation: What you are doing here is
associating the hardware interrupt for the serial port with the function dmaHwiRcv (which is defined in the file adc_setup.c).
When the DMA buffer is full, it will cause the hardware interrupt to be
generated, which will execute the interrupt vector that is associated with
it. When you specify a function for this interrupt, you are essentially
redirecting the interrupt vector to the function dmaHwiRcv
to service the interrupt.
- Repeat for HWI_INT15,
associating it with the function _dmaHwiXmt.
- Be sure that Use Dispatcher
is selected in HWI dispatcher tab.
- Under Scheduling,
- Insert a software interrupt
in the SWI - Software Interrupt Manager
module (right click and select Insert SWI).
- Rename SWI0
to processBufferSwi.
- Right
click on the processBufferSwi module and change the
following settings:
- function: to _processBuffer
- mailbox: to 3
- arg0: to 0 (the default)
- arg1: to 0 (the default)
- Explanation: The function _processBufferSwi is a software interrupt handler. The
concept of software interrupt is similar to hardware interrupts except
that the SWI is actually generated by the software. What you have defined
above is the means of generating the software interrupt. The _processBufferSwi handler is associated with a mailbox
value that is initialized (to 3 in this particular case) at the beginning
of the program and also after each time this software interrupt has been
serviced. When the mailbox value is set to 0, the software interrupt to _processBufferSwi is said to be posted. This means that
the next time the _processBufferSwi handler runs and
sees that its mailbox is 0, it will generate its software interrupt
service routine (which is defined later to be _processBuffer,
which is a function we define in C code that will be called each time this
software interrupt occurs). The arguments you defined for the pipes
specify how the mailbox value gets processed. The mailbox is first
initialized to 3, or 11b. When the DMA receive buffer has a new frame that
is ready for reading, this mailbox value is updated by the function _SWI_andn. _SWI_andn is a function
that masks the mailbox with not(2), i.e. not(..0010b)=..1101b. As a result,
the mailbox will be set from 3 to 1. Similarly, when the DMA transmit
buffer empties a frame, freeing one up for writing, the mailbox value is
masked by not(1), which will effectively set the mailbox value to 0 (if it
has been set by the receive DMA to 1). In essence, regardless of which DMA
interrupt gets executed first, the mailbox value is set to 0 when both
buffers have been executed. This guarantees that the incoming buffer is
full and the outgoing buffer is empty, which is the appropriate condition
for notifying the main application (the _processBuffer
function that will be defined later).
- That is it for the DSP/BIOS
setup. Save and close the configuration window.
- To set compiler options, go
to Project->Build Options menu
- Add c:\CCStudio_v3.1\boards\dsk5509a_v1\include to
Preprocessor-> Include Search Path
- Replace
_DEBUG with _DEBUG;CHIP_5509A in Preprocessor->Pre-Defined Symbol
- Change Memory Model to Large in Advanced
- Add c:\CCStudio_v3.1\boards\dsk5509a_v1\lib to Library Search
Path
- Add dsk5509bsl.lib; csl5509ax.lib to Include Libraries
- Completing the Setup for this
Project
- You should examine the source
codes at this point. We will start with audio.c and
do some last modifications to get the code to work. Double
click on audio.c in the
navigation panel. Enable
the loopback operation by changing the #if (0) to #if (1) in processBuffer function .
- At this point, all source
codes have been properly setup and you are ready to build the executable. Click on the rebuild all icon or select Project->Rebuild All. You
should get 0 errors after compilation.
B. Digital Audio Loop-back
This exercise will be the first to use IO in this lab, so
we will merely verify their use. An audio source is generated on the host
computer and this is connected to the input of the EVM board. The loop-back is
done digitally by copying the data from the receive serial port to the transmit
serial port. You can check the functionality of this loop-back by listening to
the output of the EVM board. A better way to check the functionality is to
verify numerically that the input samples are copied to the output (the source
(src) buffer frame gets copied to the destination
(dst) buffer frame).
- In audio.c,
observe that the function main() is used only for initialization. After
main() completes, the DSP goes into an idle loop, which waits for things
to happen (such as hardware and software interrupts).
- Examine the
processBuffer() function. This function is called by
the software interrupt processBufferSwi whenever
the receive data buffer is full and the transmit data buffer is empty.
Examine the for-loop. Notice that src
and dst point to the receive and transmit
buffers, respectively filled and emptied by DMA.
- Connect an audio
source from the PC to the EVM input and connect headphones to the output
(as done in Lab 1). Now start the music.
- Load the compiled
executable, audio.out (in
the Debug folder).
- Run the program.
This can be done by pressing <F5>, selecting Run from the menus, or
by clicking the Run icon.
- After you have verified that
the audio loop-back code works, stop the program. This
can be done by pressing <Shift>-<F5>, selecting Halt from the
menus, or by clicking on the Halt icon.
- Browse through the source
codes to get a good understanding of how the different components
interact.
C. Sine Wave
Generator
In this portion of the lab, you will write a sine wave
generator to output a pure digital sine wave from the EVM board. This section
is intended to exercise your assembly programming skills with a simple exercise
of copying data from the data memory into the data transmit buffer, pointed to
by dst. A template for the assembly routine is
provided for you but you must complete the code and generate a sine wave at the
output of the EVM.
1. Setup
- The assembly template is
provided in sinegen.zip.
First, download this file and decompress to your
account, preferably under lab2/sinegen.
- To complete the setup, copy the entire lab2/audio/
directory (including subdirectories audio.CS_ and Debug) into this directory.
The sinegen files and the audio source files should be in the same
directory. This is so you can reuse as much of the
code as possible since you have already configured the audio project to
do real-time processing.
- Start a new CCS
session.
- Open the lab2/sinegen/audio.pjt
project. We will keep audio.pjt as the project name for the sake of
convenience.
- Add the file, sinegen_proc.s55, to the project.
- The main code, audio.c, must be modified in order to call the functions
defined in sinegen_proc.s55. Open
the file, audio.c, and
do the following modifications.
- Add extern
definitions for sinegen_proc_init() and sinegen_proc():
extern Void sinegen_proc_init(Void);
extern Void sinegen_proc(Void);
- In
the main()
function, add the following statement right before
IRQ_globalDisable();
sinegen_proc_init();
Note that there is no
underscore, "_", preceding the function name, sinegen_proc_init,
but in sinegen_proc.s55, this function does have the
underscore. This is simply the convention used to call C functions from
assembly, but the underscore is not needed in C.
In the processBuffer
() function, replace the for
loop with the following statement:
sinegen_proc();
So rather than copying
the data from the src buffer to the dst
buffer in the C code, you are calling a function (which in this case is written
in assembly), sinegen_proc(), to process the src and dst buffers.
- Open the header
file, sinegen_proc.h55. A convenient way of opening this is first select Project->Scan All Dependencies, and then expand the
include folder to find this include file. What you will see in this file
is a list of .global statements. This is
similar to the extern statements in C where the globalized variables can
be seen and read by codes in other files. Note also the underscore used
to reference variables defined in C as well as in the assembly code.
- Open the assembly
file, sinegen_proc.s55. A number of things are already provided to you:
- sinegen_proc.h55 is included at
the top.
- BUFSIZE is set to 0x80 = 128. This is the number of samples of the sine
wave that is stored in memory.
- An uninitialized section (.usect, meaning that you are not providing this section
with data until run-time) is defined to be allocated in the memory
section coefSect, 128 words large (second
argument). For more information on the .usect
directive, see Assembly Language Tool.
- An initialized section, .sect "coefDat", contains two sine waves,
addressable by sine1St and sine2St,
of different frequencies. You are to output either one of these sine
waves, each consisting of 128 samples, and analyze their frequency
characteristic during measurement.
- The .mmregs
assembler directive is REQUIRED. Without
it, you cannot reference MMR registers by their abbreviations, such as AC0, AC1, AR0,
AR3, BRC0, etc.
- A .text
section. Currently, the program is empty. You will write down your
sine wave generation codes.
- Compile the codes
as is, you should get no compilation errors at this
point. If so, fix them before you go on.
2. Coding
- Complete the
subroutines _sinegen_proc_init and _sinegen_proc to implement the
sinewave generator. _sinegen_proc_init is intended for any
initialization that needs to be performed, and _sinegen_proc
will used to copy the sine wave coefficients stored in the data memory to
the dst buffer. (At this point, you do not
need to be concerned with the _src buffer since you
are not operating on the receive buffer.) NOTE:
The size of output buffer and that of sine wave table are not the same.
This means that the sine wave should be addressed in circular manner, and
you should manage the circular buffer of sine wave table.
- Compile and test
your sine wave generator by listening to the EVM
output. If it sounds right, go on. You may have to come back to debug the
generator if you find that the measured waveform is not correct.
3. Debugging with the
CCS Graphing Feature
·
One of the most helpful debugging tools that we have
available is the graphing feature of Code Composer Studio. This allows us to
graphically plot out the values in region of memory (which can be very helpful
for sinewave generation). Here is a brief description of how to graph the dst buffer:
o
Select
View->Graph->Time/Frequency. A Graph
Property dialog box will pop up. Change the following settings:
§
Graph Title - dst
buffer. This is the label you have chosen to identify the graph window.
§
Start Address - dst. This is the label you
have chosen for starting address of your data buffer.
§
Acquisition Buffer Size - 192. This is the size of
the data buffer.
§
Display Data Size - 96. This specifies the
portion of the data buffer you would like to have plotted. The number specified
here must be smaller than the acquisition buffer size.
§
DSP Data Type - 16-bit
signed integer. This is the default type for digitized samples.
§
Click on OK to close this dialog
box. The data in your dst pipe frame will be
plotted with respect to time.
o
This will allow you to view the frame pointed to by dst. Keep in mind that dst
switches between input frames, so the graph will actually show you different
frames at different times.
o
The receive pipe can be viewed by graphing src.
4. Profiling
- To accurately profile a
section of your code, you need to subtract out the overhead associated
with extracting profiling statistics from the EVM board and transferring
them to the host computer. A procedure for accurate profiling is
described in the CCS User's
Guide accessible
through the EE265 Navigation Toolbar - On-Line Programming
Reference.
Read the section Profiler->Profile Clock Accuracy.
- Now, profile
and report your sine wave generator code.
- It may help to add NOPs to
either your assembly or C code to perform the profiling described in the
Profiling Help. To add NOPs (or any other assembly instruction to your C
code you can use the following format: asm(" NOP"); (Don't forget that
the NOP must be preceded by a "tab" to place it in the second
column of the assembly code.)
D. Audio Recorder
Once you have completed
and tested your sine wave generator, you will implement an audio recorder. You will
then analyze the audio samples using the CCS graphing tool to view the time and
frequency spectrum of the samples. You will also perform some simple
experiments to analyze the physical signals.
1. Coding
Specifications
- Copy the lab2/sinegen
directory to a new directory, call it lab2/recorder. Work in this new
directory. (You can start from a different project if you know of one
that is more appropriate than lab2/sinegen).
- Modify the code
so that it can do two things:
- record the input
to a buffer (for observation and also so we can do frequency
analysis on something larger than a single frame)
- copy the input
to the output (so that the incoming signal can be listened to)
- sinegen_proc_init may
or may not serve any purpose, so whether or not you keep it in your code is
up to you.
- Recorder
requirements:
- The audio recorder data
buffer will be 512 words for each channel (so it’s
512*2 = 1024 words) and should be a circular buffer that is continually
filled with samples from the src buffer
(received from the serial port). In other words, in addition to copying
the data stored in the src buffer to the
output dst buffer, you will also copy the
input samples to a data buffer that you specify.
- You will need to define
your own data section. You can do this with either the .sect
or the .usect directive. Don't forget to associate
this data section to a memory section in the linker command file! Do not
use the buffer_sect section that is already there.
- You will need to debug your
code in CCS and later you will use MATLAB to verify that your recorder
works properly (as described below).
2. Debugging using CCS
Features
·
Graphing:
As described
above, the graphing feature of CCS can be one of the most helpful debugging
tools that we have available. You can use the graphing feature to plot the
values directly, or you can also make other plots (such as the FFT of the
values). The following steps will guide you through the process of plotting the
recorded signal directly and also plotting its FFT magnitude:
o
To test your code, connect an audio
source and start the music, as described previously.
o
Compile, reset DSP, load the program
onto the EVM, and run the program.
o
Stop the program shortly (after few seconds -
to be sure that the buffer is filled with data samples).
o
Select View->Graph->Time/Frequency. A Graph Property dialog box
will pop up. Change the following settings:
§
Graph Title - Amplitude
vs. Time
§
Start Address - recordData.
This is the label you have chosen for starting address of your data buffer.
§
Acquisition Buffer Size - 1024.
This is the size of the data buffer.
§
Index Increment - 2.
This is because the buffer format is stereo, L/R interleaved format.
§
Display Data Size - 512.
This specifies the portion of the data buffer you would like to have plotted.
The number specified here must be smaller than the acquisition buffer size.
§
DSP Data Type - 16-bit
signed integer. This is the default type for digitized samples.
o
Click on OK to close this dialog
box. The data in your record buffer will be plotted with respect to time.
- To look at the frequency
spectrum of the received data, select View->Graph->Time/Frequency again and fill in
the following settings:
- Display Type - FFT Magnitude
- Graph Title - FFT Magnitude
- Start Address - recordData
- Acquisition
Buffer Size - 1024
- Index Increment - 2
- FFT
Framesize - 512
- DSP Data Type - 16-bit signed integer
- Click OK to close the
dialog box. The FFT magnitude plot of the record buffer will be plotted.
- Saving Data to File:
Another useful debugging option is to use an external program (such
as MATLAB) for analysis. You can do this by saving the data acquired in
memory onto the computer. One reason you might want to do this is if you
want to make a printout of the data plot. CCS does not support graph
printing, so it will need to be handled by another program. The following
steps will guide you through the process of storing your recorded data to
a file that can be opened in MATLAB:
- Select File->Data->Save...
- A Store
Data dialog box will pop up. For the
Save as type: field, select Integer (*.dat).
- Enter the
filename for the data to be stored (let's call it datarec.dat - you don't need to enter the .dat extension
since it will be added for you).
- Click on Save. The Store Data dialog box will close and the Storing Memory Into File dialog box will open.
- Enter the Address, Length, and
Page of the data you wish to store.
- Click OK to store the
data and to close the dialog box.
- Before you can load this
file into MATLAB, you must remove the first line of the data file. Note: Windows will treat this file as a Windows registry file,
so you will need to use some program such as Notepad or WordPad to edit
the file, instead of simply left-clicking on the file to open it. To do
this, you can Right-click the file and select Open With, and then choose
an editor. Open datarec.dat, delete the first line, and save datarec.dat.
- You may now load datarec.dat into MATLAB and generate a plot from there.
3. Verification using
MATLAB
Although CCS has many
useful debugging features, it cannot help you with all types of analysis that you
may wish to perform. For example,