
Interface between the mbed lpc1768 and the ads1298
Diff: main.cpp
- Revision:
- 0:bd3a560e245e
- Child:
- 1:26b8b0e4d836
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/main.cpp Thu Apr 10 06:44:02 2014 +0000 @@ -0,0 +1,571 @@ +/********************************************************************************************************************************** +*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); + //} + // } + + test.num_channels = 3; + test.gain = 6; + test.lpf_cutoff = 1000; + test.mfs = 1; + test.ttl_freq = 500; + test.freq_s = 5; + +} + +/*********************************************************************************************************************************************** + 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; + } + \ No newline at end of file