Assignment #2: Due March 14, 2016
Assignment #2: Due March 14, 2016
Assignment #2: Due March 14, 2016
a 11 a 12 a 13
A = a 21 a 22 a 23
a 31 a 32 a 33
a.) Write a C function having function prototype
inv3by3(float32_t* A, float32_t* invAData),
for float32_t using the matrix of cofactors method as shown below:
a 22 a 23 a 13 a 12 a 12 a 13
a 32 a 33 a 33 a 32 a 22 a 23
–1 1 a 23 a 21 a 11 a 13 a 13 a 11
A = ----------------
det A a 33 a 31 a 31 a 33 a 23 a 21
a 21 a 22 a 12 a 11 a 11 a 12
a 31 a 32 a 32 a 31 a 21 a 22
where the cofactors are evaluated as the determinate of the 2 2 matrices of the form
det = A B = AD – BC
C D
and det[A] is the determinant of the 3 3 matrix. Verify that your inverse calculation is
correct using the test matrix below:
1 2 2
A = 4 6 10
–3 6 –8
Provide storage for A using a 1D array, i.e.,
float32_t AData[N*N] = {1.0f,2.0f,2.0f,4.0f,6.0f,10.0f,-3.0f,6.0f,
-8.0f};
This is known as row-major form and is the way C is used to store 2D arrays in numerical
computations. This is also the way CMSIS-DSP stores matrices. The inverse needs to be
stored in like fashion. Verify that the solution is correct by (1) comparing it with a Python/
MATLAB/Mathematica solution and (2) numerically pre-multiply your solution by
AData and see that you get a 3 3 identity matrix. Use the CMSIS-DSP function
Look at the J. Yiutext Example 22.6.1, p.732, to see how to use the CMSIS-DSP matrix
library functions. Hint: you will have to create three matrix instance structures using:
b.) Profile your function at compiler optimization Level 0 (o0) and Level 3 (o3) using
the test matrix
c.) Repeat part (a) except now use CMSIS-DSP for all of your calculations. In particular you
will use the function
arm_mat_inverse_f32(const arm_matrix_instance_f32 * pSrc,
arm_matrix_instance_f32 * pDst)
For details on using this function see the example on p. 730–735 of the text (Yiu).
3. In this program you will convert the pseudo-code for a square-root algorithm shown below
into C code for float32_t input/output variables.
Approximate square root with bisection method
INPUT: Argument x, endpoint values a, b, such that a < b
OUTPUT: value which differs from sqrt(x) by less than 1
done = 0
a = 0
b = square root of largest possible argument (e.g. ~216).
c = -1
do {
c_old = c
c = (a+b)/2
if (c*c == x) {
done = 1
} else if (c*c < x) {
a = c
} else {
b = c
}
} while (!done) && (c != c_old)
return c
a.) Code the above square root algorithm in C. Profile you code using the test values 23, 56.5,
and 1023.7. Run tests at compiler optimization o0 and o3. Note: You will need to estab-
lish a stopping condition, as the present form is designed for integer math. I suggest modi-
fying the line:
if (c*c == x) { to something like if (fabs(c*c - x) <= max_error) {
–6
where max-error is initially set to 10 . Realize that this value directly impacts the
execution speed, as a smaller error requirement means more iterations are required. See if
you can find the accuracy of the standard library square root.
b.) Compare the performance of your square root function at o3 with the standard math
library function for float (float32_t), using float sqrtf(float x).
c.) Compare the performance of your square root function at o3 to the M4 FPU intrinsic
function float32_t __sqrtf(float x).
4. Real-time Gold Code sequence generation using a lookup table (LUT): Pseudo-random
sequences find application in digital communications system. The most common sequences
are known as M-sequences, where M stands for maximal length. A Gold Code formed by
exclusive ORing two M sequences of the same length but of different phases. For example
Gold codes of length 1023 are uniquely assigned to the GPS satellites so that the transmis-
Following each clock (note the clock input is implicitly assumed to be a part of the shift
register) a new output bit is taken from Stage 3. The feedback taps for this M = 3 exam-
ple are located at 2 and 3. On the far right of the figure you see the output pattern has
M
length 2 – 1 bits before repeating. Note also that the initial shift register load is
1 1 1 . If you start the generator in the all zeros state it will fail to produce an output as
the M zeros in a row is not found in the output pattern. A pattern of M ones occurs exactly
M Taps
3 [0, 1, 1]
4 [0, 0, 1, 1]
5 [0, 0, 1, 0, 1]
6 [0, 0, 0, 0, 1, 1]
7 [0, 0, 0, 1, 0, 0, 1]
8 [0, 0, 0, 1, 1, 1, 0, 1]
9 [0, 0, 0, 0, 1, 0, 0, 0, 1
10 [0, 0, 0, 0, 0, 0, 1, 0, 0, 1]
once, which useful in deriving a synch waveform. The taps settings in Table 1 are not
unique, but using an arbitrary tap set does not guarantee a maximal length sequence. Also
note that the output can be taken from any shift register element. At the M stage is conve-
nient for drawing purposes.
Your task in (a) is to code a generator using a single 16-bit integer, i.e., uint16_t, to
hold the elements of the shift register. A suggested function prototype is to employ a data
structure such as, Mseq, as shown below. This makes for an efficient function call.
// gen_PN header: gen_PN.h, implementation in gen_PN.c
// Mark Wickert February 2015
//In main
gen_PN_init(&PN1,5,3,5,0x1);
//In ISR
gen_PN(&PN1);
some_variable = PN1.output_bit;
b.) Test the generator by calling from within the SPI2_IRQHandler function of the
stm32_loop_intr.c module you used in Lab1. Write the output to a GPIO pin so you
can view the waveform on the scope/logic analyzer. You may also wish to fill a buffer so
you can export the output to a file or perhaps the PC serial port. Test the generator with
M = 5 and M = 10 . Verify the period and search for the pattern of fives ones and 10
ones respectively.
c.) To explore Gold codes you will consider the case of the M = 10 (1023 bit patterns) used
in GPS for coarse acquisition (CA). Note: Commerical GPS is limited to using only the
CA codes. In the Lab 2 ZIP package you will find a text file, ca1thru37.txt, that con-
tains 37 Gold codes arranged in columns. To get a particular code to run on the Cortex-M
a utility that writes header files is available in the IPython notebook for lab two. This note-
bool also shows you how to read selected columns of a text file using the numpy
loadtxt() function. Some of the IPYthon notebook code is shown below:
1N–1
R ij k = ---- x i n x j n + k
N
n=0
where N is the data record length used in the calculation (actually estimation).
Since the Gold codes form a family of codes, taking any pair codes i j with result in
only a small cross-correlation value. This means that i j codes are nearly orthogonal and
as signals can lie on top of each other cause minimal interference when a receiver uses the
code of interest to recover via cross-correlation the information riding the transmitted sig-
nal. Here we use the function Rij, lags_axis = dc.xcorr(xi,xj,lag_val-
ue_range) to calculate the auto and cross-correlation between CA codes 1 and 2. The
code module digitalcom.py contains the needed function.
Below is a sample calculation from the IPython notebook for Lab 2. Note that signal-
ing is typically done using a bipolar waveform, that is the 0/1 values of the code are con-
as +1/-1
values from
the full CA
code matrix
Your task is to send code values for some code i and j, i j to the codec left and right
codec channels. Additional signal processing is required: (1) convert the 0/1 code values
to 10000 and implement a pulse shaping scheme using a raised cosine (RC) pulse shape.
This will give you a chance to again use the CMSIS-DSP library. The system block dia-
gram is the following:
int8_t int16_t float32_t float32_t int16_t
CA 0/1 To
Level SRC FIR codec
Code Bits Shift 4
Filter
mod 1023 {0,1} 10000 output
12 kbits/s Upsample 48 ksamps/s
(effective) by 4 means (actual) Use CMSIS-DSP
stuff 4-1 float32_t FIR
zero samples functions
The pulse shaping operation is jumping ahead to give you a taste of FIR filtering and
impulse train modulation from digital communications applications. An upsampling factor
of four is employed, which means on every fourth pass through the I2S_HANDLER func-
The bit rate will be 48/4 = 12 kbps (CA code chips per second). The header file
SRC_shape.h is supplied in the ZIP. The details of how to create it is included in the
IPython notebook for Lab 2.
d.) Now you are ready for testing via waveform data collection and auto- and cross-correla-
tion calculations in Python. Along the way also view the left or right output channels on
the spectrum analyzer (Agilent 4395A in the lab or using the Analog discovery). Verify
Agilent 4395A
Line
0 1
RF Out R .. A .. B
that the main lobe of the spectrum extends from 0 Hz to about 8.1 KHz ( 12 1.35 2 ).
Capture a long record or the left and right channels of at f s = 40 kHz or higher and import
into IPython.
I know there are a lot of parts to Problem 4. We will talk in class on Monday.
The objective is to keep the record level in GoldWave in the green just below the yellow the yel-
low part of the display shown below:
Before getting to this point you need to the control panel to configure Hardware and Sound:
Double click on
the device that has
a mic input jack
I have an iMic
USB audio system
connected here
Under the Advanced tab make sure to choose 2 channel, 16 bit, 48000 Hz or higher quality. It is
very important that you choose 2 channel, as it seems that the default for mic inputs is frequently
1 channel. With 1 channel the left and right channels will be summer together. A sure sign of this
is when you inport the wave file into Python and see that both channels are identical!
Next you need click on the Levels tab and be prepared to use the slider (see below) to adjust the
recoding level. With this control you make sure the Gold Wave recording leveling is not clipping.
With the iMic system I use there is a switch from Mic to Line, so additional. attenuation is avail-
able . With a mic only input you will need to set the gain slider to almost zero to avoid clipping. If
you cannot get the level low enough an extreme measure is to insert a resistive voltage divider
circuit as shown below:
L/R To
Mic Input
10k/1k voltage
divider as a
L/R From ~10:1 signal
Wolfson Codec attenuator
Assuming that you capture at 48 ksps, you will now have approximately same the sample rate as
the signal was generated at.
Once you have a .wav file move on to post processing the file. In an Python notebook you now
import the .wav file generate some plots.
Import digitalcom.py to get access to some useful functions
Import the wave captured via
Gold Wave
Generate an
eye plot
Note the eye plot will likely no be as clear as what was shown during lecture. By only plotting 500
Generate waveform
autocorrelation and cross
correlation. HereCA1 and
CA12 was used in the
real-time code.
Generate an
eye plot
Note in the eye plot I am assuming ~7 samples per bit since 80 ksps/12 kbps = 6.6667 and using
the Farrow resample function with rate increase of 1.05 gives 6.6667 1.05 = 7 .