Archive
12-17-2008
Today I’m going to work on getting the final piece of the ARM firmware settled: DMA. Right now, I’m acquiring samples from the SSP manually but I won’t be able to process data if I’m wasting all my time grabbing samples so I need to pass that task to the DMA controller. The unknown at this point is how the DMA controller affects to slave select line because I need it to toggle every 8 bytes to use it as the start acquisition line on the ADC.
12-16-2008
Well, just got back in port. The mission went well but the seas were terrible. The first night was the worst with 16 foot seas and it usually takes a day or two to acclimate so it was not fun at all. The seas calmed down a bit to about 8-12 foot seas the rest of the cruise with a lot of cold wind that is typical of December.
The AUV’s we were using performed very well, running their full 18 hour missions without intervention. We ran them at around 1000 meters, though they’re capable of 6000; surveying about 100 square miles of sea floor.
About the only mishap we had was one of our transponders “came loose” and drifted off. With some deft detective work, Greg was able to study the currents and winds to see where it would have drifted off to. It took us about an hour to locate it and when we pulled it aboard, the end of the line that should have had an anchor on it was just a frayed rope. Looks like something down there liked the taste of rope and chewed through about 1/2 inch thick line. The AUV had an interesting time with it because one of its transponders that was supposed to be a fixed point was suddenly drifting off. It recovered well though and completed its mission.
12-11-2008
12-10-2008
Final exam day. They say the waiting is the hardest part.
Update: 1:32 PM
Well that was easier than I thought. I finished early so that’s a good sign. We’ll find out how I did once he posts the solutions online. Grades are due on the 15th so hopefully I’ll know my final grade a week from now. Tonight I plan on finishing the documentation for my RF scripts and placing them online in the hope they’ll be useful to someone else.
Update: 5:24 PM
Well I did some analysis on the magnitude estimation trick I talked about Monday and it looks like it may work for us. Here’s the table of errors using a fixed point version of the estimator:
Angle Error using Magnitude Estimator
Name Alpha Beta Avg Err Peak Err
degrees) (degrees)
--------------------------------------------------
Min RMS Err 31048 12860 -0.07 3.18
Min Peak Err 31470 13035 0.70 2.37
Min RMS w/ Avg=0 31065 12867 -0.03 3.14
1, Min RMS Err 32767 10592 1.12 3.94
1, Min Peak Err 32767 11009 1.38 3.36
1, 1/2 32767 16383 4.53 6.06
1, 1/4 32767 8191 -0.48 7.55
Frerking 32767 13106 2.67 4.10
1, 11/32 32767 11263 1.54 3.11
1, 3/8 32767 12287 2.18 3.65
15/16, 15/32 30719 15359 1.01 3.82
15/16, 1/2 30719 16383 1.63 3.82
31/32, 11/32 31743 11263 -0.02 4.45
31/32, 3/8 31743 12287 0.64 3.01
61/64, 3/8 31231 12287 -0.15 3.72
61/64, 13/32 31231 13311 0.51 2.82Using the Min RMS w/ Avg=0 we could get about 0.03o error on average. I think, because our phase rolls evenly from 0 to 2π, we should achieve the average response with perhaps a little extra error from incomplete cycles. I’ll have to think a bit more about this but it looks promising.
12-08-2008
Not much to post today. I spent most of the day tracing down little bugs here and there. There was a interesting bug where small, seemingly insignificant code changes would sometimes cause the compiler to push some registers onto the stack, changing the amount of time it would take to perform a computation because of the extra push and pops.
There is an interesting trick for estimating the magnitude of a vector here. I started evaluating it for use with int16’s because it’ll be quite a quick operation on the ARM with the multiply and accumulate instructions.
That’s about it. I’ll be out tomorrow studying for my final exam in High Frequency Amplifiers. I’ve written a bunch of python code for impedance matching so I hope to post that once I’m done studying.
12-05-2008
It slipped my mind that using the dot product yields the absolute value of the angle difference and we care very much which vector leads of lags the other. No matter, cross product to the rescue! Because the cross product is anti-commutative, the sign of the resultant vector will tell us if the angle difference is positive of negative. We also know that the angle difference should remain constant over a reasonably short period of time so we’ll only need to compute the cross product for a single vector to determine the sign.
Update: 3:05 PM
Currently my buffer sizes and number of taps are divisible by 6. That makes optimal use of the registers in the ARM but it’s causing me a bit of a headache because 6 is not a 2n number, so I’m going to make everything divisible by 8 to ease some of the math involved.
12-04-2008
Just figured out what was wrong with my dot product calculation. I was multiplying two 16 bit integers together and they were rolling over. A simple cast to int32 and the problem was solved. Onward!
Update: 4:14 PM
Here’s and efficient implementation of the dot product that I wrote for the ARMv5E:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | ; void dot_product(int32 *product, int16 *vector1, int16 *vector2, uint32 N) dot_product STMDB SP!, {R4-R11, LR} ; Save registers to the stack next_sample LDMIA R1!, {R5, R6, R7} ; Load three vectors from vector 1 LDMIA R2!, {R8, R9, R10} ; Load three vectors from vector 2 SMULTT R11, R5, R8 ; temp = I*I SMLABB R11, R5, R8, R11 ; temp += Q*Q SMULTT R12, R6, R9 ; Repeat for the other samples SMLABB R12, R6, R9, R12 SMULTT R14, R7, R10 SMLABB R14, R7, R10, R14 STMIA R0!, {R11, R12, R14}; Save the dot products SUBS R3, R3, #3 ; Subtract 3 from N BGT next_sample ; Branch if N > 0 LDMIA SP!, {R4-R11, PC} ; Restore registers and return |
This code is functionally identical to the following code with the exception that the number of vectors in the assembly code should be evenly divisible by 3.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | void dot_product(int32 *product, int16 *vector1, int16 *vector2, uint32 N) { int16 I1, Q1, I2, Q2; for(;N--;) { I1 = *vector1++; Q1 = *vector1++; I2 = *vector2++; Q2 = *vector2++; *product++ = I1*I2 + Q1*Q2; } } |
The assembly version is about %25 faster. Use an oversized buffer if your number of samples is not evenly divisible by 3 or use the following code for arbitrary N:
1 2 3 4 5 6 7 8 9 10 11 12 13 | ; void dot_product(int32 *product, int16 *vector1, int16 *vector2, uint32 N) dot_product STMDB SP!, {R4-R6} ; Save registers to the stack next_sample LDR R5, [R1], #4 ; Load a vector from vector 1 LDR R6, [R2], #4 ; Load a vector from vector 2 SUBS R3, R3, #1 ; Subtract 1 from N SMULTT R12, R5, R6 ; temp = I*I SMLABB R12, R5, R6, R12 ; temp += Q*Q STR R7, [R0], #4 ; Save the dot product BGT next_sample ; Branch if N > 0 LDMIA SP!, {R4-R6} ; Restore registers BX R14 ; Return |
This version is about %15 faster.
Update: 5:59 PM
Well, my processing time is up to 2.8ms with IQ demod and dot product computation. It’s going to be tight!
12-03-2008
Now that IQ demodulation is working, it’s on to CORDIC. The trick is to try and get this done in a reasonable amount of time. If it’s not possible then I’ll have to explore other options for computing atan2. I only need accuracy to 0.1 degrees so that may help a bit.
Update: 2:05 PM
It’s looking like using the dot product to get the angle between vectors might be a more fruitful path. It jumps straight to the angle between vectors, which is what we want, and looks like it might be quicker to calculate. The only issue is that I really need the two vectors to be unit vectors because I don’t want to have to compute the magnitude and do division. Hmm, simulation time…
Update: 6:00 PM
Good news is that computing the magnitude and doing the division will be much faster than I thought. Bad news is that it’s not computing the angle properly. The angle should be:

but the answer is different when I compute atan2 of the two vectors and subtract them. I’m sure I’m doing something silly but it’s one of those things you have to put down for a little while so off to home I go.
12-02-2008
Today I’m going to try and figure out why my FIR Filter doesn’t seem to work properly. I’m doing IQ Demodulation for a radio location system we’re developing but the output of my new FIR Filter looks really weird. Hopefully it’s just the taps for the filter that are wrong. I’ll update this post as I go along and I’ll eventually post the FIR code for the ARM that’s based on some code in the excellent ARM System Developer’s Guide but modified to take IQ interleaved data.
Update: 2:02 PM
Note to self: An array of int16’s looks weird when you treat them like int32’s. Ok, so the FIR filters work fine; it was my data display that was screwy.
Update: 5:03 PM
IQ Demodulation is working great. My goal is to do all our mathematics within 5 milliseconds so that our acquisition time is greater than our processing time. That way we can process continually so we won’t have to deal with synchronizing bursts of packets. IQ demod is taking 1.8ms so I have 3.2ms to do everything else. Should be fun! ![]()