
Interface between the mbed lpc1768 and the ads1298
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; }