Chirp Signal Generator

Dependencies:   mbed

Fork of TAU_ZOOLOG_Playback_Rev1_1 by Yossi_Students

main.cpp

Committer:
TauZoolog
Date:
2015-12-06
Revision:
1:0b510109a099
Parent:
0:e239fd599412
Child:
2:1d99e9b70f0d

File content as of revision 1:0b510109a099:

/*
Digital Filter Implementation: arkadiraf@gmail.com 21/10/2015
ADC --> Filter --> DAC , Based on NUCLEO - F303RE

Pinout:
ADC -- PA_0 -- A0
DAC -- PA_4 -- A2

I/O -- PA_5 -- D13 (Status LED, Condition)
I/O -- PA_6 -- D12 (Toggle Pin, Loop Freq)
I/O -- PA_7 -- D11 (General Output Pin   )

Loop Running at up to 1 MHz, depending on filter lenght.
250 proccessor operations at 250 kHz
Make sure to use float variables in filter (Not double!).
*/
#include "mbed.h"
// mbed variables, Settings
AnalogOut my_output(PA_4);
AnalogIn my_input(PA_0);
DigitalOut myled(PA_5);
DigitalOut mytoggle(PA_6);
DigitalOut mytrigger(PA_7);

// Low level declerations
ADC_HandleTypeDef hadc1;
DAC_HandleTypeDef hdac1;

// initialize low level dac, adc
static void MX_ADC1_Init(void);
static void MX_DAC1_Init(void);

// declare filter
inline float FilterFloat(float Variable);
// declare output filter
inline float OutputFilterFloat(float Variable);
// declare first filter
inline float FirstFilterFloat(float Variable);
// declare second filter
inline float SecondFilterFloat(float Variable);
//nadav - declare simple filter
inline float simpleFilterFloat(float Variable);

// Variables
uint16_t ADCValue=0;
float ADCFloat=0;
float OutputADCFloat=0;
//amplitude scale is normalized such that 1 equals 3.3V, -1 equals 0V, and 0 equals 3.3/2V
float ADC2Float=(2.0f/4095.0f); //ADCvalue*(2/0xFFF)-1.0f // 12 bits range
float Float2ADC=(4095.0f/2.0f); //(ADCvalue+1.0f)*(0xFFF/2) // 12 bits range


bool PinD11_state=0;
bool PinD12_state=0;
bool PinD13_state=0;

////////////////////////////////////////////////////////////////////////////////////////////////////
//// Define Your Variables ////////////////////////////////////////////// Define Your Variables ////
////////////////////////////////////////////////////////////////////////////////////////////////////

float example=0.0f; // example

//nadav - Simple First order filter
//get this from matlab script "simple_SimpleFilterExample.m"
//float ALPF=0.152641; 
//float AHPF=0.999815; 
//float AHPF=0.999815; //10Hz cut off fs=340
//float AHPF=0.574978; //40KHz cut off fs=340
//float AHPF=0.782963; //15KHz cut off fs=340
//float AHPF=0.844025; //10KHz cut off fs=340
//float AHPF=0.871202; //8KHz cut off fs=340
//float AHPF=0.915416;  //5KHz cut off fs=340
//float AHPF=0.900187; //6KHz cut off fs=340
//float AHPF=0.885458; //7KHz cut off fs=340
//float AHPF=0.931168; //8KHz cut off fs=340*2
float AHPF=0.999128; //100Hz cut off fs=340*2
float SOSMat[6]= { 1.000000, -1.970399, 1.000000, 1.000000, -1.942826, 0.946079}; 
float Gscale=0.097947; 
//nrackoz ydagon hpf
float SOSMat_H[6]= { 1.000000, -2.000000, 1.000000, 1.000000, -1.949235, 0.950492}; 
float Gscale_H=0.974932; 
//nrakocz ydagon - simple filter variables
//float AHPF=0.730141;
//filter 1 bus
float LLastY=0;
float LastY=0;
float CurY=0;
float LLastU=0;
float LastU=0;
float CurU=0;
//filter 2 bus
float LLastY_H=0;
float LastY_H=0;
float CurY_H=0;
float LLastU_H=0;
float LastU_H=0;
float CurU_H=0;


////////////////////////////////////////////////////////////////////////////////////////////////////
//// Define Your Variables ////////////////////////////////////////////// Define Your Variables ////
////////////////////////////////////////////////////////////////////////////////////////////////////




// Main code
int main()
{
    // System Clock Configuration  (Peripherial clocks)
    RCC_PeriphCLKInitTypeDef PeriphClkInit;
    PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_ADC12;
    PeriphClkInit.Adc12ClockSelection = RCC_ADC12PLLCLK_DIV1;
    HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit);

    MX_ADC1_Init();
    MX_DAC1_Init();

    HAL_DAC_SetValue(&hdac1, DAC_CHANNEL_1, DAC_ALIGN_12B_R, 0x000);
    HAL_DAC_Start(&hdac1, DAC_CHANNEL_1);

    HAL_ADC_Start(&hadc1);
    
    // more direct method to setting DAC value`s
    //define Dac Register.
    __IO uint32_t Dac_Reg = 0;
    Dac_Reg = (uint32_t) (hdac1.Instance);
    Dac_Reg += __HAL_DHR12R1_ALIGNEMENT(DAC_ALIGN_12B_R);
    
      /* Set the DAC channel1 selected data holding register */
    *(__IO uint32_t *) Dac_Reg = ADCValue;
    
    // more direct method to reading ADC value's:
    /* Clear regular group conversion flag */
    
    //__HAL_ADC_CLEAR_FLAG(&hadc1, (ADC_FLAG_EOC | ADC_FLAG_EOS) );
  
    /* Return ADC converted value */ 
    //ADCValue=(uint16_t)(hadc1.Instance->DR);
  
    // Infinite loop
    
    // ADC to float convertion and back.
    
    while(1) {
        // more direct method to reading ADC value's:
        /* Return ADC converted value */
        ADCValue=(uint16_t)(hadc1.Instance->DR);
        
        // read ADC value ,  Alternative more slow method
        //ADCValue=HAL_ADC_GetValue(&hadc1);
        
        // convert to float for filter
        //amplitude scale is normalized such that 1 equals 3.3V -1 euqales 0V, and 0 equales 3.3/2V
        ADCFloat=((float)ADCValue * ADC2Float)-1.0f;
        
        // toggle pin, Loop frequency indicator
        PinD12_state=!PinD12_state;
        if (PinD12_state) {GPIOA->BSRRL = GPIO_PIN_6;}else{GPIOA->BSRRH = GPIO_PIN_6;}
        
        ////////////////////////////////////////////////////////////////////////////////////////////////////
        //// Change Code from here ////////////////////////////////////////////// Change Code from here ////
        ////////////////////////////////////////////////////////////////////////////////////////////////////
        
        //////////////////////////////////////////////////////
        // Apply Filter to reading before further processing//
        //////////////////////////////////////////////////////
        
        ADCFloat=simpleFilterFloat(ADCFloat); //nadav - filtering input
        
        ADCFloat=FirstFilterFloat(ADCFloat);
        ADCFloat=SecondFilterFloat(ADCFloat);
        
        ////////////////////////////
        // Apply Filter to Output //
        ////////////////////////////
        
        OutputADCFloat=OutputFilterFloat(ADCFloat); 
        
        // Set Condition of Pin D13 (LED2) Status
        if (ADCFloat>0.5f){ 
            GPIOA->BSRRL = GPIO_PIN_5; 
        }else{
            GPIOA->BSRRH = GPIO_PIN_5;
        }
        
        ///////////////////////////////////////////////////////////////////////////////////////////////////
        //// Change Code Up To Here /////////////////////////////////////////// Change Code Up To Here ////
        ///////////////////////////////////////////////////////////////////////////////////////////////////
        
        
        // Apply limits to max dac values [0..1]
        // Convert filtered data back to uint16_t, 
        if (OutputADCFloat < -1.0f) {
            ADCValue=0; // Min value
        } else if (OutputADCFloat > 1.0f) {
            ADCValue=0xFFF; // Max value
        } else {
            ADCValue=(uint16_t)((OutputADCFloat+1.0f) * Float2ADC);
        }
        
        // Update Dac value
        /* Set the DAC channel1 selected data holding register */
        *(__IO uint32_t *) Dac_Reg = ADCValue;
        //HAL_DAC_SetValue(&hdac1, DAC_CHANNEL_1, DAC_ALIGN_12B_R, ADCValue); //Alternative more slow method
        
    }
}
///////////////////////////////////////////
// Filter Function ////////////////////////
///////////////////////////////////////////
inline void NOP() { __ASM volatile ("nop"); } // one tick operation, Use to adjust frequency by slowing down the proccess
//nadav - simple filter implementation
inline float simpleFilterFloat(float Variable){
    // Buffer variables
    LastU=CurU;
    CurU=Variable;
    LastY=CurY;
    
    // Simple Filter LFP
    //CurY=(1-ALPF)*LastY+ALPF*CurU;
    
    // Simple Filter HPF
    CurY=AHPF*(LastY+CurU-LastU);
    
    
    return CurY;
}// end output filter function


inline float FirstFilterFloat(float Variable){
    LLastU_H=LastU_H;
    LastU_H=CurU_H;
    CurU_H=Variable;
    LLastY_H=LastY_H;
    LastY_H=CurY_H;
    
   // IIR biquad filter direct form 1 // y[n] = b0 * x[n] + b1 * x[n-1] + b2 * x[n-2] - a1 * y[n-1] - a2 * y[n-2]
    CurY_H=SOSMat_H[0]*CurU_H + SOSMat_H[1]*LastU_H + SOSMat_H[2]*LLastU_H - SOSMat_H[4]*LastY_H - SOSMat_H[5]*LLastY_H;
    return CurY_H*Gscale_H; // scale output
}// end filter function


///////////////////////////////////////////
// Output Filter Function /////////////////
///////////////////////////////////////////

///////////////////////////////////////////
inline float SecondFilterFloat(float Variable, int LPF_flag){
        
    // Buffer variables
    LLastU=LastU;
    LastU=CurU;
    CurU=Variable;
    LLastY=LastY;
    LastY=CurY;
    
        // IIR biquad filter direct form 1 // y[n] = b0 * x[n] + b1 * x[n-1] + b2 * x[n-2] - a1 * y[n-1] - a2 * y[n-2] 
        CurY=SOSMat[0]*CurU + SOSMat[1]*LastU + SOSMat[2]*LLastU - SOSMat[4]*LastY - SOSMat[5]*LLastY;
        return CurY*Gscale;

        //IIR biquad filter direct form 1 // y[n] = b0 * x[n] + b1 * x[n-1] + b2 * x[n-2] - a1 * y[n-1] - a2 * y[n-2]
        CurY=SOSMat_H[0]*CurU + SOSMat_H[1]*LastU + SOSMat_H[2]*LLastU - SOSMat_H[4]*LastY - SOSMat_H[5]*LLastY;
        return CurY*Gscale_H; // scale output

// end output filter function
}

/////gain filter/////
inline float OutputFilterFloat(float Variable){
    Variable*=1.0f; // Example of Math operation, Make sure to use float operations and not Double.
    return Variable;
}// end output filter function




////////////////////////
// Settings functions //
////////////////////////
/* ADC1 init function */
void MX_ADC1_Init(void)
{

  ADC_ChannelConfTypeDef sConfig;

    /**Common config 
    */
  hadc1.Instance = ADC1;
  hadc1.Init.ClockPrescaler = ADC_CLOCK_ASYNC;
  hadc1.Init.Resolution = ADC_RESOLUTION12b;
  hadc1.Init.ScanConvMode = ADC_SCAN_DISABLE;
  hadc1.Init.ContinuousConvMode = ENABLE;
  hadc1.Init.DiscontinuousConvMode = DISABLE;
  hadc1.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE;
  hadc1.Init.DataAlign = ADC_DATAALIGN_RIGHT;
  hadc1.Init.NbrOfConversion = 1;
  hadc1.Init.DMAContinuousRequests = DISABLE;
  hadc1.Init.EOCSelection = EOC_SINGLE_CONV;
  hadc1.Init.LowPowerAutoWait = DISABLE;
  hadc1.Init.Overrun = OVR_DATA_OVERWRITTEN;
  HAL_ADC_Init(&hadc1);

    /**Configure Regular Channel 
    */
  sConfig.Channel = ADC_CHANNEL_1;
  sConfig.Rank = 1;
  sConfig.SingleDiff = ADC_DIFFERENTIAL_ENDED ;//ADC_DIFFERENTIAL_ENDED; //ADC_SINGLE_ENDED
  sConfig.SamplingTime = ADC_SAMPLETIME_19CYCLES_5; //ADC_SAMPLETIME_1CYCLE_5;
  sConfig.OffsetNumber = ADC_OFFSET_NONE;
  sConfig.Offset = 0;
  HAL_ADC_ConfigChannel(&hadc1, &sConfig);

}

/* DAC1 init function */
void MX_DAC1_Init(void)
{

  DAC_ChannelConfTypeDef sConfig;

    /**DAC Initialization 
    */
  hdac1.Instance = DAC1;
  HAL_DAC_Init(&hdac1);

    /**DAC channel OUT1 config 
    */
  sConfig.DAC_Trigger = DAC_TRIGGER_NONE;
  sConfig.DAC_OutputBuffer = DAC_OUTPUTBUFFER_ENABLE;
  HAL_DAC_ConfigChannel(&hdac1, &sConfig, DAC_CHANNEL_1);

}