Skip to content Skip to navigation


You are here: Home » Content » Digital Transmitter: Processor Optimization Exercise for Frequency Shift Keying


Recently Viewed

This feature requires Javascript to be enabled.

Digital Transmitter: Processor Optimization Exercise for Frequency Shift Keying

Module by: Robert Morrison, Matt Kleffner, Michael Frutiger. E-mail the authors

Based on: Digital Transmitter: Processor Optimization Exercise for Frequency Shift Keying by Matthew Berry

Summary: Students are to implement and optimize a frequency shift keying (FSK) digital transmitter and pseudo-noise (PN) sequence generator.

In this lab you are to implement and optimize the frequency shift keying (FSK) digital transmitter and pseudo-noise (PN) sequence generator shown in this figure. For the lab grade, you will be judged on the execution time of your system (memory usage need not be minimized).


You will implement and optimize the complete system shown in this figure. over the next two weeks. You may write in C, assembly, or any combination of the two; choose whatever will allow you to write the fastest code. The optimization process will probably be much easier if you plan for optimization before you begin any programming.

Reference Implementation

We provide for you in Appendix A a complete C implementation of this lab. It consists of the main C file fsk.c and a C-callable SINE function in SINE.asm. Compile and link this using the batch file C_ASM.bat by typing "C_ASM fsk SINE" on the command prompt. Load FSK.out onto the DSP, and run the code. Observe the output (Channel 1) on the scope.

After taking a look at the source code of this implementation, you'll realize that this is a rather inefficient implementation. It's there to show you what output is expected of your code, and the computational efficiency of your code will be judged against it. While the given code might serve as a starting point, you should do whatever you need to do to make your code as efficient as possible, while producing the same output as the given code.

PN Generator

Once you have planned your program strategy, implement the PN generator from Figure 2 and verify that it is working. If you are programming in assembly, you may wish to refer to the description of assembly instructions for logical operations in Section 2-2 of the C54x Mnemonic Instruction Set reference. Initialize the shift register to one.

In testing the PN generator, you may find the file v: \ece320\54x\dspclib\pn_output.mat helpful. To use it, type load v:\ece320\54x\dspclib\pn_output at the Matlab command prompt. This will load a vector pn_output into memory. The vector contains 500 elements, which are the first 500 output bits of the PN generator. Be prepared to prove to a TA that your PN generator works properly as part of your quiz.


For your transmitter implementation you are to use the data-block-to-carrier-frequency mapping in this table and a digital symbol period of T symb =32 T symb 32 samples.

Viewing the transmitted signal on the oscilloscope may help you determine whether your code works properly, but you should check it more carefully by setting breakpoints in Code Composer and using the Memory option from the View menu to view the contents of memory. The vector signal analyzer (VSA) provides another method of testing.

Testing with the VSA

The VSA is an instrument capable of demodulating digital signals. You may use the VSA to demodulate your FSK signal and display the symbols received.

Configuring the VSA

The VSA is the big HP unit on a cart in the front of the classroom. Plug the output from the DSP board into the "Channel 1" jack on the front of the vector signal analyzer, and then turn on the analyzer and follow these instructions to display your output:

After powering the signal analyzer up, the display will not be in the correct mode. Use the following sequence of keypresses to set it up properly:

If this doesn't work, hit "Save/Recall," F7 (Catalog), point at ECE320.STA with the wheel, and hit F5 (Recall State) and F1 (Enter).
  • "Freq" button, followed by F1 (center), 11.025 (on the keypad), and F3 (KHz)
  • F2 (span), 22, and F3 (KHz)
  • "Range," then F5 (ch1 autorange up/down)
  • "Instrument Mode," then F3 (demodulation)

Viewing the signal spectrum on the VSA

The VSA is also capable of displaying the spectrum of a signal. Hook up the output of your PN generator to the VSA and set it up properly to view the spectrum of the random sequence. Hit "Instrument Mode" and then F1 (Scalar) to see the spectrum. Note that you can also use your Lab 4 code for this purpose.

Does what you see match the Matlab simulations?


One purpose of this lab is to teach optimization and efficient code techniques. For this reason, for your lab grade you will be judged primarily on the total execution time of your system. You are not required to optimize memory use. Note that by execution time we mean cycle count, not the number of instructions in your program. Remember that several of the TMS320C54xx instructions take more than one cycle. The multicycle instructions are primarily the multi-word instructions, including instructions that take immediates, like stm, and instructions using direct addressing of memory (such as ld *(temp),A). Branch and repeat statements also require several cycles to execute. Most C instructions take more than one cycle. The debugger can be used to determine the exact number of cycles used by your code; ask your TA to demonstrate. However, since the number of execution cycles used by an instruction is usually determined by the number of words in its encoding, the easiest way to estimate the number of cycles used by your code is to count the number of instruction words in the .lst file or the disassembly window in the debugger.

We will grade you based on the number of cycles used between the return from the WAITDATA call and the arrival at the next WAITDATA call in assembly, or the return from one WaitAudio call and the arrival at the next WaitAudio call in C. If the number of cycles between the two points is variable, the maximum possible number of cycles will be counted. You must use the core.asm file in v:\ece320\54x\dsplib\core.asm or the C core file in v:\ece320\54x\dspclib\core.asm as provided by the TAs; these files may not be modified. You explicitly may not change the number of samples read and written by each WAITDATA or WaitAudio call! We reserve the right to test your code by substituting the test vector core file.


This is a two-week lab. Your prelab is due a week after the quiz for Lab 4, and the quizzing occurs two weeks after the quiz for Lab 4.

Grading for this lab will be a bit different from past labs:

  • 1 point: Prelab
  • 2 points: Working code, implemented from scratch in assembly language or C.
  • 5 points: Optimization. These points will be assigned based on your cycle counts and the optimizations you have made.
  • 2 points: Oral quiz.

Appendix A:




        1    /* ECE320, Lab 5, Reference Implementation (Non-Optimized) */
        2    /* Michael Frutiger 2/24/04 */
        4    #include "v:/ece320/54x/dspclib/core.h"   /* Declarations for core file */
        6    main()
        7    {
        8        int *Rcvptr,*Xmitptr;                 /* pointers to Xmit & Rcv Bufs   */
        9        int r1,r2;      // temp random bit storage
        10        int symbol;           // 0 for [00], 1 for [01], 2 for [10], 3 for [11]
        11        int n;          // dummy variable
        13        int freqs[4] = {9, 13, 21, 17};     // 32*freqs
        14        int phase[32];
        15        int output[64];                     // temp output storage
        18        // Initial PN generator register contents
        19        int seed = 1;
        21        // Initial phase
        22        int prev_phase = 0;
        25        while( 1 )
        26        {
        27              /* Wait for a new block of samples */
        28              WaitAudio(&Rcvptr,&Xmitptr);
        30            // Get next two random bits
        31              r1 = randbit( &seed );
        32              r2 = randbit( &seed );
        33              // Convert 2 bit binary number to decimal
        34              symbol = series2parallel(r1,r2);
        36              for (n=0; n<32; n++)
        37              {
        38                      phase[n] = ( freqs[symbol]*n + prev_phase ) % 64;   // get into 0 to 64 range
        39                      if (phase[n] > 32) phase[n]=phase[n]-64;    // get into -32 to 32 range
        40                      phase[n] = phase[n] * 1024;    // 1024=2^15*1/32
        41                                                     // [-2^15 2^15] range for use with
        42                                                     // SINE.asm
        43              }
        44              sine(&phase[0], &output[0], 32);                // compute SINE, put result in output[0 - 
        45              prev_phase = ( freqs[symbol]*32 + prev_phase ) % 64;   // save current phase offset
        47                      // Get next two random bits
        48              r1 = randbit( &seed );
        49              r2 = randbit( &seed );
        50              // Convert 2 bit binary number to decimal
        51              symbol = series2parallel(r1,r2);
        53              for (n=0; n<32; n++)
        54              {
        55                      phase[n] = ( freqs[symbol]*n + prev_phase ) % 64;
        56                      if (phase[n] > 32) phase[n]=phase[n]-64;
        57                      phase[n] = phase[n] * 1024;
        58              }
        59              sine(&phase[0], &output[32], 32);
        60              prev_phase = ( freqs[symbol]*32 + prev_phase ) % 64;
        63              // Transfer the two symbols to transmit buffer
        64              for (n=0; n<64; n++)
        65              {
        66                      Xmitptr[6*n] = output[n];
        67              }
        69        }
        70    }
        73    // Converts 2 bit binary number (r2r1) to decimal
        74    int series2parallel(int r2, int r1)
        75    {
        76      if ((r2==0)&&(r1==0)) return 0;
        77      else if ((r2==0)&&(r1==1)) return 1;
        78      else if ((r2==1)&&(r1==0)) return 2;
        79      else return 3;
        80    }
        82    //Returns as an integer a random bit, based on the 15 low-significance bits in iseed (which is
        83    //modified for the next call).
        84    int randbit(unsigned int *iseed)
        85    {
        86      unsigned int newbit; // The accumulated XORs.
        87      newbit =  (*iseed >> 14) & 1 ^ (*iseed >> 13)  & 1;  // XOR bit 15 and bit 14
        88      // Leftshift the seed and put the result of the XORs in its bit 1.
        89      *iseed=(*iseed << 1) | newbit;
        90      return (int) newbit;
        91    }

Content actions

Download module as:

Add module to:

My Favorites (?)

'My Favorites' is a special kind of lens which you can use to bookmark modules and collections. 'My Favorites' can only be seen by you, and collections saved in 'My Favorites' can remember the last module you were on. You need an account to use 'My Favorites'.

| A lens I own (?)

Definition of a lens


A lens is a custom view of the content in the repository. You can think of it as a fancy kind of list that will let you see content through the eyes of organizations and people you trust.

What is in a lens?

Lens makers point to materials (modules and collections), creating a guide that includes their own comments and descriptive tags about the content.

Who can create a lens?

Any individual member, a community, or a respected organization.

What are tags? tag icon

Tags are descriptors added by lens makers to help label content, attaching a vocabulary that is meaningful in the context of the lens.

| External bookmarks