Ultrasonic Audio File Player

Dependencies:   mbed

Fork of TAU_ZOOLOG_Chirp_Generator by Yossi_Students

main_filter3.cpp

Committer:
Arkadi
Date:
2017-08-06
Revision:
12:e2b4a11ebe5a
Parent:
9:6d4136d9c074
Child:
13:24d8512fc722

File content as of revision 12:e2b4a11ebe5a:

/*
General Biquadratic Digital Filter Implementation
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   )

Make sure to use float variables in filter (Not double!).
*/
#include "mbed.h"
#include "config.h"
#include "sounddata.h"

#define TEST_OUTPUT_MODE  5

// mbed variables, Settings
AnalogIn in(A0);
AnalogOut out(PA_4);

// digital pins
DigitalOut led(LED1);
DigitalOut outPulse(PA_6); // pulse output on tr connector
DigitalOut mytoggle(PA_7);

// User Button as interrupt
InterruptIn mybutton(USER_BUTTON);

// Serial over USB as input device
Serial pc(SERIAL_TX, SERIAL_RX);

// ADC/DAC declarations
ADC_HandleTypeDef hadc1;
DAC_HandleTypeDef hdac1;

// Dac Register for direct method of setting DAC value`s
__IO uint32_t Dac_Reg = 0;

// Variables
uint16_t ADCValueIn=0;
uint16_t ADCValueOut=0;
float ADCFloat=0;
float ADCFloatFiltered=0;
float OutputADCFloat=0;
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
// float ADC2Float=  1.0;
// float Float2ADC= 1.0;
uint16_t ADCValueMax = 0;
uint16_t ADCValueMin = 0xfff;

// Definitions for software developer
#define NUM_CYCLES_TO_CHECK_KEYBOARD_INPUT   ((long)300000)   // 0 - not check keyboard input
#define SAMPLING_FREQUENCY_DELAY 2  // microseconds
#define CONSTANT_SIGNAL_LEVEL_FOR_TEST 0.2
#define NUM_OF_CYCLES_BACK_TO_NORMAL 0  // User can play with this. Hysteresis, 0 - no hysteresis

// global variables
float scale_for_predefined_output = (float)SCALE_FOR_PREDEFINED_OUTPUT;
int sampling_frequency_delay = SAMPLING_FREQUENCY_DELAY;
int delay_after_signal_transmission = DELAY_AFTER_SIGNAL_TRANSMISSION;
bool use_filter_with_predefined_output = USE_FILTER_WITH_PREDEFINED_OUTPUT;
int num_of_cycles_to_detect_threshold_crossing = NUM_OF_CYCLES_TO_DETECT_THRESHOLD_CROSSING;

int startPredefinedOutput = 0;
int num_threshold_crossing = 0;
int num_back_to_normal = 0;
int signal_low_threshold = SIGNAL_LOW_THRESHOD;

int UserButtonPressed;
long  NumCycles;

// second-order sections filter variables - upto 8 sections
#define MAX_SECTION_NUMBER 8
int NumSections = sizeof(SOSMat)/sizeof(float)/6;
int NumSectionsHP = sizeof(SOSMatHP)/sizeof(float)/6;

// Inputs
float CurrInput [MAX_SECTION_NUMBER+1];
float LastInput [MAX_SECTION_NUMBER+1];
float LLastInput [MAX_SECTION_NUMBER+1];

float scaled_sounddata[AMOUNT_OF_SIGNIFICANT_SAMPLES];
char FilterType[5][32];
int LoopCount = 0;

// trigger_pass variables
float triggThresholdValue=TRIGGER_THRESHOLD_VALUE;
// number of samples to count
float sample_length=SAMPLE_LENGTH*(SampleRate/1000.0f); // compansate number of cycles based on sample rate
float quiet_length=QUIET_LENGTH*(SampleRate/1000.0f);  // compansate number of cycles based on sample rate
bool trigger_HPF=TRIGGER_HPF;

// Filter variables
// high pass variables
// high pass
// tau=RC=1/2pif
// α := RC / (RC + dt) :=Tau/(Tau+dt)
// y[0] := x[0]
// y[i] := α * y[i-1] + α * (x[i] - x[i-1])
// AHPF=ALPHA

float Tau=TAU_AHPF/TWOPI; // time constat of the filter, (1khz -> 0.001 second) (converted to hz from rad/sec
float AHPF=Tau/(Tau+1.0f/SampleRate);
float LastY=0;
float CurY=0;
float LastU=0;
float CurU=0;

// Saturation variables
float saturation_threshold=SATURATION_THRESHOLD;
int num_saturation_samples=NUM_SATURATION_SAMPLES;
bool saturation_detection=SATURATION_DETECTION;

// Saturation delay
uint32_t saturation_delay=SATURATION_DELAY*OPERATION_MS;

// nop operation
inline void NOP()
{
    __ASM volatile ("nop");    // one tick operation, Use to adjust frequency by slowing down the proccess
}

// User Button Interrupt Service Routine (ISR)
void pressed()
{
    UserButtonPressed = 0;
}

int checkKeyboardInput(void)
{
    if (pc.readable())
        return 0; // means has input
    else
        return 1; // means no input
}

#include "adc_init.h"

#include "iirlpnorm_filter.h"

#include "high_path_filter.h"

#include "no_filter.h"

#include "predefined_output.h"

#include "triggered_pass.h"

void print_parameters()
{
    printf("\r\n%s Digital Filter.\r\nSTART MAIN LOOP, use mode %d, loop #%d, number of sections: %d\r\n",
           FilterType[UseFilterMode], UseFilterMode, LoopCount,
           (UseFilterMode == IIRLPNORM_FILTER_MODE) ? NumSections : NumSectionsHP);
    if (UseFilterMode == PREDEFINED_OUTPUT_MODE) {
        printf("Signal threshould: %d\r\nSignal scale: %5.2f\r\nNumber of cycles to detect threshold crossing: %d\r\nDelay after signal in microseconds: %d\r\nUse filter: %s\r\n",
               signal_low_threshold, scale_for_predefined_output, num_of_cycles_to_detect_threshold_crossing, delay_after_signal_transmission,
               use_filter_with_predefined_output ? "Y" : "N");
    }
}

// Main procedure
int main()
{
    char command[64];
    int isInputNotValid;
    int k;
    bool isSignalClipped = false;

    strcpy(FilterType[0], "IIRLPNORM filter");
    strcpy(FilterType[1], "High Pass filter");
    strcpy(FilterType[2], "No filter");
    strcpy(FilterType[3], "Predefined Output");
    strcpy(FilterType[4], "Test Output");

    ADC1_Init();
    DAC1_Init();

    HAL_ADC_Start(&hadc1);
    HAL_DAC_Start(&hdac1, DAC_CHANNEL_1);

    // define Dac Register for direct method of setting DAC value`s
    Dac_Reg = (uint32_t) (hdac1.Instance);
    Dac_Reg += __HAL_DHR12R1_ALIGNEMENT(DAC_ALIGN_12B_R);

    // set trigger state:
    outPulse.write(0);
    
    typedef void(*functionPtr)(void);
    functionPtr FilterFunction;

    // Assign ISR
    mybutton.fall(&pressed);

    LoopCount++;
    print_parameters();
        
    if (UseFilterMode == PREDEFINED_OUTPUT_MODE) {
        // Prepare scaled sound data
        isSignalClipped = false;
        for (k=0; k < AMOUNT_OF_SIGNIFICANT_SAMPLES; k++ ) {
            scaled_sounddata[k] = sounddata[k]* scale_for_predefined_output;
            if (scaled_sounddata[k] < (float)-1.0) {
                scaled_sounddata[k] = (float)-1.0;
                isSignalClipped = true;
            }
            if (scaled_sounddata[k] > (float)1.0) {
                scaled_sounddata[k] = (float)1.0;
                isSignalClipped = true;
            }
        }
    }

    // Infinite loop
    while(true) {
        switch (UseFilterMode) {
            case IIRLPNORM_FILTER_MODE:
                FilterFunction = iirlpnorm_filter;
                printf("Running IIRLPNORM filter\r\n");
                memset(CurrInput, 0, sizeof(CurrInput));
                memset(LastInput, 0, sizeof(LastInput));
                memset(LLastInput, 0, sizeof(LLastInput));
                break;
                // end of case IIRLPNORM_FILTER_MODE

            case HIGH_PASS_FILTER_MODE:
                FilterFunction = highpath_filter;
                printf("Running High Path filter\r\n");
                memset(CurrInput, 0, sizeof(CurrInput));
                memset(LastInput, 0, sizeof(LastInput));
                memset(LLastInput, 0, sizeof(LLastInput));
                break;
                // end of case HIGH_PASS_FILTER_MODE

            case PREDEFINED_OUTPUT_MODE:
                FilterFunction = predefined_output;
                printf("Running Predefined Output\r\n");
                memset(CurrInput, 0, sizeof(CurrInput));
                memset(LastInput, 0, sizeof(LastInput));
                memset(LLastInput, 0, sizeof(LLastInput));
                num_threshold_crossing = 0;
                startPredefinedOutput = 0;
                num_back_to_normal = 0;
                break;
                // end of case PREDEFINED_OUTPUT_MODE

            case NO_FILTER_MODE:
                FilterFunction = no_filter;
                printf("Running No filter\r\n");
                break;
                // end of case NO_FILTER_MODE

            case TRIGGERED_OUTPUT_MODE:
                FilterFunction = triggered_pass;
                printf("Running Triggered Mode\r\n");
                break;
                // end of case Triggered Mode

            case TEST_OUTPUT_MODE:
                FilterFunction = test_output;
                printf("Running test output\r\n");
                break;
                // end of case TEST_OUTPUT_MODE

            default:
                printf("Wrong User Filter Mode");
                // Default - no filter
                FilterFunction = no_filter;
                printf("No filter\r\n");
                break;

        } //  end of switch (UserFilterMode)

        UserButtonPressed = 1;
        NumCycles = 0;
        ADCValueMax = 0;
        ADCValueMin = 0xfff;

        // ====================================================
        // Start signal processing
        while(UserButtonPressed) {
            FilterFunction();
            NumCycles++;
            // Check keyboard input each NUM_CYCLES_TO_CHECK_KEYBOARD_INPUT cycles
            if((NUM_CYCLES_TO_CHECK_KEYBOARD_INPUT > 0)  && (NumCycles % NUM_CYCLES_TO_CHECK_KEYBOARD_INPUT == 0)) {
                // printf("Check keyboard input. Cycle: %d\n", NumCycles);
                UserButtonPressed = checkKeyboardInput();
            }
        } // end of while(UserButtonPressed)
        // End of signal processing
        // ====================================================

        // User button pressed
        // Main loop working with ADC/DAC is stopped
        // Here should be functionality which should be done before start another loop with ADC/DAC
        printf("\nKeyboard key or User button pressed! Exit from main loop.\r\n");

        // Init filter variables
        memset(CurrInput, 0, sizeof(CurrInput));
        memset(LastInput, 0, sizeof(LastInput));
        memset(LLastInput, 0, sizeof(LLastInput));

        // Input new use mode
        isInputNotValid = 1;
        while (isInputNotValid) {
            printf("Please, select use mode: \r\n");
            printf("%d - IIRLPNORM filter\r\n", IIRLPNORM_FILTER_MODE);
            printf("%d - High Pass filter\r\n", HIGH_PASS_FILTER_MODE);
            printf("%d - No filter\r\n", NO_FILTER_MODE);
            printf("%d - Predefined Output\r\n", PREDEFINED_OUTPUT_MODE);
            printf("%d - Triggered Mode \r\n", TRIGGERED_OUTPUT_MODE);
            printf("Input your choice or hit Enter to continue main loop in the same use mode: ");
            memset(command, 0, sizeof(command));
            gets(command);
            // printf("Command:%s; command length:%d\n", command, strlen(command));
            if (strlen(command)-2 != 0 ) {
                // convert characters to integer; if convertion not succeeded return 0 (i.e. IIRLPNORM_FILTER_MODE)
                UseFilterMode = atoi(&command[strlen(command)-2]);
            }

            if (UseFilterMode >= IIRLPNORM_FILTER_MODE && UseFilterMode <= TRIGGERED_OUTPUT_MODE) {
                if (UseFilterMode == PREDEFINED_OUTPUT_MODE) {
                    printf("Enter signal amplitude threshold to start generate predefined signal (default - %d): ", SIGNAL_LOW_THRESHOD);
                    memset(command, 0, sizeof(command));
                    gets(command);
                    signal_low_threshold = atoi(command);
                    if (signal_low_threshold == 0) {
                        printf("\r\nWrong input - default is taken\r\n");
                        signal_low_threshold = SIGNAL_LOW_THRESHOD;
                    }
                        
                    // not used //
//                   isSignalClipped = true;
//                    while (isSignalClipped) {
//                        printf("Enter amplitude scale parameter for predefined signal (default - %5.2f): ", SCALE_FOR_PREDEFINED_OUTPUT);
//                        memset(command, 0, sizeof(command));
//                        gets(command);
//                        scale_for_predefined_output = atof(command);
//                        if (scale_for_predefined_output == float(0.0)) {
//                            printf("\r\nWrong input - default is taken\r\n");
//                            scale_for_predefined_output = SCALE_FOR_PREDEFINED_OUTPUT;
//                        }
//                        isSignalClipped = false;
//                        for (k=0; k < AMOUNT_OF_SIGNIFICANT_SAMPLES; k++ ) {
//                            scaled_sounddata[k] = sounddata[k]* scale_for_predefined_output;
//                            if (scaled_sounddata[k] < (float)-1.0) {
//                                scaled_sounddata[k] = (float)-1.0;
//                                isSignalClipped = true;
//                            }
//                            if (scaled_sounddata[k] > (float)1.0) {
//                                scaled_sounddata[k] = (float)1.0;
//                                isSignalClipped = true;
//                            }
//                        }
//                        if (isSignalClipped) {
//                            printf("With amplitude scale %5.2f, signal will be clipped !!!. Select smaller scale.\r\n",scale_for_predefined_output);
//                        }
//                    }  // end of while (isSignalClipped)

                    printf("Enter delay after signal in microseconds (default - %d): ", DELAY_AFTER_SIGNAL_TRANSMISSION);
                    memset(command, 0, sizeof(command));
                    gets(command);
                    delay_after_signal_transmission = atoi(command);
                    if (delay_after_signal_transmission == 0) {
                        printf("\r\nWrong input - default is taken\r\n");
                        delay_after_signal_transmission = DELAY_AFTER_SIGNAL_TRANSMISSION;
                    }
//                    printf("Enter number of cycles to detect threshold crossing (default - %d): ", NUM_OF_CYCLES_TO_DETECT_THRESHOLD_CROSSING);
//                    memset(command, 0, sizeof(command));
//                    gets(command);
//                    num_of_cycles_to_detect_threshold_crossing = atoi(command);
//                    if (num_of_cycles_to_detect_threshold_crossing == 0) {
//                        printf("\r\nWrong input - default is taken\r\n");
//                        num_of_cycles_to_detect_threshold_crossing = NUM_OF_CYCLES_TO_DETECT_THRESHOLD_CROSSING;
//                    }
                    // not implemeted filter not activated //
                    //printf("Use high pass filter with predefined output: Y/N (default - %s): ",
//                           USE_FILTER_WITH_PREDEFINED_OUTPUT ? "Y" : "N" );
//                    memset(command, 0, sizeof(command));
//                    gets(command);
//                    if ((command[0] == 'Y') || (command[0] == 'y')) {
//                        use_filter_with_predefined_output = true;
//                    } else if ((command[0] == 'N') || (command[0] == 'n')) {
//                        use_filter_with_predefined_output = false;
//                    } else {
//                        use_filter_with_predefined_output = USE_FILTER_WITH_PREDEFINED_OUTPUT;
//                    }
//
//                    if (delay_after_signal_transmission == 0) {
//                        delay_after_signal_transmission = USE_FILTER_WITH_PREDEFINED_OUTPUT;
//                    }
//                    memset(command, 0, sizeof(command));

                    isInputNotValid = 0;
                } else  if (UseFilterMode == TEST_OUTPUT_MODE) {
                    isInputNotValid = 0;
                } else  if (UseFilterMode == NO_FILTER_MODE) {
                    isInputNotValid = 0;
                } else if (UseFilterMode == HIGH_PASS_FILTER_MODE) {
                    isInputNotValid = 0;
                } else if (UseFilterMode == TRIGGERED_OUTPUT_MODE) {

                    // define threshold
                    printf("Enter signal trigger threshold (default - %f): ", TRIGGER_THRESHOLD_VALUE);
                    memset(command, 0, sizeof(command));
                    gets(command);
                    triggThresholdValue = atof(command);
                    if (triggThresholdValue == 0) {
                        printf("\r\nWrong input - default is taken\r\n");
                        triggThresholdValue = TRIGGER_THRESHOLD_VALUE;
                    }
                    printf("\r\nChosen - %f\r\n",triggThresholdValue);

                    // define record time
                    printf("Enter record time (millis) (default - %f): ", SAMPLE_LENGTH);
                    memset(command, 0, sizeof(command));
                    gets(command);
                    sample_length = atof(command)*(SampleRate/1000.0f); // compansation for number of samples
                    if (sample_length == 0) {
                        printf("\r\nWrong input - default is taken\r\n");
                        sample_length = SAMPLE_LENGTH*(SampleRate/1000.0f);
                    }
                    printf("\r\n Signal samples - %f\r\n",sample_length);

                    // define silence time
                    printf("Enter silence time (millis) (default - %f): ", QUIET_LENGTH);
                    memset(command, 0, sizeof(command));
                    gets(command);
                    quiet_length = atof(command)*(SampleRate/1000.0f); // compansation for number of samples
                    if (quiet_length == 0) {
                        printf("\r\nWrong input - default is taken\r\n");
                        quiet_length = QUIET_LENGTH*(SampleRate/1000.0f);
                    }
                    printf("\r\n silence samples - %f\r\n",quiet_length);

                    // enable TRIGGER HPF
                    printf("Enter enable trigger HPF (default - %d): ", TRIGGER_HPF);
                    memset(command, 0, sizeof(command));
                    gets(command);
                    trigger_HPF = (bool)atoi(command);
                    printf("\r\nChosen - %d\r\n",trigger_HPF);

                    // enable Saturation Detector
                    printf("Enter enable Saturation Detection (default - %d): ", SATURATION_DETECTION);
                    memset(command, 0, sizeof(command));
                    gets(command);
                    saturation_detection = (bool)atoi(command);
                    printf("\r\nChosen - %d\r\n",saturation_detection);

                    // no point asking quations if not enabled
                    if (saturation_detection) {
                        // set saturation threshold
                        printf("Enter Saturation threshold (default - %f): ", SATURATION_THRESHOLD);
                        memset(command, 0, sizeof(command));
                        gets(command);
                        saturation_threshold =atof(command);
                        if (saturation_threshold <= 0) {
                            printf("\r\nWrong input - default is taken\r\n");
                            saturation_threshold = SATURATION_THRESHOLD;
                        }
                        printf("\r\nChosen - %f \r\n",saturation_threshold);

                        // set saturation sample numbers
                        printf("Enter Saturation sample number (default - %d): ", NUM_SATURATION_SAMPLES);
                        memset(command, 0, sizeof(command));
                        gets(command);
                        num_saturation_samples =atoi(command);
                        if (num_saturation_samples == 0) {
                            printf("\r\nWrong input - default is taken\r\n");
                            num_saturation_samples = NUM_SATURATION_SAMPLES;
                        }
                        printf("\r\nChosen - %d\r\n",num_saturation_samples);


                        // set saturation delay period
                        printf("Enter Saturation delay in millis (default - %d): ", SATURATION_DELAY);
                        memset(command, 0, sizeof(command));
                        gets(command);
                        float saturation_delay_float =atof(command);
                        if (saturation_delay_float <= 0) {
                            printf("\r\nWrong input - default is taken\r\n");
                            saturation_delay_float = SATURATION_DELAY;
                        }
                        saturation_delay=(uint32_t)(saturation_delay_float*OPERATION_MS);
                        printf("\r\nChosen - %f , delay in cycle number %d \r\n",saturation_delay_float,saturation_delay);
                    }
                    // finish parameter settings
                    isInputNotValid = 0;
                } else {
                    printf("\r\nWrong input - try again\r\n");
                }
            }
            LoopCount++;
            print_parameters();

        } // end while(True)
    }
}