Interface between the mbed lpc1768 and the ads1298

Dependencies:   USBDevice mbed

main.cpp

Committer:
faithcerebral
Date:
2014-04-14
Revision:
1:26b8b0e4d836
Parent:
0:bd3a560e245e

File content as of revision 1:26b8b0e4d836:

/**********************************************************************************************************************************
*changed the ISR function 
*incuded 0x02 to make sure that 24 buts are sent
****************************************************************************************************************************************/
// include files
#include "mbed.h"
#include "ADS1x9x.h"
#include "stdef.h"
#pragma diag_suppress 177  //suppress unused declared entities

/*******************************************************************************************************************************************
                                        Definitions
 ********************************************************************************************************************************************/
#define ADS1298_DATA_LENGTH 27
#define STAND_BY_MODE 0x04
#define REGISTER_DEFAULT_SETTINGS 0x00
#define WAIT_CCSSC 0.000000007 //wait 7ns
#define WAIT_CSH 0.000001 //wait 2 clock cycles
#define WAIT_DSHD 0.00008 //wait 16 clock cycles
#define WAIT_RST  0.000009//wait 18 clock cycles
#define wait_time 0.000004  //8th sclk falling edge
#define wait_time2 0.000012 //wait 24clock cycles
#define buffer_size 100      // size of data buffers 

/***********************************************************************************************************************************************
                                           Pin Allocations
 ***********************************************************************************************************************************************/
DigitalOut myled(LED1);
Timer timer1;
SPI spi(p5,p6,p7);  // Initialisng variables mosi, miso,sclk,chip select
DigitalOut cs(p8);           //Chip select
DigitalOut out(p18);           // To  Oscillioscope
InterruptIn DRDY(p22);           //Interrupt signal
DigitalOut Start(p23);
DigitalOut PWDN (p24);
DigitalOut CLKSEL(p25);
DigitalOut Reset(p26);
DigitalOut CS_START(p27);


Serial pc(USBTX, USBRX); //tx,rx
PwmOut pw(p21);

/***********************************************************************************************************************************************
                                                STRUCTURES
*************************************************************************************************************************************************/
// info from pc
typedef struct {
        int resolution;             //resolution of adc
        volatile char data_out1[9]; //msb
        volatile char data_out2[9];//middle byte
        volatile char data_out3[9];//lsb
        int ttl_freq;
        int gain;             //duty cycle of pulse generation.
        int RLD;                    //right leg drive
        int test_duration;
        int num_channels;
        int count;
        int lpf_cutoff;
        int mfs;// value either 1 or 0 representing if a ganzfeld or multifocal system(mfs) is used
        int mfs_frequency; //frequency of mfs simulator 
        int ganzfeld_frequency; //frequency of ganzfeld simulator
        int freq_s;

}data;

data test;

/**************************************************************************************************************************************************
*                                 Global Variables                                                                                                *
**************************************************************************************************************************************************/
unsigned char ADS1x9x_SPI_data;
signed char ADS1x9x_Data [ADS1298_DATA_LENGTH];
float buffer_1[buffer_size] = {0};
float buffer_2[buffer_size] = {0};
unsigned char device_slot;

/************************************************************************************************************************************************
                                Function prototypes
 **********************************************************************************************************************************************/
void pulse_generation(int mfs, int ganzfeld_frequency, int mfs_frequency );
void Initialize_ADS1x9x_Mode(void);
void spi_initialise(void);
void file_system(void);
void read_data(void);
void test_info(void);
 int Initialize_ADS1x9x_Channel (void);
void lpf_coef(void);
float lpf( float coeff[5], float);
void ISR1();
void read(void);


/**************************************************************************************************************************************************
                                                MAIN PROGRAM 
***************************************************************************************************************************************************/
int main() {
    
    pc.baud(14400);
    int system_pause = 1;
    int device_slot = 1;
    
    DRDY.fall(&ISR1);
    
    test_info(); 
    // calculate the low pass filter coeficeints
    lpf_coef(); 
    wait(0.1);
    
    cs = LOW;
    
    CS_START =LOW;
    wait(WAIT_CCSSC);
    
    pc.printf("Initialising");
      spi_initialise();
      cs = LOW;
      wait(0.1);
      
      Reset = 1;            //introduced this
      wait(wait_time);
      Reset = 0;
      
       pc.printf("Waking up adc from sleep ");
     spi.write(WAKE_CONVERTER_FROM_SLEEP); //power up adc
     wait(1);
    
      
      spi.write(RESET_CONVERTER); //reset
      wait(WAIT_RST);
   
      CLKSEL = 1; //use internal clock
       wait(wait_time);
       
       PWDN = 1; 
       Reset = 1;
       wait(1.5);
      // Reset = 0; //not sure about this bit.
      // wait(WAIT_RST);
       
       spi.write(RESET_CONVERTER); //reset
       wait(WAIT_RST);
    pc.printf("Converter has been reset\n");
          
       read(); //read config registers
        wait(wait_time);
       
    spi.write(WRITE_CONFIG_3_REGISTER);
    wait(wait_time);
    spi.write(SINGLE_BYTE_READ_WRITE);
    wait(wait_time);
    spi.write(INTERNAL_REF);
    
              
       //setup config registers
       Initialize_ADS1x9x_Mode(); //config 1,2,3,4
       
       test.num_channels = Initialize_ADS1x9x_Channel();
       
       //initialise gpio
    init_ADS1x9x_IO (device_slot);
      wait(wait_time);
      
      pc.printf("Reading the config settings");
            
       read();
        wait(0.0001);
              
              
        Start = LOW;
        wait(WAIT_CSH);
          
        spi.write(START_RESTART_CONVERSION);
        wait(WAIT_DSHD);
        
      spi.write(SET_READ_DATA_CONTINUOUSLY );
      wait(wait_time);
      
     
             
    system_pause = pc.scanf("%d\n",&system_pause); //wait for start command
    timer1.start(); 
    
    while(timer1.read() < 200){    //Ensure that the test runs for 2 minute only 
     
              //check for pause before continuing
        system_pause = 1;
        if (system_pause == 0)
        {
            while(system_pause == 0)
            {
            system_pause = pc.scanf("%d\n",&system_pause);
            
             }
        }
        
        else
        {
          pulse_generation(test.mfs, test.ganzfeld_frequency,test.mfs_frequency);  //5 is just an arbitrary value selected so that the code runs, to use adc speed  
         
         int a = test.count - 1;
     
        __disable_irq();
         if (test.count > a) //prevents the same data being repeatedly sent since the adc is slower than the mcu
         {
          //include lpf
         // test.data_out = lpf(test.data_out) 
       //  read2();
         for (int i = 0; i <= (test.num_channels +1);i++){
          
               //pc.printf("\n");             
          pc.printf("%02x%02x%02x\n",test.data_out1[i], test.data_out2[i],test.data_out3[i]); 
          }  
                  
           }
          
           
           else 
               {
               wait(0.000000000001); //momentary pause 
               
            }
           __enable_irq ();
                                         
        }
          }
         Start = LOW; //stop conversion
         wait(WAIT_DSHD);
        // spi.write(0x0A);
    spi.write( STOP_READ_DATA_CONTINUOUSLY );
    wait(wait_time );
    spi.write(STAND_BY_MODE);        //Enter standby mode
  timer1.stop();
 wait(WAIT_CSH);
  cs = HIGH;
     return 1;
 }
/**********************************************************************************************************************************************
                                            TEST INFORMATION
**********************************************************************************************************************************************/
void test_info(void){
   LocalFileSystem local("local");               // Create the local filesystem under the name "local"
    //open text file 
       FILE *fp = fopen("/local/out.txt", "r");  // Open "out.txt" on the local file system for reading
         
          if (fp == NULL){
            myled = 1;
           }
        else {
        while (!feof(fp)){
              
        fscanf(fp,"%d\n",&test.num_channels);
        fscanf(fp,"%d\n",&test.gain); 
        fscanf(fp,"%d\n",&test.ttl_freq); //specify frequency of test
        fscanf(fp,"%d\n",&test.mfs);//specify if multifocal or erg test
    }
        }   
       
    
}

/***********************************************************************************************************************************************
                                        PUSLE GENERATION
 ***********************************************************************************************************************************************/
void pulse_generation(int mfs, int ganzfeld_frequency, int mfs_frequency ){

PwmOut pw(p21);
float duty_cycle;

static double period;
 //Enable ganzfeld synchronising pulse
// pc.printf("Using a Ganzfeld(0) or Mfs(1)?"); //mfs=>multifocal system 
        switch(test.mfs)
        {
            case 0:
                    { //ganzfeld
                        period = 1/test.ttl_freq;
                        pw.period(period); 
                        pw = 0.5;
                    }   
            case 1: //mf case sends pulse at the operating frequency of the adc
                    {
                       pw.period(0.0010);
                        pw = 0.5; //duty cycle of 50% , a perfect square wave                  
                        
                    }
        }

}
/************************************************************************************************************************************************
                                            SPI INTERFACE
*************************************************************************************************************************************************/

void spi_initialise(void){
           
    spi.format(8,1);       //configuring the transmission of data and mode 1
    spi.frequency(2000000);  //spi  clock frequency to 2Mhz
             return; 
}


 /**********************************************************************************************************************************
                                         INITIALISE ADS I/O
  **********************************************************************************************************************************/
  void init_ADS1x9x_IO (unsigned char){
 //right now, not using any input or output pins
 //setting all GPIO to output mode and connecting them to ground
 
 spi.write(WRITE_GENERAL_PORT_IO);  //write the command to the GPIO register
 wait(wait_time);
 spi.write(SINGLE_BYTE_READ_WRITE);
 wait(wait_time);
 spi.write(REGISTER_DEFAULT_SETTINGS);  //Turn all general purpose inputs and outputs off
 wait(wait_time);
 //pc.printf("GPIO initialisation complete\n");
 return;
  }
    
 /*************************************************************************************************************************************
                                        INITIALISE ADS MODE
  **************************************************************************************************************************************/
  //Data rate configured
  void Initialize_ADS1x9x_Mode() {
       
    wait(WAIT_DSHD);
    spi.write(WRITE_CONFIG_1_REGISTER);      //Write to config1
    wait(WAIT_DSHD);
    spi.write(SINGLE_BYTE_READ_WRITE);       //Second byte of WReg
    wait(WAIT_DSHD);
    switch(test.freq_s)
    {
        case 0:
                spi.write(THIRTY_TWO_KSPS_SAMPLING_FREQ);        //use command 0xC0 to use external clock
                test.freq_s = 32000;
        case 1:
                spi.write(SIXTEEN_KSPS_SAMPLING_FREQ);
                test.freq_s = 16000;
        case 2:
                spi.write(EIGHT_KSPS_SAMPLING_FREQ);
                test.freq_s = 8000;
        case 3:
                spi.write(FOUR_KSPS_SAMPLING_FREQ);
                test.freq_s  = 4000;
        case 4: 
                spi.write(TWO_KSPS_SAMPLING_FREQ);
                test.freq_s = 2000;
        case 5:
                spi.write(ONE_KSPS_SAMPLING_FREQ);
                pc.printf("\n1k sampling rate\n");
                test.freq_s = 1000;
         case 6:
                spi.write(FIVE_SPS_SAMPLING_FREQ);
                test.freq_s = 500;
    }
    wait(0.00002);
           
        pc.printf("Config 1 value\n");
        volatile char d = spi.write(FETCH_DATA);
        wait(wait_time2);
        pc.printf("%X",d);
    
     
    spi.write(WRITE_CONFIG_2_REGISTER );           //Write to CONFIG 2
    wait(wait_time);
    spi.write(SINGLE_BYTE_READ_WRITE);
    wait(wait_time);
    spi.write(REGISTER_DEFAULT_SETTINGS);            //configures the test signal generation
    
    wait(wait_time);
    spi.write(WRITE_CONFIG_3_REGISTER);      //Write to CONFIG 3
    wait(wait_time);
    spi.write(SINGLE_BYTE_READ_WRITE);
    wait(wait_time);
    spi.write(INTERNAL_REF);                //Configures multireference and enables internal reference buffer
    wait(0.01);
    
    //CONFIG4
    
    spi.write(WRITE_CONFIG_4_REGISTER );
    wait(wait_time);
    spi.write(SINGLE_BYTE_READ_WRITE);
    wait(wait_time);
    spi.write(REGISTER_DEFAULT_SETTINGS); //set adc in continous mode and respiration modulatiion frequency at 64khz
    wait(0.00001);
    
    //pc.printf("Configuration complete"); 
  return ;
 
 }
/*****************************************************************************************************************************
                                               INITIALISE ADS CHANNEL
 ******************************************************************************************************************************/
 int Initialize_ADS1x9x_Channel (void){
     
    int i,j;
 
 spi.write( WRITE_CHANNEL_1_SET_REGISTER);   //Start at channel register 1
 wait(WAIT_DSHD);
spi.write(EIGHT_BYTE_READ_WRITE); //write 8 channels
wait(WAIT_DSHD);
 switch(test.gain)
 {
     case 1:
             for ( i = 0; i <= test.num_channels; i++)
                {
                     spi.write(GAIN_ONE); //turn on channels
                     wait(WAIT_DSHD);
                }
    case 2:
            for ( i = 0;i <= test.num_channels ;i++)
                {
                     spi.write(GAIN_TWO); //turn on channels
                     wait(WAIT_DSHD);
                }        
    case 3:
            for ( i = 1; i <= test.num_channels ;i++)
                {
                     spi.write(GAIN_THREE); //turn on channels
                     wait(WAIT_DSHD);
                }
    case 4:
            for (i = 1; i <= test.num_channels; i++)
                {
                     spi.write(GAIN_FOUR); //turn on channels
                     
                     wait(WAIT_DSHD);
                }
        case 6:
                for (i = 1; i <= test.num_channels; i++)
            {
                 spi.write(GAIN_SIX); //turn on channels
                 wait(WAIT_DSHD);
                 pc.printf("gain of 6");
            }
    case 8:
                for ( i = 0; i <= test.num_channels ; i++)
            {
                 spi.write(GAIN_EIGHT); //turn on channels
                 wait(WAIT_DSHD);
            }
    case 12:
            for (i = 0; i <= test.num_channels ;i++)
                {
                     spi.write(GAIN_TWELVE); //turn on channels
                     wait(WAIT_DSHD);
                }
        
     }//switch case bracket
     
     wait(WAIT_DSHD);
  for (j = 1; j <= (8 - test.num_channels); j++)
  {
       spi.write(INPUT_SHORT); // turn off channels
       wait(WAIT_DSHD);  
       pc.printf("turning off channels\n") ;    
 }
  wait(wait_time);

 //pc.printf("ADC channels initiaslise\n");
 return test.num_channels;
 //Configure right leg drive
 }
 
 /*******************************************************************************************************************************************
                                      Low pass filter_coefficents
The low pass filter uses a 3rd Order butterworth filter to have a 40db attenuation 
This function calculates the coeffients to be used for the low pass filter 
inputs:sampling frequency, cut off frequency
outputs:a pointer to an  array with all the coeffiecents.
 ********************************************************************************************************************************************/
 void lpf_coef(void){
 //calculate prewarped coeficients 
 static float wp;   //the prewarped frequencies
 static float coeff[5] = {0};
 float pi = 3.14159265359;
 static float a;
static float b;
static float* coeff_pointer;
  
  a = 0.5*wp*wp;
  b = 0.5*wp*wp*wp;
  
 //user inputs the desired cut off frequency 
  //pc.printf("enter the desired cut off frequency:");
 
 wp = tan((2*pi *test.lpf_cutoff)/2*test.freq_s);  //prewarped frequency

 coeff[0] = (-1 + wp - a + b)/wp;
 coeff[1] = (3 -wp -a+3*b)/wp;
 coeff[2] = (-3 -wp +3*a +3*b)/wp;
 coeff[3] = (1 + wp + a + b);
 coeff[4] = wp;
 }
 
 /*******************************************************************************************************************************************
                                            Low pass filter
   ******************************************************************************************************************************************/
   float lpf( float coeff[5], float lpf_in){
      
   static float lpf_out;
    float y[4];
    float x[4];
    
     
    x[0] = lpf_in;
    //moving x and y values by one sample
     x[3] = x[2]; x[2] = x[1]; x[1] = x[0];

     y[3] = y[2]; y[2] = y[1]; y[1] = y[0]; 
    
    //the output is given by:
    y[0] = (coeff[3]*x[0])+(coeff[2]*x[1])+ (coeff[1]*x[2])+(coeff[0]*x[3]) + (3*y[1])+(3*y[2])+(y[3]);
    
    lpf_out = y[0];
    
    return lpf_out;
    
    }
          
     /***************************
     read the ads channels*/
     void read(void){
         int a;
         int b;
         volatile int c;
         
        
       spi.write(STOP_READ_DATA_CONTINUOUSLY); //disable conversions to read registers
          wait(WAIT_DSHD); 
        
         spi.write(READ_DEVICE_ID ); //start reading at register 0
         wait(wait_time2);
         spi.write(EIGHT_BYTE_READ_WRITE); //read 8 registers
         //spi.write(0x06);
           wait(WAIT_DSHD );
         for (c=1; c<=8; c++){
             a = spi.write(FETCH_DATA); //send dummy variable to get data
             wait(WAIT_DSHD);
             pc.printf("%x\n",a);
             
            }
         wait(wait_time);
                 
         }
         /*********************************************************
         Interrupt from the DRDY to rad the data from the adc
         ************************************************************/
         void ISR1(){
             //call function read data
                myled = !myled;
             
            
             for(int i = 0; i <= (test.num_channels+1); i++)
             {
              //try changing to wait_time
              wait(wait_time);
              test.data_out1[i] = spi.write(FETCH_DATA); //send the dummy variable to recieve the data.
              wait(wait_time);
              test.data_out2[i] = spi.write(FETCH_DATA); 
               wait(wait_time);
              test.data_out3[i] = spi.write(FETCH_DATA);
               wait(wait_time);
              }
                         
             test.count = test.count +1;            
             }