final code by 32X84688

VIEWS: 6 PAGES: 38

									10.1 audio.h
#ifndef _AUDIO_H
#define _AUDIO_H
#include <p30f5011.h>
#include <stdlib.h>


void sample_audio (void);
void send_audio_uart (void);
void audio_menu (void);
unsigned int isqrt(unsigned long a);
void FFT (void);
void displaypout (void);
void display_bars (void);
void loop_bars (void);
void average_bargraph(void);

#endif

10.2 audio.c

/********************************************************/
/*                ---------                             */
/*                |audio.c|                             */
/*                ---------                             */
/*                                                      */
/* Contains code to handle the audio spectrum           */
/********************************************************/

#include   "audio.h"
#include   "misc.h"
#include   "FftFunct.h"
#include   "interrupt.h"
#include   <dsp.h>
#include   <stdio.h>

#define FFT_SIZE 256

fractional audio[256];       //audio samples buffer
fractional buff[256];        //audio samples double buffer
unsigned int audio_count;       //count of the number of samples
acquired
extern char data[10];
char build_data[10];
char set_mask[8] = {0xFE,0xFD,0xFB,0xF7,0xEF,0xDF,0xBF,0x7F};
extern int cycle_count;
fractional pIN[FFT_SIZE];
unsigned int pOUT[FFT_SIZE/2];
unsigned int bargraph[8];
unsigned int average_bar[8];

int scale[8] = {16,16,16,16,32,32,32,32};
int offset[8] = {0,8,16,24,32,48,64,80};
int shift[8] = {10,9,8,7,7,7,5,5};

/********************************************************/
/*                --------------                        */
/*                |sample_audio|                        */
/*                --------------                        */
/*                                                      */
/*    This function samples the audio signal and        */
/* does a simple averaging to smooth out the response */
/********************************************************/

void sample_audio (void)
{
  int i;
  for(i=0;i<3;i++){
    audio_count = 0;             //clear sample count
    IEC1bits.T5IE = 1;           //timer 5 interrupt enable
    while (audio_count < 256);   //wait until we have enough samples
    IEC1bits.T5IE = 0;           //timer 5 interrupt enable
    FFT();                       //Calculates the FFT and quantizes it
to 8 bars
    average_bargraph();          //used to smooth the response
  }
} /* sample_audio */

/********************************************************/
/*                ------------------                    */
/*                |average_bargraph|                    */
/*                ------------------                    */
/*                                                      */
/* Simple averaging of current bargraph and next        */
/* bargraph                                             */
/********************************************************/

void average_bargraph(){
  int i;
  for(i=0;i<8;i++){
    //average_bar is equal to have itself plus half the new bargraph
    average_bar[i] = (average_bar[i]>>1) + (bargraph[i]>>1);
  }
} /*average_bargraph */


/********************************************************/
/*                ------------                          */
/*                |audio_menu|                          */
/*                ------------                          */
/*                                                      */
/*      The audio menu to display relevant information */
/* and to start the audio spectrum.                     */
/* Sample Audio -- calls sample_audio--used in debuging*/
/* Send Integer Data -- Displays the last 256 values */
/*           sampled                                    */
/* FFT -- Displays the last FFT values calculated       */
/* bars -- prints out the current bar values -- used */
/*          in debugging                                */
/* Exit -- returns to main menu                         */
/********************************************************/

void audio_menu (void)
{
 char c;

 while (1)
 {
   uart_puts("\n\r--Audio Menu--\r\n");
   uart_puts("(1) Sample Audio\r\n");
   uart_puts("(2) Send Integer Data\r\n");
   uart_puts("(3) FFT\r\n");
   uart_puts("(4) bars\r\n");
   uart_puts("(5) loop bars\r\n");
   uart_puts("(9) Exit\r\n");

    while (!U2STAbits.URXDA);
    c = (char) U2RXREG;
    //uart_putc(c);
    switch(c)
    {
    case '1' : {sample_audio(); break;}
    case '2' : {send_audio_uart(); break;}
    case '3' : {displaypout();break;}
    case '4' : {display_bars();break;}
    case '5' : {loop_bars();break;}
    case '9' : {return; break;}
    }
  }
} /* audio_menu */

/********************************************************/
/*                ------------                          */
/*                |audio_menu|                          */
/*                ------------                          */
/*                                                      */
/* Starts the audio spectrum loop, q will quit and      */
/* return to the main menu. This function also builds */
/* the bars from the values calculated                  */
/********************************************************/

void loop_bars(){

 int i = 0;
 int j = 0;
 char c;

 //starting message
 uart_puts("Press (q) to stop audio spectrum\r\n");
 //wait for the next input capture, and then clear the data
 while(cycle_count);
 for(i=0;i<8;i++){
   data[i] = 0x00;
 }

 while(1){
   sample_audio();
   for(i=0;i<8;i++){
     for(j=0;j<8;j++){
     if(average_bar[j]>i){
       //if average_bar is greater than the line being built
          //set that bit high
        build_data[j] |= (0x01<<i);
      } else {
        //if the average_bar is less or equal, clear that line bit
        build_data[j] &= (set_mask[i]);
      }
      }
    }
    for(i=0;i<8;i++){
      if(build_data[i] < data [i]){
      //new built data bar is lower than the current bar
        //decrease by one bar
      data[i] >>= 1;
        data[i] |= 0x01;
      }
      else{
      //new built data bar is higher, set to new value
        //keeps it responding quick enough
      data[i] = build_data[i];}
    }
    cycle_count = 1;
    if(U2STAbits.URXDA == 1){
      c = (char) U2RXREG;
      if(c == 'q' || c == 'Q'){break;}
    }
    //wait until another rotation of the drum is complete
    while(cycle_count);
 }
 intialize_data();
}
/********************************************************/
/*                --------------                        */
/*                |display_bars|                        */
/*                --------------                        */
/*                                                      */
/*      Displays current bar values, used during debug */
/********************************************************/

void display_bars(){
   int i=0;
   int k=0;
   char string[20];

  uart_puts("Bars: \n\r");
  for(k=0;k<8;k++){
    uart_puti(bargraph[k]);
    sprintf(string, " %4i \r\n", bargraph[k]);
    uart_puts(string);
  }
  uart_puts("\r\n");
}
/********************************************************/
/*                -----                                 */
/*                |FFT|                                 */
/*                -----                                 */
/*                                                      */
/*      Displays FFT values to import into Matlab, used */
/* during debug stages                                  */
/********************************************************/

void FFT(){
  int k;
  int i;

  CalcFFT(pIN,pOUT);
  for(k=0;k<8;k++){
     bargraph[k] = 0;
      for(i=0;i<scale[k];i++){
        if(k==0&&i==1){}
        else if(k==0&&i==2){
        if(pOUT[2] > 6500){}
        else{bargraph[k] = pOUT[2];}
        }
        else {bargraph[k] += pOUT[offset[k]+i];}
      }
      bargraph[k] >>= shift[k];
   }
}
/********************************************************/
/*                --------------                        */
/*                |display_pout|                        */
/*                --------------                        */
/*                                                      */
/* Displays the calculated FFT values -- debug function*/
/********************************************************/

void displaypout (void)
{
  unsigned int k;
  char string[20];

  for (k=0; k<128; k++)
  {
    sprintf(string, "%4i ", pOUT[k]);
    uart_puts(string);
  }

  while (!U2STAbits.URXDA);
  string[0] = U2RXREG;
  uart_puts ("\n\r");
} /* send_audio_uart */

/********************************************************/
/*                -----------------                     */
/*                |send_audio_uart|                     */
/*                -----------------                     */
/*                                                      */
/*   Displays the sampled audio values -- debuging func */
/********************************************************/

void send_audio_uart (void)
{
  unsigned int k;
  char string[20];
 for (k=0; k<256; k++)
 {
   sprintf(string, "%4i ", audio[k]);
   uart_puts(string);
 }

  while (!U2STAbits.URXDA);
  string[0] = U2RXREG;
  uart_puts ("\n\r");
} /* send_audio_uart */

10.3 char_lookup.h

/********************************************************/
/*                ----------                            */
/*                |char_map|                            */
/*                ----------                            */
/*                                                      */
/*     Used to convert ASCII to our laser display       */
/*         Column-major order                           */
/********************************************************/

#ifndef _CHAR_LOOKUP_H
#define _CHAR_LOOKUP_H

const unsigned char char_map[485]={
  0x00,0x00,0x00,0x00,0x00, //    space
  0x00,0x00,0xf2,0x00,0x00, //    !
  0x00,0xe0,0x00,0xe0,0x00, //    "
  0x28,0xfe,0x28,0xfe,0x28, //    #
  0x24,0x54,0xfe,0x54,0x48, //    $
  0xc4,0xc8,0x10,0x26,0x46, //    %
  0x6c,0x92,0xaa,0x44,0x0a, //    &
  0x00,0xa0,0xc0,0x00,0x00, //    '
  0x00,0x38,0x44,0x82,0x00, //    (
  0x00,0x82,0x44,0x38,0x00, //    )
  0x28,0x10,0x7c,0x10,0x28, //    *
  0x10,0x10,0x7c,0x10,0x10, //    +
  0x00,0x0a,0x0c,0x00,0x00, //    ,
  0x10,0x10,0x10,0x10,0x10, //    -
  0x00,0x06,0x06,0x00,0x00, //    .
  0x04,0x08,0x10,0x20,0x40, //    /
  0x7c,0x8a,0x92,0xa2,0x7c, //    0
  0x00,0x42,0xfe,0x02,0x00, //    1
  0x42,0x86,0x8a,0x92,0x62, //    2
  0x84,0x82,0xa2,0xd2,0x8c, //    3
  0x18,0x28,0x48,0xfe,0x08, //    4
  0xe4,0xa2,0xa2,0xa2,0x9c, //    5
  0x3c,0x52,0x92,0x92,0x0c, //    6
  0x80,0x8e,0x90,0xa0,0xc0, //    7
  0x6c,0x92,0x92,0x92,0x6c, //    8
  0x60,0x92,0x92,0x94,0x78, //    9
  0x00,0x6c,0x6c,0x00,0x00, //    :
  0x00,0x6a,0x6c,0x00,0x00, //    ;
  0x10,0x28,0x44,0x82,0x00, //    <
  0x28,0x28,0x28,0x28,0x28, //    =
0x00,0x82,0x44,0x28,0x10,   //   >
0x40,0x80,0x8a,0x90,0x60,   //   ?
0x4c,0x92,0x9e,0x82,0x7c,   //   @
0x7e,0x88,0x88,0x88,0x7e,   //   A
0xfe,0x92,0x92,0x92,0x6c,   //   B
0x7c,0x82,0x82,0x82,0x44,   //   C
0xfe,0x82,0x82,0x44,0x38,   //   D
0xfe,0x92,0x92,0x92,0x82,   //   E
0xfe,0x90,0x90,0x90,0x80,   //   F
0x7c,0x82,0x92,0x92,0x5e,   //   G
0xfe,0x10,0x10,0x10,0xfe,   //   H
0x00,0x82,0xfe,0x82,0x00,   //   I
0x04,0x02,0x82,0xfc,0x80,   //   J
0xfe,0x10,0x28,0x44,0x82,   //   K
0xfe,0x02,0x02,0x02,0x02,   //   L
0xfe,0x40,0x30,0x40,0xfe,   //   M
0xfe,0x20,0x10,0x08,0xfe,   //   N
0x7c,0x82,0x82,0x82,0x7c,   //   O
0xfe,0x90,0x90,0x90,0x60,   //   P
0x7c,0x82,0x8a,0x84,0x7a,   //   Q
0xfe,0x90,0x98,0x94,0x62,   //   R
0x62,0x92,0x92,0x92,0x8c,   //   S
0x80,0x80,0xfe,0x80,0x80,   //   T
0xfc,0x02,0x02,0x02,0xfc,   //   U
0xf8,0x04,0x02,0x04,0xf8,   //   V
0xfc,0x02,0x1c,0x02,0xfc,   //   W
0xc6,0x28,0x10,0x28,0xc6,   //   X
0xe0,0x10,0x0e,0x10,0xe0,   //   Y
0x86,0x8a,0x92,0xa2,0xc2,   //   Z
0x00,0xfe,0x82,0x82,0x00,   //   [
0x40,0x20,0x10,0x08,0x04,   //   \
0x00,0x00,0x00,0x00,0x00,   //   GARBAGE
0x00,0x82,0x82,0xfe,0x00,   //   ]
0x20,0x40,0x80,0x40,0x20,   //   ^
0x02,0x02,0x02,0x02,0x02,   //   _
0x00,0x80,0x40,0x20,0x00,   //   `
0x04,0x2a,0x2a,0x2a,0x1e,   //   a
0xfe,0x12,0x22,0x22,0x1c,   //   b
0x1c,0x22,0x22,0x22,0x04,   //   c
0x1c,0x22,0x22,0x12,0xfe,   //   d
0x1c,0x2a,0x2a,0x2a,0x18,   //   e
0x10,0x7e,0x90,0x80,0x40,   //   f
0x30,0x4a,0x4a,0x4a,0x7c,   //   g
0xfe,0x10,0x20,0x20,0x1e,   //   h
0x00,0x22,0xbe,0x02,0x00,   //   i
0x04,0x02,0x22,0xbc,0x00,   //   j
0xfe,0x08,0x14,0x22,0x00,   //   k
0x00,0x82,0xfe,0x02,0x00,   //   l
0x3e,0x20,0x18,0x20,0x1e,   //   m
0x3e,0x10,0x20,0x20,0x1e,   //   n
0x1c,0x22,0x22,0x22,0x1c,   //   o
0x3e,0x28,0x28,0x28,0x10,   //   p
0x10,0x28,0x28,0x18,0x3e,   //   q
0x3e,0x10,0x20,0x20,0x10,   //   r
0x12,0x2a,0x2a,0x2a,0x04,   //   s
0x20,0xfc,0x22,0x02,0x04,   //   t
0x3c,0x02,0x02,0x04,0x3e,   //   u
  0x38,0x04,0x02,0x04,0x38,   //   v
  0x3c,0x02,0x0c,0x02,0x3c,   //   w
  0x22,0x14,0x08,0x14,0x22,   //   x
  0x30,0x0a,0x0a,0x0a,0x3c,   //   y
  0x22,0x26,0x2a,0x32,0x22,   //   z
  0x00,0x10,0x6c,0x82,0x00,   //   {
  0x00,0x00,0xfe,0x00,0x00,   //   |
  0x00,0x82,0x6c,0x10,0x00,   //   }
  0x40,0x80,0x40,0x20,0x40,   //   ~
  0x10,0x38,0x54,0x10,0x10    //   <-
};
#endif

10.4 FFTFunct.h

//This code was found on the website
http://www.moetronix.com/dspic/files/dspdemosource.zip
//It's implementation of the dsp.h functions was simliar enough to our
code, so
//we modified it to meet our needs.

/*
=======================================================================
===*/
/* - - - - - - - - - - - - F F T F U N C T , H - - - - - - - - - - -
- - - */
/*
=======================================================================
===*/
/*    Created   07-10-2004   M. Wheatley
*/
/*    Modified 07-10-2004    MW
*/
/*.....................................................................
.... */
/* FFT Module Include File
*/
/*.....................................................................
.... */
#ifndef FFT_MODULE
#define FFT_MODULE

/*>>>>>>>>>>>>>>>>>>>>>> Global Defines
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<*/
#include <dsp.h>

/*>>>>>>>>>>>>>>>>>>>>>>> External memory
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<*/

/*>>>>>>>>>>>>>>>>>>>>>> External functions
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<*/
extern void InitFFT( void );
extern void CalcFFT( fractional* pIn, int* pOut);

#endif
10.5 FFTFunct.c

//This code was found on the website
http://www.moetronix.com/dspic/files/dspdemosource.zip
//It's implementation of the dsp.h functions was simliar enough to our
code, so
//we modified it to meet our needs.


/*
=======================================================================
===*/
/* - - - - - - - - - - - - F F T F U N C T , C - - - - - - - - - - -
- - - */
/*
=======================================================================
===*/
/*    Created   07-11-2004   M. Wheatley
*/
/*    Modified 07-19-2004    MW
*/
/*.....................................................................
.... */
/* FFT Processing Module
*/
/*.....................................................................
.... */

/*---------------------------------------------------------------------
------*/
/*------------------------> I N C L U D E S <--------------------------
------*/
/*---------------------------------------------------------------------
------*/
#include <p30f5011.h>
#include <dsp.h>
/*---------------------------------------------------------------------
------*/
/*----------------> P R O C E S S O R    S P E C I F I C <-------------
------*/
/*---------------------------------------------------------------------
------*/

/*---------------------------------------------------------------------
------*/
/*--------> T Y P E D E F S   U N I O N S    S T R U C T U R E S <-----
------*/
/*---------------------------------------------------------------------
------*/

/*---------------------------------------------------------------------
------*/
/*--------------------> L O C A L   D E F I N E S <--------------------
------*/
/*---------------------------------------------------------------------
------*/
#define FFT_SIZE 256
#define LOG2N 8               // LOG2(FFT_SIZE)

/*---------------------------------------------------------------------
------*/
/*--------------> G L O B A L M E M O R Y A L L O C A T I O N <------
------*/
/*---------------------------------------------------------------------
------*/

/*---------------------------------------------------------------------
------*/
/*--------------> L O C A L M E M O R Y A L L O C A T I O N <--------
------*/
/*---------------------------------------------------------------------
------*/
static unsigned int page;
static fractcomplex* offset;

/* FFT input and output data must be stored in Y-Space */
static fractcomplex FftBuf[FFT_SIZE] __attribute__ ( (section
(".ybss"), aligned(FFT_SIZE*4) ) );

//Complex forward FFT Twiddle factors pre-generated to save RAM
// Wreal[k] = 32767 * cos( 2*PI*k/FFT_SIZE )
// Wimag[k] = -32767 * sin( 2*PI*k/FFT_SIZE )
//     0 <= k < FFT_SIZE/2

const fractcomplex TWIDDLE_FACTORS[FFT_SIZE/2] =
{
       32767,      0, 32757,    -804, 32728, -1608,      32678,    -2410,
       32609, -3212, 32521, -4011, 32412, -4808,         32285,    -5602,
       32137, -6393, 31971, -7179, 31785, -7962,         31580,    -8739,
       31356, -9512, 31113, -10278, 30852, -11039,       30571,   -11793,
       30273, -12539, 29956, -13279, 29621, -14010,      29268,   -14732,
       28898, -15446, 28510, -16151, 28105, -16846,      27683,   -17530,
       27245, -18204, 26790, -18867, 26319, -19519,      25832,   -20159,
       25329, -20787, 24811, -21402, 24279, -22005,      23731,   -22594,
       23170, -23170, 22594, -23731, 22005, -24279,      21403,   -24811,
       20787, -25329, 20159, -25832, 19519, -26319,      18868,   -26790,
       18204, -27245, 17530, -27683, 16846, -28105,      16151,   -28510,
       15446, -28898, 14732, -29268, 14010, -29621,      13279,   -29956,
       12539, -30273, 11793, -30571, 11039, -30852,      10278,   -31113,
        9512, -31356,   8739, -31580,   7962, -31785,     7179,   -31971,
        6393, -32137,   5602, -32285,   4808, -32412,     4011,   -32521,
        3212, -32609,   2411, -32678,   1608, -32728,      804,   -32757,
           0, -32767,   -804, -32757, -1608, -32728,     -2410,   -32678,
       -3212, -32609, -4011, -32521, -4808, -32412,      -5602,   -32285,
       -6392, -32137, -7179, -31971, -7962, -31785,      -8739,   -31580,
       -9512, -31356, -10278, -31113, -11039, -30852,   -11793,   -30571,
      -12539, -30273, -13278, -29956, -14010, -29621,   -14732,   -29268,
      -15446, -28898, -16151, -28510, -16846, -28105,   -17530,   -27683,
      -18204, -27245, -18867, -26790, -19519, -26319,   -20159,   -25832,
      -20787, -25329, -21402, -24812, -22005, -24279,   -22594,   -23731,
      -23170, -23170, -23731, -22594, -24279, -22005,   -24811,   -21403,
      -25329, -20787, -25832, -20159, -26319, -19519,   -26790,   -18868,
      -27245, -18204, -27683, -17530, -28105, -16846, -28510, -16151,
      -28898, -15446, -29268, -14732, -29621, -14010, -29956, -13279,
      -30273, -12539, -30571, -11793, -30852, -11039, -31113, -10278,
      -31356, -9512, -31580, -8739, -31785, -7962, -31971, -7179,
      -32137, -6393, -32285, -5602, -32412, -4808, -32521, -4011,
      -32609, -3212, -32678, -2411, -32728, -1608, -32757, -804
      };
/* Windowing data table */

static fractional HanningWindow[FFT_SIZE] =
{
       0,   19,    44,    78,   123,   177,   241,     314,     398,     490,
    593,   705,   826,   957, 1097, 1247, 1405,       1572,    1749,    1934,
   2128, 2330, 2541, 2761, 2988, 3224, 3467,          3718,    3977,    4244,
   4517, 4798, 5086, 5381, 5682, 5989, 6303,          6623,    6949,    7281,
   7618, 7960, 8308, 8660, 9017, 9378, 9744,         10113,   10487,   10864,
  11244, 11627, 12013, 12402, 12793, 13187, 13582,   13979,   14377,   14777,
  15178, 15579, 15981, 16383, 16785, 17187, 17588,   17989,   18389,   18787,
  19184, 19579, 19973, 20364, 20753, 21139, 21522,   21902,   22279,   22653,
  23022, 23388, 23749, 24106, 24458, 24806, 25148,   25485,   25817,   26143,
  26463, 26777, 27084, 27385, 27680, 27968, 28249,   28522,   28789,   29048,
  29299, 29542, 29778, 30005, 30225, 30436, 30638,   30832,   31017,   31194,
  31361, 31519, 31669, 31809, 31940, 32061, 32173,   32276,   32368,   32452,
  32525, 32589, 32643, 32688, 32722, 32747, 32762,   32767,   32767,   32762,
  32747, 32722, 32688, 32643, 32589, 32525, 32452,   32368,   32276,   32173,
  32061, 31940, 31809, 31669, 31519, 31361, 31194,   31017,   30832,   30638,
  30436, 30225, 30005, 29778, 29542, 29299, 29048,   28789,   28522,   28249,
  27968, 27680, 27385, 27084, 26777, 26463, 26143,   25817,   25485,   25148,
  24806, 24458, 24106, 23749, 23388, 23022, 22653,   22279,   21902,   21522,
  21139, 20753, 20364, 19973, 19579, 19184, 18787,   18389,   17989,   17588,
  17187, 16785, 16383, 15981, 15579, 15178, 14777,   14377,   13979,   13582,
  13187, 12793, 12402, 12013, 11627, 11244, 10864,   10487,   10113,    9744,
   9378, 9017, 8660, 8308, 7960, 7618, 7281,          6949,    6623,    6303,
   5989, 5682, 5381, 5086, 4798, 4517, 4244,          3977,    3718,    3467,
   3224, 2988, 2761, 2541, 2330, 2128, 1934,          1749,    1572,    1405,
   1247, 1097,    957,   826,   705,   593,   490,     398,     314,     241,
    177,   123,    78,    44,    19,     0
    };

/*---------------------------------------------------------------------
------*/
/*-----------------------> P R O T O T Y P E S <-----------------------
------*/
/*---------------------------------------------------------------------
------*/
void InitFFT( void );
void CalcFFT( fractional* pIn, int* pOut);

/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%*/
/*                          ---------------
*/
/*                         | I n i t F F T |
*/
/*                          ---------------
*/
/*    This initializes the FFT Processing module.
*/
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%*/
void InitFFT( void)
{

}

/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%*/
/*                            ---------------
*/
/*                          | C a l c F F T |
*/
/*                            ---------------
*/
/*     Calculates the real FFT of pIn and places the log2 mag in pOut.
*/
/*        (1840uS)                                           */
                                       */
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%*/
void CalcFFT( fractional* pIn, int* pOut)
{
   int i;
   int tmp;
   VectorWindow(FFT_SIZE, pIn, pIn, HanningWindow);     //window the data
   for (i=0; i<FFT_SIZE; i++)
     {
       FftBuf[i].real = pIn[i];       //input data is real
       FftBuf[i].imag = 0;      //so zero the complex side
     }
   asm("mov #psvpage(_TWIDDLE_FACTORS),w0\nmov w0,_page");      //sets up
Twiddle factors
   asm("mov #psvoffset(_TWIDDLE_FACTORS),w0\nmov w0,_offset"); //sets up
Twiddle factors
   FFTComplexIP( LOG2N, FftBuf, offset, page ); //Calculates a complex
FFT
   BitReverseComplex(LOG2N, FftBuf); //Performs a bit reversal on the
indexes from the FFT calculation
   for(i=0;i<FFT_SIZE/2;i++){
     FftBuf[i].real = FftBuf[i].real * 0.01; //scales the real
     FftBuf[i].imag = FftBuf[i].imag * 0.01; //scales the imaginary
     //combines the two by summing the squares, the sqaure root was
attempted, however it gave
     //erronous results. Due to time constraints, we weren't able to
solve this problem.
     pOut[i] =
(FftBuf[i].real*FftBuf[i].real+FftBuf[i].imag*FftBuf[i].imag);
   }
}


10.6 flash.h

#ifndef _FLASH_H
#define _FLASH_H

#include <p30f5011.h>
#define FRAMESIZE 128

char FlashStatus(void);
int ReadFrame(int, char *);
int WriteFrame(int, char *);

#endif

10.7 flash.c

/********************************************************/
/*                 ---------                            */
/*                 |flash.c|                            */
/*                 ---------                            */
/*                                                      */
/* Contains code to read and write to the SPI Flash     */
/********************************************************/
#include "flash.h"

/********************************************************/
/*                -----------------                     */
/*                | FlashStatus |                       */
/*                -----------------                     */
/*                                                      */
/*   Displays the status byte of the flash chip         */
/*         7   |    6    | 5 | 4 | 3 | 2 | 1 | 0        */
/*       !BUSY | COMPARE | 0 | 1 | 1 | 1 | x | x        */
/********************************************************/

char FlashStatus(void)
{
      char garbage = 0;
      int status = 0;
      PORTCbits.RC1 = 0;            //Send out opcode
      SPI2BUF = 0xD7;
      while(SPI2STATbits.SPIRBF == 0)
      {
      }
      garbage = SPI2BUF;
      SPI2BUF = 0x00;               //Receive status code
      while(SPI2STATbits.SPIRBF == 0)
      {
      }
      status = SPI2BUF;
      PORTCbits.RC1 = 1;
      return status;
}

/********************************************************/
/*                -----------------                     */
/*                |   ReadFrame   |                     */
/*                -----------------                     */
/*                                                      */
/*   Will read the data in the given page number        */
/*   from memory into the passed array. The maximum     */
/*   size of this array is FRAMESIZE. The maximum page */
/*   number that can be called is 2047.                 */
/********************************************************/

int ReadFrame(int FrameNumber, char *Frame)
{
      char garbage = 0;
      int temp = 0;
      int i = 0;

       //Frame must be shifted left by one bit to be
       //compatible with address scheme.
     FrameNumber << 1;
     PORTCbits.RC1 = 0;             //Send opcode
     SPI2BUF = 0x52;
     while(SPI2STATbits.SPIRBF == 0)
     {
     }
     garbage = SPI2BUF;
       //First 4 bits are reserved. The next 11 bits
     //are the page number bits.
     //Since the maximum frame number is 2048, the
     //highest nibble is blanked.
       //The second highest nibble is sent with these
       //zeros to give a full byte.
     temp = FrameNumber & 0x0F00;
     SPI2BUF = (char)(temp >> 8);
     while(SPI2STATbits.SPIRBF == 0)
     {
     }
     garbage = SPI2BUF;
       //The rest of the page number is sent
     SPI2BUF = (FrameNumber & 0x00FF);
     while(SPI2STATbits.SPIRBF == 0)
     {
     }
     garbage = SPI2BUF;
     //The starting byte address is 0x00
     SPI2BUF = 0x00;
     while(SPI2STATbits.SPIRBF == 0)
     {
     }
     garbage = SPI2BUF;
     //32 zeros are sent to queue in the data to be read
     for(i = 0; i <= 3; i++)
     {
           SPI2BUF = 0x00;
           while(SPI2STATbits.SPIRBF == 0)
           {
           }
           garbage = SPI2BUF;
     }
     //Read in data until framesize is met
     for(i = 0; i < FRAMESIZE; i++)
     {
           SPI2BUF = 0x00;
            while(SPI2STATbits.SPIRBF == 0)
            {
            }
            Frame[i] = SPI2BUF;
     }
     PORTCbits.RC1 = 1;
}
/********************************************************/
/*                -----------------                     */
/*                |   WriteFrame |                      */
/*                -----------------                     */
/*                                                      */
/*   Will insert the passed array into the given        */
/*   page in memory. The maximum size of this array     */
/*   is FRAMESIZE. The maximum page number that can     */
/*   be called is 2047.                                 */
/********************************************************/


int WriteFrame(int FrameNumber, char *Frame)
{
      char garbage = 0;
      int temp = 0;
      int i = 0;
      char Status = 0;

     //Frame number must be shifted left by one to be
     //compatible with address scheme.
     FrameNumber << 1;
     PORTCbits.RC1 = 0;             //Send opcode
     SPI2BUF = 0x85;
     while(SPI2STATbits.SPIRBF == 0)
     {
     }
     garbage = SPI2BUF;
       //First 4 bits are reserved. The next 11 bits
     //are the page number bits.
     //Since the maximum frame number is 2048, the
     //highest nibble is blanked.
       //The second highest nibble is sent with these
       //zeros to give a full byte.
     temp = (FrameNumber & 0x0F00);
     SPI2BUF = (char)(temp >> 8);
     while(SPI2STATbits.SPIRBF == 0)
     {
     }
     garbage = SPI2BUF;
     //Send rest of page number
     SPI2BUF = (FrameNumber & 0x00FF);
     while(SPI2STATbits.SPIRBF == 0)
     {
     }
     garbage = SPI2BUF;
     //The starting byte address is 0x00
     SPI2BUF = 0x00;
     while(SPI2STATbits.SPIRBF == 0)
     {
        }
        garbage = SPI2BUF;
        //Send each byte of the array out of the SPI
        for(i = 0; i < FRAMESIZE; i++)
        {
                 SPI2BUF = Frame[i];
               while(SPI2STATbits.SPIRBF == 0)
               {
               }
               garbage = SPI2BUF;
        }
        PORTCbits.RC1 = 1;
           //Do not release function until the flash is done
        //erasing and writing data
        do
        {
        Status = FlashStatus();
    }while((Status & 0x80) == 0);
}

10.6 interrupt.h

#ifndef _INTERRUPT_H
#define _INTERRUPT_H

#include <p30f5011.h>

#define   ON          1
#define   SET         1
#define   OFF         0
#define   CLEAR       0
#define   MAXPIXELS   100
#define   MAXSIDES    8

int captured_return();
int interval_return();

int face_return(int select);
int ontime_return(void);
char data_return(int select);
float multiplier_return(void);

void   face_set(int select, int value);
void   ontime_set(int value);
void   data_set(char select, char value);
void   global_increase_offset(int value);
void   global_decrease_offset(int value);

void intialize_offset(void);
void intialize_data(void);

#endif


10.7 interrupt.c

/********************************************************/
/*                -------------                         */
/*                |interrupt.c|                         */
/*                -------------                         */
/*                                                      */
/* Conatins the interrupt service routines, and         */
/* helper functions to modify variables                 */
/********************************************************/

#include <dsp.h>
#include "interrupt.h"
#include "audio.h"

float interval_desired = 4733.00;

//external variables from audio.c
extern fractional audio[256];
extern fractional pIN[256];
extern unsigned int audio_count;

int captured = 0;
int interval = 0;
int cycle_count = 1;

float multiplier = 0.0;
int PR4_interval = 0;
int running_total = 0x127d;
int side = 0;
int reset = 0;
int pixel = 0;
unsigned int face_start[9];
int ontime = 0x0140;
char mask[8] = {0x80,0x40,0x20,0x10,0x08,0x04,0x02,0x01};
char data[MAXPIXELS];

void _ISRFAST _T2Interrupt(void)
{
  //Timer 2 interrupt routine. Right now, this just clears the flag
and returns to program code
  IFS0bits.T2IF = 0; //Clear Timer 2 interrupt flag
} /* _T2Interrupt */


/********************************************************/
/*                --------------                        */
/*                |IC1Interrupt|                        */
/*                --------------                        */
/*                                                      */
/*    Handles the chopper event                         */
/********************************************************/

void _ISRFAST _IC1Interrupt(void)
{
  interval = IC1BUF - captured; //interval for rotation
  captured = IC1BUF;            //current timer value
  IEC0bits.T1IE = 0;            //Disable Timer 1 interrupts
  IFS0bits.T1IF = 0;   //Clear Timer 1 interrupt flag
  IEC0bits.T1IE = 1;   //Enable Timer 1 interrupt
 TMR1 = 0;              //Clear Timer

  multiplier = (float) (interval/interval_desired); //recalculate the
multiplier
  PR1 = (int) (multiplier * face_start[0]);         //Offset from
Chopper
  PR4_interval = (int) (multiplier * ontime);       //new PR4 interval,
load at Timer 1 interrupt
  running_total = (int) (multiplier * face_start[0]); //intialize the
running total
  reset = 1;                   //Set Timer 1 to reset mode
  cycle_count = 0;         //clear cycle_count used in other functions
  IFS0bits.IC1IF = CLEAR; //clear IC1 interrupt flag
}

/********************************************************/
/*                -------------                         */
/*                |T1Interrupt|                         */
/*                -------------                         */
/*                                                      */
/* Handles the Timer 1 interrupt, happens at the        */
/* beginning of the usable mirror                       */
/********************************************************/

void _ISRFAST _T1Interrupt(void)
{
  int difference = 0;

 IEC1bits.T4IE = OFF;      //Disable Timer 4 interrupts
 TMR4 = CLEAR;             //Clear Timer 4

 /*Restart Timer 4*/

 pixel = 0;
 //resets values after an inputer capture
 if(reset == 1){
   side = -1;
   PR4 = PR4_interval;
   reset = 0;}
 side++;
 //set the laser to the first data value
 PORTDbits.RD1 = (data[pixel++]&mask[side]) >> (7-side);
 //difference is the interval to the start of the next usabel mirror
 //face_starts are based on a continuous timer1
 //running total represents if the timer didn't have to reset
 difference = (int) ((multiplier * face_start[side+1])-running_total);
 PR1 = difference;
 running_total += difference;

 IFS1bits.T4IF = CLEAR; //Clear Timer 4 interrupt flag
 IEC1bits.T4IE = ON;    //Enable Timer 4 interrupts

  /*Timer 1 exit*/
  IFS0bits.T1IF = CLEAR; //Clear Timer 1 interrupt flag
} /* _T1Interrupt */
/********************************************************/
/*                -------------                         */
/*                |T4Interrupt|                         */
/*                -------------                         */
/*                                                      */
/* Handles the Timer 4 interrupts, happens at the       */
/* beginning of a new pixel                             */
/********************************************************/

void _ISRFAST _T4Interrupt(void){

 if(pixel < MAXPIXELS){
   //sets the laser to the current data value
   PORTDbits.RD1 = (data[pixel++]&mask[side]) >> (7-side);
 } else {
   //outside visible range, keep the laser off
   PORTDbits.RD1 = OFF;
 }
 IFS1bits.T4IF = CLEAR; //Clear interrupt flag
}
/********************************************************/
/* Functions to allow access to global variables in     */
/* interrupt.c                                          */
/********************************************************/

/********************************************************/
/*                -------------                         */
/*                |T5Interrupt|                         */
/*                -------------                         */
/*                                                      */
/* Handles the Timer 5 interrupts, happens every time */
/* a new sample should be recorded                      */
/********************************************************/

void _ISRFAST _T5Interrupt(void)
{
  ADCON1bits.SAMP = 1;         //start ADC sample/conversion
  while(!ADCON1bits.DONE);     //while not done with conversion
  audio[audio_count] = ADCBUF0; //grab converted value
  pIN[audio_count] = audio[audio_count++];
  IFS1bits.T5IF = 0; //clear interrupt flag
} /* _T5Interrupt */

/********************************************************/
/* Functions to initialize face offsets and the cuurent*/
/* data being displayed                                 */
/********************************************************/

void intialize_face(){
  face_start[0] = 0x0128;
  face_start[1] = 0x035C;
  face_start[2] = 0x05C4;
  face_start[3] = 0x0800;
  face_start[4] = 0x0A64;
  face_start[5] = 0x0CAE;
  face_start[6] = 0x0F02;
    face_start[7] = 0x113C;
    face_start[8] = 0x127D;
}

void intialize_data(){
  int i;
  for(i=0;i<MAXPIXELS;i++){
    data[i] = 0x00;
  }
}

/********************************************************/
/* Functions to allow return values of global variables */
/* in interrupt.c                                       */
/********************************************************/
int captured_return(){return captured;}
int interval_return(){return interval;}
int face_return(int select){return face_start[select];}
int ontime_return(){return ontime;}
char data_return(int select){return data[select];}
float multiplier_return(){return multiplier;}

/********************************************************/
/* Functions to allow changing of global variables in   */
/* interrupt.c                                          */
/********************************************************/

void face_set(int select, int value){face_start[select] = value;}
void ontime_set(int value){ontime = value;}
void data_set(char select, char value){data[select]=value;}
void global_increase_offset(int value){
  int i = 0;
  for(i=0;i<8;i++){
    face_start[i] += value;
  }
}

void global_decrease_offset(int value){
  int i = 0;
  for(i=0;i<8;i++){
    face_start[i] -= value;
  }
}



10.8 main.h

#ifndef _MAIN_H
#define _MAIN_H

#include   <p30f5011.h>
#include   <dsp.h>
#include   "startup.h"
#include   "interrupt.h"
#include   "misc.h"
#include   "spi.h"
#endif


10.9 main.c


#include "main.h"
#include "misc.h"
#include "audio.h"


/********************************************************/
/*                ------                                */
/*                |main|                                */
/*                ------                                */
/*                                                      */
/*   Main function to call the startup, and start the   */
/* busy loop in menu                                    */
/********************************************************/

int main (void)
{
  Startup ();
  uart_puts ("\n\n\n\rrestarted\n\n\n\r");
  while (1)
  {
    menu();
  }
}


10.10 menu.h

#ifndef _MENU_H
#define _MENU_H

#include <p30f5011.h>
#include "interrupt.h"

void   status(void);
void   offset_menu(void);
void   ontime_menu(void);
void   data_menu(void);
void   simple_menu(void);
void   change_message(void);
void   display_message(void);
void   motor(void);
void   menu(void);
void   modify(void);
void   restart(void);
void   motor_control_setup (void);
void   increase(void);
void   decrease(void);

#endif
10.11 menu.c

/********************************************************/
/*                --------                              */
/*                |menu.c|                              */
/*                --------                              */
/*                                                      */
/* Contains code to display menus over the UART         */
/********************************************************/


#include   "menu.h"
#include   "interrupt.h"
#include   "audio.h"
#include   "char_lookup.h"
#include   "flash.h"


extern int cycle_count; //from interrupt.c
extern char data[MAXPIXELS]; //from interrupt.c

/********************************************************/
/*                ------                                */
/*                |menu|                                */
/*                ------                                */
/*                                                      */
/* main menu displayed on the Seriel port to a          */
/* a hyperterminal, and used to debug timing and change*/
/* the text display                                     */
/********************************************************/

void menu(){
  char c;
  uart_puts("Select a menu \r\n");
  uart_puts("(1) Status\r\n");
  uart_puts("(2) Modify\r\n");
  uart_puts("(3) Audio Menu\r\n");
  uart_puts("(4) Simple Text\r\n");
  uart_puts("(m) Default setting\r\n");
  while (!U2STAbits.URXDA);
  c = (char) U2RXREG;
  switch(c){
  case '1' : {status();break;}
  case '2' : {modify();break;}
  case '3' : {audio_menu();break;}
  case '4' : {simple_menu();break;}
  case 'm' : {restart();break;}
  }
}/* menu */


/********************************************************/
/*                -------------                         */
/*                |simple_menu|                         */
/*                -------------                         */
/*                                                      */
/*     Contains the menu options for displaying text    */
/********************************************************/
void simple_menu(){
   char c;
   while(1){
     uart_puts("Simple Text Mode\r\n");
     uart_puts("(1) Change message\r\n");
     uart_puts("(2) Display message\r\n");
     uart_puts("(q) quit\r\n");
     while(!U2STAbits.URXDA);
     c = (char) U2RXREG;
     switch(c){
     case '1' :{change_message();break;}
     case '2' :{display_message();break;}
     case 'q' :{return;break;}
     }
   }
} /*simple_menu*/

/********************************************************/
/*                ----------------                      */
/*                |change_message|                      */
/*                ----------------                      */
/*                                                      */
/*   Changes the value of a message on flash            */
/*   Doesn't change the current message being display   */
/********************************************************/

void change_message(){
  unsigned char c;
  int choice = 0;
  unsigned char new_message[MAXPIXELS]= {0x00};
  int count = 0;
  int i = 0;
  int offset = 0;

 //Choose the message to edit
 uart_puts("Change which message (0-9): ");
 while(!U2STAbits.URXDA);
 c = (unsigned char) U2RXREG;
 choice = 2*(c - '0');
 uart_puti(choice);
 uart_puts("\r\n");

 //Enter in new message
 uart_puts("New Message, enter to end \r\n");
 while(!U2STAbits.URXDA);
 c = (unsigned char) U2RXREG;
 while(c != 0x0D){
   uart_putc(c);
   uart_puts(" : ");
   uart_putb(c);
   uart_puts(" : ");
   for(i=0;i<5;i++){
     new_message[count++] = char_map[(c-' ')*5+i];
     uart_putb(char_map[(c-' ')*5+i]);
     uart_putc(' ');
   }
   new_message[count++] = 0x00;
   uart_puts("\r\n");
   while(!U2STAbits.URXDA);
   c = (unsigned char) U2RXREG;
  }
  uart_putc(c);
  //Store new message
  WriteFrame(choice,new_message);
  uart_puts("\r\n");
}/*change_message*/

/********************************************************/
/*                -----------------                     */
/*                |display_message|                     */
/*                -----------------                     */
/*                                                      */
/*   Changes the current message being display to the   */
/* one selected                                         */
/********************************************************/

void display_message(){
  unsigned char c;
  int choice = 0;
  unsigned char new_message[FRAMESIZE]= {0x00};
  int i;
  int j = 0;

 //Choose the message to edit
 uart_puts("Select which message to display(0-9)\r\n");
 while(!U2STAbits.URXDA);
 c = (unsigned char) U2RXREG;
 choice = 2*(c - '0');


  //Load new message
  ReadFrame(choice,new_message);
  uart_puts("New message is: \r\n");
  while(cycle_count != 0);
  for(i=0;i<MAXPIXELS;i++){
    data[i] = new_message[i];
    uart_putb(new_message[i]);
    if(j == 5){
      j=0;
      uart_puts("\r\n");
    }else{
      j++;
      uart_putc(' ');}
  }
} /*display_message*/

/********************************************************/
/*                ---------                             */
/*                |restart|                             */
/*                ---------                             */
/*                                                      */
/*   sets a couple values to their intial state         */
/********************************************************/

void restart(){
   intialize_face();
   OC1RS = 0x0060;
}/*restart*/
/********************************************************/
/*                 --------                             */
/*                 |modify|                             */
/*                 --------                             */
/*                                                      */
/*    select the parameter that needs to be changed in  */
/* submenu
/********************************************************/

void modify(){
   char c;
   uart_puts("Select variable to modify \r\n");
   uart_puts("(1) Face Start Value \r\n");
   uart_puts("(2) Motor \r\n");
   uart_puts("(3) Laser on time \r\n");
   uart_puts("(4) Data \r\n");
   uart_puts("(5) Increase global \r\n");
   uart_puts("(6) Decrease global \r\n");
   uart_puts("(q) Quit \r\n");
   while (!U2STAbits.URXDA);
   c = (char) U2RXREG;
   switch(c){
   case '1' : {offset_menu();break;}
   case '2' : {motor();break;}
   case '3' : {ontime_menu();break;}
   case '4' : {data_menu();break;}
   case '5' : {increase();break;}
   case '6' : {decrease();break;}
   case 'q' : {return;break;}
   }
} /*modify*/
/********************************************************/
/*                 ----------                           */
/*                 |increase|                           */
/*                 ----------                           */
/*                                                      */
/*    Increases the face start values for all the sides */
/********************************************************/

void increase(){
  char c;
  int select;
  char ascii[4] = {0,0,0,0};
  int index = 0;

 uart_puts("\r\nIncrease Offset by(in HEX): ");

 while(index < 4){
   while (!U2STAbits.URXDA);
   c = (char) U2RXREG;
   uart_putc(c); //ECHO
     ascii[index++] = c;
   }
   global_increase_offset(ascii_to_hex(ascii));
   uart_puts("\r\n");
}/*increase*/

/********************************************************/
/*                 ----------                           */
/*                 |decrease|                           */
/*                 ----------                           */
/*                                                      */
/*    Decreases the face start values for all the sides */
/********************************************************/
void decrease(){
   char c;
   int select;
   char ascii[4] = {0,0,0,0};
   int index = 0;

  uart_puts("\r\nDecrease Offset by(in HEX): ");

  while(index < 4){
     while (!U2STAbits.URXDA);
     c = (char) U2RXREG;
     uart_putc(c); //ECHO
     ascii[index++] = c;
   }
   global_decrease_offset(ascii_to_hex(ascii));
   uart_puts("\r\n");
}/*decrease*/

/********************************************************/
/*                 -------------                         */
/*                 |ontime_menu|                         */
/*                 -------------                         */
/*                                                       */
/*    Changes the ontime for laser, smaller values = more*/
/* pixels, but closer together. bigger values = less     */
/* pixels but clearer display.                           */
/********************************************************/
void ontime_menu(){
   char c;
   int select;
   char ascii[4] = {0,0,0,0};
   int index = 0;


  uart_puts("Current ontime Value: ");
  uart_puti(ontime_return());
  uart_puts("\r\nNew Value(in HEX): ");

  while(index < 4){
     while (!U2STAbits.URXDA);
     c = (char) U2RXREG;
     uart_putc(c); //ECHO
     ascii[index++] = c;
   }
   ontime_set(ascii_to_hex(ascii));
   uart_puts("\r\nSet To: ");
   uart_puti(ontime_return());
   uart_puts("\r\n");
}/*ontime_menu*/

/********************************************************/
/*                 -----------                           */
/*                 |data_menu|                           */
/*                 -----------                           */
/*                                                       */
/*    Allowed changes to the data vector, used for debug */
/********************************************************/
void data_menu(){
   char c;
   int i = 0;
   int select;
   char ascii[4] = {'0','0','0','0'};
   int index = 2;


  uart_puts("Current Data: \r\n ");
  uart_puts("00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 10 11 12
13 14\n\r");
  for(i=0;i<20;i++){
    uart_putb(data_return(i));
    uart_puts(" ");
  }
  uart_puts("\r\nModify?: ");
  while(index < 4){
    while (!U2STAbits.URXDA);
    c = (char) U2RXREG;
    uart_putc(c);
    ascii[index++] = c;
  }
  uart_puts("\r\n");
  select = ascii_to_hex(ascii);
  index = 2;
  uart_puts("select: ");
  uart_puti(select);
  uart_puts("\r\nSet as:");


  while(index < 4){
     while (!U2STAbits.URXDA);
     c = (char) U2RXREG;
     uart_putc(c); //ECHO
     ascii[index++] = c;
   }
   data_set(select,ascii_to_hex(ascii));
   uart_puts("\r\nSet as: ");
   uart_putb(data_return(select));
   uart_puts("\r\n");
}/*data_menu*/

/********************************************************/
/*                -------                               */
/*                 |motor|                              */
/*                 -------                              */
/*                                                      */
/*    Changes the PWM value of the motor                */
/********************************************************/
void motor(){
   int motor = OC1RS;
   int flag = 1;
   int index = 0;
   char c;
   char ascii[4] = {0,0,0,0};

 uart_puts("Current Value: ");
 uart_puti(motor);
 uart_puts("\r\nNew Value(in HEX): ");

  while(index < 4){
     while (!U2STAbits.URXDA);
     c = (char) U2RXREG;
     uart_putc(c); //ECHO
     ascii[index++] = c;
   }
   OC1RS = ascii_to_hex(ascii);
   uart_puts("\r\nSet To: ");
   motor = OC1RS;
   uart_puti(motor);
   uart_puts("\r\n");
}/*motor*/

/********************************************************/
/*                 -------------                        */
/*                 |offset_menu|                        */
/*                 -------------                        */
/*                                                      */
/*    Allows the modification of individual face start  */
/* values.                                              */
/********************************************************/
void offset_menu(){
   char c;
   int select;
   char ascii[4] = {0,0,0,0};
   int index = 0;


 uart_puts("Select Timer face start (0-7): ");
 while (!U2STAbits.URXDA);
 c = (char) U2RXREG;
 uart_putc(c);
 uart_puts("\r\n");

 select = c - 48;
 uart_puts("Current Value: ");
 uart_puti(face_return(select));
 uart_puts("\r\nNew Value(four hex digits): ");

 while(index < 4){
   while (!U2STAbits.URXDA);
       c = (char) U2RXREG;
       uart_putc(c); //ECHO
       ascii[index++] = c;
   }
   face_set(select,ascii_to_hex(ascii));
   uart_puts("\r\nSet To: ");
   uart_puti(face_return(select));
   uart_puts("\r\n");
} /*offset_menu*/


/********************************************************/
/*                --------                              */
/*                |status|                              */
/*                --------                              */
/*                                                      */
/*   Displays the current value of some useful variables*/
/********************************************************/
void status(){
    int motor = OC1RS;
    int i = 0;

    for(i=0; i<8 ;i++){
      uart_puts("\r\nface_start[");
      uart_putc(i+48);
      uart_puts("] = ");
      uart_puti(face_return(i));
    }
    uart_puts("\r\nOntime");
    uart_puti(ontime_return());
    uart_puts("\r\n");
    uart_puts("Motor Speed : ");
    uart_puti(motor);
    uart_puts("\r\n");
    uart_puts("Interval : ");
    uart_puti(interval_return());
    uart_puts("\r\n");
    uart_puts("Multiplier * 0x100 :");
    uart_puti((int) (multiplier_return()*0x100));
    uart_puts("\r\n");
}/*status*/




10.12 misc.h

#ifndef _MISC_H
#define _MISC_H

#include <p30f5011.h>

void   uart_nputs(char *s, int i);
void   uart_puti(int i);
void   uart_putil(long int i);
void   uart_putc(char c);
char   dec_to_hex(int i);
void wait (unsigned int msec);
int ascii_to_hex(char *c);
void uart_putb (char i);

#endif

10.13 misc.c

/********************************************************/
/*                --------                              */
/*                |misc.c|                              */
/*                --------                              */
/*                                                      */
/* Contains miscellaneous code dealing with displaying */
/* text through the UART                                */
/********************************************************/

#include "misc.h"

/********************************************************/
/*                ------------                          */
/*                |uart_nputs|                          */
/*                ------------                          */
/*                                                      */
/* Used to display an array of characters, replaced     */
/* uart_puts                                            */
/********************************************************/

void uart_nputs(char *s, int i) {
  int j;

  j = 0;

  while(j < i) {
    uart_putc(s[j]);
    wait(10);
    j++;
    }

}/*uart_nputs*/

/********************************************************/
/*                 -----------                           */
/*                 |uart_putc|                           */
/*                 -----------                           */
/*                                                       */
/*    puts a character on in the transmit buffer         */
/********************************************************/
void uart_putc(char c) {
   while(U2STAbits.UTXBF);       //wait for TX buffer to be empty
   U2TXREG = c;
}/*uart_putc*/


/********************************************************/
/*                -----------                           */
/*                |uart_puts|                           */
/*                 -----------                           */
/*                                                       */
/*    Used to display a string of any length, terminiated*/
/* with the NULL character                               */
/********************************************************/
void uart_puts (char *string)
{
   //Prints string of characters passed to function from data pointer
   while (*string)
   {
     uart_putc (*string);
     string++;
   }
} /* uart_puts */


/********************************************************/
/*                -----------                           */
/*                |uart_puti|                           */
/*                -----------                           */
/*                                                      */
/*   Display an integer in an ascii representation of   */
/* a four digit hex number                              */
/********************************************************/

void uart_puti(int i) {
  int bit1;
  int bit2;
  int bit3;
  int bit4;

  bit1   =   i & 0x000f;
  bit2   =   (i & 0x00f0) >> 4;
  bit3   =   (i & 0x0f00) >> 8;
  bit4   =   (i & 0xf000) >> 12;

  uart_putc('0');
  uart_putc('x');
  uart_putc(dec_to_hex(bit4));
  uart_putc(dec_to_hex(bit3));
  uart_putc(dec_to_hex(bit2));
  uart_putc(dec_to_hex(bit1));

  return;
}/*uart_puti*/

/********************************************************/
/*                ------------                          */
/*                |uart_putil|                          */
/*                ------------                          */
/*                                                      */
/*   Display a long int                                 */
/********************************************************/

void uart_putil(long int i) {
  int bit1;
  int bit2;
 int    bit3;
 int    bit4;
 int    bit5;
 int    bit6;
 int    bit7;
 int    bit8;

 bit1    =   i & 0x0000000f;
 bit2    =   (i & 0x000000f0)   >>   4;
 bit3    =   (i & 0x00000f00)   >>   8;
 bit4    =   (i & 0x0000f000)   >>   12;
 bit5    =   (i & 0x000f0000)   >>   16;
 bit6    =   (i & 0x00f00000)   >>   20;
 bit7    =   (i & 0x0f000000)   >>   24;
 bit8    =   (i & 0xf0000000)   >>   28;

 uart_putc('0');
 uart_putc('x');
 uart_putc(dec_to_hex(bit8));
 uart_putc(dec_to_hex(bit7));
 uart_putc(dec_to_hex(bit6));
 uart_putc(dec_to_hex(bit5));
 uart_putc(dec_to_hex(bit4));
 uart_putc(dec_to_hex(bit3));
 uart_putc(dec_to_hex(bit2));
 uart_putc(dec_to_hex(bit1));

  return;
}/*uart_putil*/

/********************************************************/
/*                -----------                           */
/*                |uart_putb|                           */
/*                -----------                           */
/*                                                      */
/*   Displays a byte                                    */
/********************************************************/

void uart_putb (char i)
{
  int bit1;
  int bit2;

  bit1 = i & 0x000f;
  bit2 = (i & 0x00f0) >> 4;
  uart_putc(dec_to_hex(bit2));
  uart_putc(dec_to_hex(bit1));
}/*uart_putb*/


/********************************************************/
/*                ------------                          */
/*                |dec_to_hex|                          */
/*                ------------                          */
/*                                                      */
/*   converts an integer between 0-F and to the ASCII   */
/* representation, called by uart_putx functions        */
/********************************************************/
char dec_to_hex(int i) {
  if(i < 10 && i >= 0) {
    return (i + 48);
    }
  else if(i > 9 && i < 17) {
    return (i + 87);
    }

  return 'h';
}/*dec_to_hex*/

/********************************************************/
/*                 --------------                       */
/*                 |ascii_to_hex|                       */
/*                 --------------                       */
/*                                                      */
/*    Takes an array of four ascii characters and       */
/* converts it to the integer equivalent                */
/********************************************************/
int ascii_to_hex(char c[4]){
   int i = 0;
   int hex = 0;
   int temp = 0;

  for(i=0;i<4;i++){
    if(c[i]>47 && c[i]<58){
      temp = c[i] - 48;
    }
    else if(c[i]>64 && c[i]<71){
      temp = c[i] - 55;
    }
    else if(c[i]>96 && c[i]<103){
      temp = c[i] - 87;
    }
    else{i = 0;}
    hex = hex | temp << (4*(3-i));
  }
  return hex;
}/*ascii_to_hex*/



/********************************************************/
/*                 ------                               */
/*                 |wait|                               */
/*                 ------                               */
/*                                                      */
/*    A simple wait loop, used mainly in debugging for  */
/* long delay periods                                   */
/********************************************************/
void wait (unsigned int msec)
{
   //waits msec milliseconds
   unsigned int i;
   unsigned int j;
  for (i = 0; i < msec; i++)
  {
    for(j = 0; j< 1000; j++){
      asm ("nop");
      asm ("nop");
      asm ("nop");
    }
  }
} /* wait */


/********************************************************/
/*                ------                                */
/*                |itoa|                                */
/*                ------                                */
/*                                                      */
/*   converts an integer to its ASCII equivalent        */
/********************************************************/
char *itoa (int i, char buffer[12])
{
     char *back;

     back = buffer + 11;
     *back = 0;
     do {
          *--back = i % 10 + '0';
          i /= 10;
     } while (i);
     return back;
}/*itoa*/


10.14 startup.h

#ifndef _STARTUP_H
#define _STARTUP_H

#include <p30f5011.h>
#include "interrupt.h"
#include "FftFunct.h"

void   Startup();
void   Startup_PWM();
void   Startup_SPI();
void   Startup_UART();
void   Startup_FLASH();
void   Startup_ADC();
void   Startup_Chopper();
void   Startup_LAZER();
void   Startup_TMR5 (void);

#endif

10.15 startup.c


/********************************************************/
/*                -----------                           */
/*                |Startup.c|                           */
/*                -----------                           */
/*                                                      */
/*   Contains the startup code for the modules used in */
/* the project                                          */
/********************************************************/



#include "startup.h"

/********************************************************/
/*                ---------                             */
/*                |Startup|                             */
/*                ---------                             */
/*                                                      */
/*   Calls all the startup subroutines, allows for easy */
/* disabling of modules                                 */
/********************************************************/

void Startup (void)
{
  Startup_SPI ();         //Setup SPI
  Startup_UART();         //Setup UART
  Startup_FLASH();        //Setup FLASH
  Startup_PWM ();         //Setup PWM - do this before chopper
  Startup_ADC ();         //Configure the ADC
  Startup_Chopper();      //Setup Input Capture
  Startup_LAZER();
  Startup_TMR5 ();        //Sets up timer 5

} /* SetupRegisters */
******************/

void Startup_PWM (){

  OC1CON = 0;          //Clear Output Compare 1 Module
  OC1RS = 0x0060;      //0x0054 //Write duty cycle to buffer register
  OC1R = 0x0060;       //Write initial duty cycle value
  OC1CON = 0x0006;     //Load Output Compare 1 Module with the compare
mode
  PR2 = 0x00BF;        //Set timer interrupt value
  IPC1bits.T2IP = 1;   //Set Timer 2 priority value
  IFS0bits.T2IF = 0;   //Clear Timer 2 interrupt flag
  IEC0bits.T2IE = 1;   //Enable Timer 2 interrupt
  T2CONbits.TON = 1;   //Start Timer 2 with assumed settings
} /* Setup_PWM */

/********************************************************/
/*                ------------                          */
/*                |Statup_SPI|                          */
/*                ------------                          */
/*                                                      */
/*   Intializes SPI2                                    */
/********************************************************/
void Startup_SPI() {
    SPI2CONbits.CKE = 0;         //clock edge select bit
    SPI2CONbits.CKP = 1;         //clock polarity select bit
    SPI2CONbits.SMP = 0;         //data is sampled at middle of frame
    SPI2CONbits.MSTEN = 1;       //master mode enable bit
    SPI2CONbits.SPRE = 0b110;    //secondary prescale
    SPI2CONbits.PPRE = 0b01;     //primary prescale
    SPI2STATbits.SPIROV = 0;     //Clear overflow flag
    SPI2STATbits.SPIEN = 1;      //enable SPI number two

    }

/********************************************************/
/*                --------------                        */
/*                |Startup_UART|                        */
/*                --------------                        */
/*                                                      */
/*   Initializes UART2                                   */
/********************************************************/
void Startup_UART(){

    U2BRG = 15;   //set baudrate 9600 = 64
    U2STA = 0;           //clear
    U2MODE = 0x8000;    //Enable UART for 8-bit data, no parity
                        //no parity, 1 STOP bit, no wakeup
    U2STAbits.UTXEN = 1; //Enable TX
}

/********************************************************/
/*                ---------------                       */
/*                |Startup_Flash|                       */
/*                ---------------                       */
/*                                                      */
/*   Initialize ports used for SPI flash                */
/********************************************************/
void Startup_FLASH(void) {

    TRISC = 0xFFFD;   //Enable F_CS
    TRISG = 0x5FFF;   //Enable F_WP and F_RST
    PORTG = 0xA000;

    PORTCbits.RC1 = 1;    //clear F_CS (Active LOW)

}


/********************************************************/
/*                 -------------                          */
/*                 |Startup_ADC|                          */
/*                 -------------                          */
/*                                                         */
/*    Initializes the analog to digital converter         */
/********************************************************/
void Startup_ADC (void)
{
   //Setup the analog to digital converter
   ADCON1bits.ADSIDL = 1;      //discontinue in idle mode
   ADCON1bits.FORM = 0b10;     //output data form:fractional, duh!
     ADCON1bits.SSRC = 0b111;      //conversion trigger source select
     ADCON1bits.ASAM = 0;          //automatic sampling enable

     ADCON2bits.VCFG = 0b000;      //voltage reference configuration bits
     ADCON2bits.CSCNA = 0;         //do/don't scan inputs
     ADCON2bits.SMPI = 0b0000;     //sample/convert sequences per interrupt
     ADCON2bits.BUFM = 0;          //buffer mode select
     ADCON2bits.ALTS = 0;          //alternate input sample mode

  ADCON3bits.SAMC = 0b00011; //auto sample time bits
  ADCON3bits.ADRC = 0;        //ADC conversion clock source bit
(0=system clock, 1=internal RC)
  ADCON3bits.ADCS = 0b000111; //ADC conversion clock select bits

  ADCHS = 0x0000;             //ADC input select register
  ADPCFGbits.PCFG0 = 0;       //Configure individual pins as
analog/digital (1=digital, 0=analog)
  ADCSSL = 0x0000;            //ADC input scan select register

  ADCON1bits.ADON = 1;             //enable ADC
} /* Startup_ADC */


/********************************************************/
/*                -----------------                     */
/*                |Startup_Chopper|                     */
/*                -----------------                     */
/*                                                      */
/*   Initializes the Input Capture values, which are    */
/* triggered on a chopper event                         */
/********************************************************/
void Startup_Chopper(){

     IPC0bits.IC1IP = 1;     //Set Priority for IC1
     IFS0bits.IC1IF = 0;    //Clear interrupt flag
     IEC0bits.IC1IE = 1;    //Enable interrupts
     IC1CON = 0;            //Clear IC1CON
     IC1CON = 0x0003;       //Set prescaler mode
     IEC0bits.T3IE = 0;     //disable Timer 3 interrupt
     T3CONbits.TCKPS = 3;   //Timer Prescale bits: 1:256
     T3CONbits.TCS = 0;     //Time Clock Source:    Internal
     T3CONbits.TON = 1;     //Start Timer 3 with assumed settings

 }

/********************************************************/
/*                ---------------                       */
/*                |Startup_LAZER|                       */
/*                ---------------                       */
/*                                                      */
/*   Intialize the port used for the laser,             */
/*             Timer 1, and                             */
/*             Timer 4                                  */
/********************************************************/
void Startup_LAZER(){

     intialize_face();
    intialize_data();
    TRISD = 0xFFFD;      //Enable Lazer pin for output
    PORTDbits.RD1 = 0;   //Turn the lazer off
    /*For chopper offset*/
    PR1 = 0x0001;
    T1CONbits.TCKPS = 2; //Timer Prescale bit: 1:64
    T1CONbits.TCS = 0;   //Timer Clock Source: Internal
    IPC0bits.T1IP = 1;   //Set Timer 1 priority value
    IEC0bits.T1IE = 0;   //Disable Timer 1 interrupts
    T1CONbits.TON = 1;   //Turn Timer 1 on
    //Timer1 will be enabled on a chopper interrupt

    /*For the actual laser*/
    PR4 = 0x0001;
    T4CONbits.TCKPS = 0; //Timer Prescale bit: 1:1
    T4CONbits.TCS = 0;    //Timer Clock source: Internal
    IPC5bits.T4IP = 1;    //Set Timer 4 priority value
    IEC1bits.T4IE = 0;    //Disable Timer 4 interrupts
    T4CONbits.TON = 1;    //Turn Timer 4 on
    //Timer 4 will be enabled on a Timer 1 interrupt

}

/********************************************************/
/*                 -------------                         */
/*                 |Startup_TM5|                         */
/*                 -------------                         */
/*                                                       */
/*    Initializes Timer 5 settings, used for sample      */
/* period for the ADC                                    */
/********************************************************/
  void Startup_TMR5 (void)
{
   //Start timer five
   T5CONbits.TCKPS = 0b00;   //prescale value (0b11: 256, 0b10: 64,
0b01: 8, 0b00: 1)
   T5CONbits.TCS = 0;        //clock source select (0 = internal, 1 =
external clock)
   T5CONbits.TON = 1;        //enable timer five
   PR5 = 500;                //compare value

  IPC5bits.T5IP =   2;       //timer 5 interrupt priority level
  IFS1bits.T5IF =   0;       //clear timer 5 interrupt flag
  IEC1bits.T5IE =   0;       //timer 5 interrupt enable
} /* Startup_TMR5   */

								
To top