250 likes | 390 Views
Developing a multi-thread Simulation of GPS system You’ll only need to add the threads – all functions (except correlation( )) provided. M. Smith Electrical Engineering, University of Calgary Smithmr @ ucalgary.ca. Tackled today. Why bother with a GPS example of a multi-tasking DSP problem?
E N D
Developing a multi-thread Simulation of GPS systemYou’ll only need to add the threads – all functions (except correlation( )) provided M. Smith Electrical Engineering, University of Calgary Smithmr @ ucalgary.ca
Tackled today • Why bother with a GPS example of a multi-tasking DSP problem? • Prototype of working product • Explanation of the provided functions • Tests are provided so you can test out your assembly code versions of the correlation functions. • Lab. 4 and Take home quiz 4 • How are they interlinked?
Why bother? • Learn the basics of programming DSP within real time operation system constraints • Interesting Basic concepts to understand GPS functionality • Ability to easily visualize work load • Basic C++ correlation (provided by me) (Lab. 4) • FFT correlation (provided by Analog as part of C++ library (THQ4) • Assembly FIR algorithm modified for correlation (Lab. 4 using Lab 3 code provided by you) • Use of CLU XCORR instruction (THQ4 -- Hints from Analog, myself and Trevor) • Research side • Allows me to test out the E-TDD tool set in RTOS environment on embedded system, and gain personal familiarity with problems of doing so.
GPS Positioning Concepts • For now make 2 assumptions: • We know the distance to each satellite • We know where each satellite is • Require 3 satellites for a 3-D position in this “ideal” scenario • Requires 4 satellites to account for local receiver clock drift. (1)
GPS Signal Structure • Each satellite transmits 2 carrier frequencies referred to as L1 (1575 MHz) and L2 (1227 MHz) • Each carrier frequency is BPSK modulated with a unique PRN (pseudo random number) code • The PRN code on L1 is called CA code (coarse acquisition), The PRN code on L2 is called P code (precise) • CA code takes 1 ms for full PRN transmission at 1MHz chip (bit) rate. P code takes 1.5 s for full PRN transmission at ~10MHz chip rate • Also modulated on each carrier is 50 Hz data that includes the current position of the satellite
Determining Time • Use the PRN code to determine time • Use time to determine distance to the satellite distance = speed of light * time (1)
Algorithms to Find PRN Phase • Time-domain Cross correlation: 1/N∑x1 (n) * x2(n) • Coding equivalent to FIR filter, but need to filter N sets of data, each shifted by one data point • Correlation of perfectly matching signals gives a maximum value • Correlation of 2 random data sequences tends to 0 • PRN code from different satellites are designed to correlate to 0. • Frequency domain correlation: 1/N F-1[X1(k)X2(k)] where F-1 is the inverse Discrete Fourier Transform and the X’s are the Discrete Fourier Transforms of two sequences D
Lab. 4 – Parts 1, 2 and 3 – done as pre-laboratory tasks – about 1 hour • Part 1 -- Create an Initialization Thread • Use VDK::Sleep(200) sleep as a work load • Part 2 – Launch (create) Satellite Receiver Tasks as free running tasks • Use VDK::Sleep(X) as a work load • ClearReceiverThread X = 100 • ReceiveSatellite1 X = 10 • ReceiveSatellite2 X = 20 • ReceiveSatellite3 X = 30 • Part 3 – Add semaphores to get satellite tasks running in proper time sequences
Lab. 4 – Continued – details to be added • Part 4 -- Add Satellite Receiver Tasks Payloads • Download payload code from the web – code provided • Part 5 – Generate E-TTD tests for correlation function designed using your existing FIR filter code • Part 6 – Add analysis and reporting threads • Part 7 – adjust task priorities to make realistic and working • Demo and code hand-in with minor write-up
Lab. 4 – Adding payloads to the threads • Thread set to receive signals from satellites • Simulation – Clear receiveBuffer. Add satelliteX’s PRN signal stream to receiveBuffer based on satellite location and speed. • Functions and their tests provided • Thread set to analyze received signal • Correlate information in receiveBuffer with satelliteX PRN stream to see if signal from satellite is present or not. • Analysis functions and their tests provided • Correlation function tests provided • Thread set to report on satellite status • ErrorX means that signal to satellite signal X was lost
Final result – VDK Thread Picture Satellite thread generates signal into receiveBuffer Analysis thread – long execution time – each tick = 0.05 ms
Satellite signal “received” into receiveBuffer Clear Add Add Add Startbuffer Sat1 Sat2 Sat3 Analysis
Analysis errors can occur Errors occur – here one satellite is active but algorithm gets confused. Length of PRN too smallChoice of PRN poor – rand( ) poor?
InitializationThread::Run() InitializationThread::Run() { VDK::CreateThread(kReceiverControlThread); VDK::CreateThread(kAnalysisThread); VDK::CreateThread(kError1); VDK::CreateThread(kError2); VDK::CreateThread(kError3); VDK::CreateThread(kReportThread); VDK::CreateThread(kReceiverBufferClear); VDK::CreateThread(kReceive1Satellite); VDK::CreateThread(kReceive2Satellite); VDK::CreateThread(kReceive3Satellite); while (1) { VDK::PostSemaphore(kCaptureSignalSTART); VDK::Sleep(1500); if (VDK::GetUptime( ) > 20000) exit(0); } } You cancut-and-pastethis code from the slide PROVIDED your thread namesare the same as mine Order of creationchanges the waythings look inVDK HISTORYwindow
void ReceiverControlThread::Run() // You’ll need to add #include “Satellite.h” // Generate a PRN sequence Warning -- big problems with the rand( ) generator const int prn_length = TEST_PRN_LENGTH; InitializeSatelliteData(prn_length); SetSatelliteVelocity(2, 60); SetSatelliteLocation(2, 0); while (1) { VDK::PendSemaphore(kCaptureSignalSTART, 0); VDK::PostSemaphore(kReceiverBufferClearSTART); VDK::PendSemaphore(kReceiverBufferClearDONE, 0); VDK::PostSemaphore(kReceiver1SatelliteSTART); VDK::PendSemaphore(kReceiver1SatelliteDONE, 0); VDK::PostSemaphore(kReceiver2SatelliteSTART); VDK::PendSemaphore(kReceiver2SatelliteDONE, 0); VDK::PostSemaphore(kReceiver3SatelliteSTART); VDK::PendSemaphore(kReceiver3SatelliteDONE, 0); VDK::PostSemaphore(kAnalysisSTART); VDK::PendSemaphore(kAnalysisDONE, 0); VDK::PostSemaphore(kCaptureSignalDONE); }
ReceiverBufferClear::Run() #include "Satellite.h" // ReceiverBufferClear Run Function (ReceiverBufferClear's main{}) void ReceiverBufferClear::Run() { while (1) { // TODO - Put the thread's "main" body HERE VDK::PendSemaphore(kReceiverBufferClearSTART, 0); ClearReceiveBuffer( ); VDK::PostSemaphore(kReceiverBufferClearDONE); // Use a "break" instruction to exit the "while (1)" loop } // TODO - Put the thread's exit from "main" HERE // A thread is automatically Destroyed when it exits its run function }
Adding satellite data void Receive2Satellite::Run() { // Data not added from this satellite while (1) { VDK::PendSemaphore(kReceiver2SatelliteSTART, 0); // TransferSatelliteDataToReceiveBuffer(1); VDK::PostSemaphore(kReceiver2SatelliteDONE); } } void Receive3Satellite::Run() { // Data added while (1) { VDK::PendSemaphore(kReceiver3SatelliteSTART, 0); TransferSatelliteDataToReceiveBuffer(2); VDK::PostSemaphore(kReceiver3SatelliteDONE); } }
AnalysisThread::Run() void AnalysisThread::Run() { bool valid_results; while (1) { // TODO - Put the thread's "main" body HERE VDK::PendSemaphore(kAnalysisSTART, 0); AnalyseReceiveBuffer( ); valid_results = ValidateResults( ); if (!valid_results) { VDK::PostSemaphore(kReportSTART); VDK::PendSemaphore(kReportDONE, 0); } VDK::PostSemaphore(kAnalysisDONE); } }
void ReportThread::Run( ) void ReportThread::Run() { while (1) { VDK::PendSemaphore(kReportSTART, 0); if ((satelliteActive[0] != MYsatelliteActive[0]) || (satelliteLocation[0] != MYsatelliteLocation[0])) VDK::PostSemaphore(kSatellite0LOST); if ((satelliteActive[1] != MYsatelliteActive[1]) || (satelliteLocation[1] != MYsatelliteLocation[1])) VDK::PostSemaphore(kSatellite0LOST); if ((satelliteActive[2] != MYsatelliteActive[2]) || (satelliteLocation[2] != MYsatelliteLocation[2])) VDK::PostSemaphore(kSatellite0LOST); VDK::PostSemaphore(kSatellite1LOST); VDK::PostSemaphore(kSatellite2LOST); VDK::PostSemaphore(kReportDONE); } } Just spotted a BUG
What you’ll need to modify void CorrelateAlongReceiverBuffer(int *satellitePRN, int array_size, int *correlation_result){ for (int i = 0; i < RECEIVE_BUFFER_LENGTH; i++) correlation_result[i] = 0; for (int result_index = 0; result_index < RECEIVE_BUFFER_LENGTH - array_size; result_index++) { int sum = 0; for (int sum_index = 0; sum_index < array_size; sum_index++) sum = sum + satellitePRN[sum_index] * receiveBuffer[sum_index + result_index]; correlation_result[result_index] = sum; } }
Provided “Satellite.h” #ifdef DECLARE_SATELLITE_VARIABLES #define EXTERN #else #define EXTERN extern #endif #define RECEIVE_BUFFER_LENGTH 256 EXTERN int receiveBuffer[RECEIVE_BUFFER_LENGTH]; void ClearReceiveBuffer(void); #define NUM_SATELLITES 3 #define MAX_PRN_LENGTH 128 #define TEST_PRN_LENGTH 128 // Generate a pseudo-random number sequence // Warning -- big problems with the rand( ) generator // when generating random bits -- (rand ( ) >> X ) % 2 #define SATELLITE_SEED 0x12397 EXTERN pm int satellitePRN[NUM_SATELLITES][MAX_PRN_LENGTH]; EXTERN pm bool satelliteActive[NUM_SATELLITES]; EXTERN pm int satelliteLocation[NUM_SATELLITES]; EXTERN pm int satelliteNextLocation[NUM_SATELLITES]; EXTERN pm int satelliteVelocity[NUM_SATELLITES]; EXTERN pm int MYsatelliteLocation[NUM_SATELLITES]; EXTERN pm bool MYsatelliteActive[NUM_SATELLITES]; EXTERN pm int MYsatelliteNextLocation[NUM_SATELLITES]; EXTERN pm int MYsatelliteVelocity[NUM_SATELLITES];
Provided “Satellite.h” void TransferSatelliteDataToReceiveBuffer(int which_satellite); bool InitializeSatelliteData(int prn_length); void SetSatelliteVelocity(int which_satellite, int which_speed); void SetSatelliteLocation(int which_satellite, int which_distance); int GetSatelliteVelocity(int which_satellite); int GetSatelliteLocation(int which_satellite); bool InitializeMYSatelliteData(void); void SetMYSatelliteVelocity(int which_satellite, int which_speed); void SetMYSatelliteLocation(int which_satellite, int which_distance); int GetMYSatelliteVelocity(int which_satellite); int GetMYSatelliteLocation(int which_satellite); void CrossCorrelate(int *first, int *second, int *correlation_result, int array_size); void CorrelateAlongReceiverBuffer(int *satellitePRN, int array_size, int *correlation_result); int MaximumLocation(int *correlation_result, int array_size); int MaximumValue(int *correlation_result, int array_size); bool ValidateResults(void); void AnalyseReceiveBuffer(void); int CalculateCorrelationRange(void); int CalculateCorrelationAverage(void)
Provided Tests Examples TEST(CrossCorrelationTest, DEVELOPER_TEST) { TEST_LEVEL(9); int first[ARRAY_SIZE] = {1, 0, 0, 0, 0, 0, 0, 0}; int second[ARRAY_SIZE] = {0, 1, 0, 0, 0, 0, 0, 0}; int third[ARRAY_SIZE] = {0, 0, 1, 0, 0, 0, 0, 0}; int correlation_result[ARRAY_SIZE]; int maximum_location; CrossCorrelate(first, first, correlation_result, ARRAY_SIZE); maximum_location = MaximumLocation(correlation_result, ARRAY_SIZE); CHECK_EQUAL(maximum_location, 0); CrossCorrelate(first, second, correlation_result, ARRAY_SIZE); maximum_location = MaximumLocation(correlation_result, ARRAY_SIZE); CHECK_EQUAL(maximum_location, 1); etc. ……..}
Tackled today • Why bother with a GPS example of a multi-tasking DSP problem? • Prototype of working product • Explanation of the provided functions • Tests are provided so you can test out your assembly code versions of the correlation functions. • Lab. 4 and Take home quiz 4 • How are they interlinked?