diff --git a/PULP/Makefile b/PULP/Makefile index 53d84fa..2c2ed91 100755 --- a/PULP/Makefile +++ b/PULP/Makefile @@ -1,16 +1,16 @@ -PULP_APP = delineation_app +PULP_APP = adaptive_rpeak_detection PULP_APP_FC_SRCS = main.c \ adaptive_Rpeak_detection/adaptiveRpeakDetection.c \ Morph_filt/morpho_filtering.c \ REWARD_R_peak_detection/relativeEnergy.c \ REWARD_R_peak_detection/peakDetection.c \ error_detection/error_detection.c \ profiling/profile.c CORES ?= 1 CTARGET ?= 0 PULP_CFLAGS += -DTARGET=$(CTARGET) -DNUM_CORES=$(CORES) -O3 -g3 -w PULP_LDFLAGS = -lm #-lg #uncomment -lg for pulpissimo include $(PULP_SDK_HOME)/install/rules/pulp_rt.mk diff --git a/PULP/Morph_filt/morpho_filtering.c b/PULP/Morph_filt/morpho_filtering.c index 52814b8..7dbda28 100755 --- a/PULP/Morph_filt/morpho_filtering.c +++ b/PULP/Morph_filt/morpho_filtering.c @@ -1,862 +1,862 @@ #include "morpho_filtering.h" #include "rt/rt_api.h" #include "../defines.h" ///////////////////////////////////////////////////////////////////////////////// //-----------------------PRIVATE MEMORY OF CORE 0,1 and 2----------------------// ///////////////////////////////////////////////////////////////////////////////// //El vector B1 definido en la tecnica se despliega en memoria #if HIGH_FREQ==1 PULP_L1_DATA int16_t B1[] = B1_STRUCTURING_ELEMENT; #endif // SIZE IN BYTES PER LEAD // (250 Hz) (500 Hz) PULP_L1_DATA int16_t bufferEB0[CHANNELS][TAMB0]; // 100 200 PULP_L1_DATA int16_t bufferDB0[CHANNELS][TAMB0]; // 100 200 PULP_L1_DATA int16_t bufferDBc[CHANNELS][TAMBc]; // 150 300 PULP_L1_DATA int16_t bufferEBc[CHANNELS][TAMBc]; // 150 300 PULP_L1_DATA int16_t bufferEnt[CHANNELS][TAMBEnt]; // 300 600 #if HIGH_FREQ==1 PULP_L1_DATA volatile int16_t bufferFBc1[CHANNELS][TAMBFB]; // 10 18 PULP_L1_DATA volatile int16_t bufferFBc1ed[CHANNELS][TAMBFB]; // 10 18 PULP_L1_DATA volatile int16_t bufferFBc1de[CHANNELS][TAMBFB]; // 10 18 #endif PULP_L1_DATA int16_t bufferEntrada[CHANNELS][BUFFER_SIZE_FILTER]; // 2 2 PULP_L1_DATA int16_t bufferSalida[CHANNELS][BUFFER_SIZE_FILTER]; // 2 2 //volatile int16_t bufferSalida[CHANNELS]; PULP_L1_DATA int16_t samplesRead[CHANNELS]; // 2 2 PULP_L1_DATA int16_t actEntrada[CHANNELS]; // 2 2 PULP_L1_DATA int16_t contador[CHANNELS]; // 2 2 PULP_L1_DATA int16_t aBEB0[CHANNELS]; // 2 2 PULP_L1_DATA int16_t pMinEB0[CHANNELS]; // 2 2 PULP_L1_DATA int16_t p2MinEB0[CHANNELS]; // 2 2 PULP_L1_DATA int16_t aBDB0[CHANNELS]; // 2 2 PULP_L1_DATA int16_t pMaxDB0[CHANNELS]; // 2 2 PULP_L1_DATA int16_t p2MaxDB0[CHANNELS]; // 2 2 PULP_L1_DATA int16_t aBDBc[CHANNELS]; // 2 2 PULP_L1_DATA int16_t pMaxDBc[CHANNELS]; // 2 2 PULP_L1_DATA int16_t p2MaxDBc[CHANNELS]; // 2 2 PULP_L1_DATA int16_t aBEBc[CHANNELS]; // 2 2 PULP_L1_DATA int16_t pMinEBc[CHANNELS]; // 2 2 PULP_L1_DATA int16_t p2MinEBc[CHANNELS]; // 2 2 PULP_L1_DATA int16_t aBEnt[CHANNELS]; // 2 2 PULP_L1_DATA int16_t rBEnt[CHANNELS]; // 2 2 #if HIGH_FREQ==1 PULP_L1_DATA volatile int16_t aBFBc1[CHANNELS]; // 2 2 PULP_L1_DATA volatile int16_t aFBc1x[CHANNELS]; // 2 2 PULP_L1_DATA volatile int16_t pMaxFBc1ed[CHANNELS]; // 2 2 PULP_L1_DATA volatile int16_t pMinFBc1de[CHANNELS]; // 2 2 PULP_L1_DATA volatile int16_t p2MinFBc1de[CHANNELS]; // 2 2 PULP_L1_DATA volatile int16_t p2MaxFBc1ed[CHANNELS]; // 2 2 PULP_L1_DATA volatile int16_t indiceB1[CHANNELS]; // 2 2 PULP_L1_DATA volatile int16_t min1E[CHANNELS]; // 2 2 PULP_L1_DATA volatile int16_t max1D[CHANNELS]; // 2 2 #endif PULP_L1_DATA int16_t vaux[CHANNELS]; // 2 2 PULP_L1_DATA int16_t v2aux[CHANNELS]; // 2 2 //TOTAL 890 1714 ///////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////// void fill_in_filter(int16_t input, int16_t index) { actEntrada[index] = 0; bufferEntrada[index][0] = input; samplesRead[index] = BUFFER_SIZE_FILTER; if (contador[index] < (TAMB0 * 3) + (TAMB0 / 2) - (TAMBcm - TAMB0m) - 3) (contador[index])++; } void storeOutput(int16_t v, int16_t index) { bufferSalida[index][0] = v; } //Opening: dilation(erosion(X)) //Closing: erosion(dilation(X)) //Definicion de buffers segun su aparicion en la tecnica: //bufferEB0: opening(entrada) -> erosion(entrada, B0) //bufferDB0: opening(entrada) -> dilation(erosion(entrada, B0)) //bufferDBc: closing(fbt) -> dilation(fbt, Bc) //bufferEBc: closing(fbt) -> erosion(dilation(fbt, Bc)) //bufferEnt: buffer necesario para superar la diferencia de tamaño entre // los buffers del final del calculo y los iniciales y poder // realizar la resta fbc = entrada - fb // IF HIGH_FREQ==1: //BufferFBc1: buffer con los valores fbc para los siguientes //BufferFBc1e: opening(fbc) -> erosion(fbc, B1); //BufferFBc1ed: opening(fbc) -> dilation(erosion(fbc, B1)); //BufferFBc1d: closing(fbc) -> dilation(fbc, B1); //BufferFBc1de: closing(fbc) -> erosion(dilation(fbc,B1)); // END IF //A partir de los valores de BufferFB2de y BufferFB2ed es posible obtener //el valor resultado del filtrado. void init_filtering() { for(int16_t i = 0; i < CHANNELS; i++) { #if HIGH_FREQ==1 aBFBc1[i] = 0; aFBc1x[i] = 0; pMaxFBc1ed[i] = 0; pMinFBc1de[i] = 0; p2MinFBc1de[i] = -1; p2MaxFBc1ed[i] = -1; indiceB1[i] = 0; #endif contador[i] = 0; aBEB0[i] = TAMB0 - 1; pMinEB0[i] = 0; p2MinEB0[i] = -1; aBDB0[i] = TAMB0m; pMaxDB0[i] = 0; p2MaxDB0[i] = -1; aBDBc[i] = TAMB0m; pMaxDBc[i] = 0; p2MaxDBc[i] = -1; aBEBc[i] = TAMB0m; pMinEBc[i] = 0; p2MinEBc[i] = -1; aBEnt[i] = 0; rBEnt[i] = -1; } } void initBuffers(int16_t i, int16_t input_value, int16_t index) { #if HIGH_FREQ==1 int16_t j; int16_t component; #endif actEntrada[index] = 0; //VICTOR: se incrementa el contador, al ser llamado este procedimiento para cada nuevo sample. (contador[index])++; samplesRead[index] = 1; //Llenado inicial de los buffers //FRAN:morph --> change bufferEntrada[i] by 0 bufferEB0[index][i] = input_value; if (input_value <= bufferEB0[index][pMinEB0[index]]) { p2MinEB0[index] = pMinEB0[index]; pMinEB0[index] = i; } else if (p2MinEB0[index] != -1 && input_value <= bufferEB0[index][p2MinEB0[index]]) { p2MinEB0[index] = i; } if (i >= TAMB0m) bufferEnt[index][(aBEnt[index])++] = input_value; else { bufferDB0[index][i] = input_value; if (input_value >= bufferDB0[index][pMaxDB0[index]]) { p2MaxDB0[index] = pMaxDB0[index]; pMaxDB0[index] = i; } else if (input_value >= bufferDB0[index][p2MaxDB0[index]]) p2MaxDB0[index] = i; bufferDBc[index][i] = input_value; if (input_value >= bufferDBc[index][pMaxDBc[index]]) { p2MaxDBc[index] = pMaxDBc[index]; pMaxDBc[index] = i; } else if (input_value >= bufferDBc[index][p2MaxDBc[index]]) p2MaxDBc[index] = i; bufferEBc[index][i] = input_value; if (input_value <= bufferEBc[index][pMinEBc[index]]) { if (pMinEBc[index] != 0) p2MinEBc[index] = pMinEBc[index]; pMinEBc[index] = i; } else if (p2MinEBc[index] != -1 && input_value <= bufferEBc[index][p2MinEBc[index]]) p2MinEBc[index] = i; #if HIGH_FREQ==1 bufferFBc1[index][aBFBc1[index]] = 0; if (aBFBc1[index] != TAMBFB - 1) (aBFBc1[index])++; else aBFBc1[index] = 0; if (i >= TAMBFB - 1) //i >= 4 { // A partir del bufferFBc1, se calcula erosion y dilation // y se almacenan los valores sobre los buffers FBc1d y FBc1e // cuyos limites se calculan en paralelo. j = indiceB1[index]; if (indiceB1[index] != TAMB1*(TAMB1 - 1)) indiceB1[index] += TAMB1; else indiceB1[index] = 0; min1E[index] = bufferFBc1[index][0] - B1[j]; max1D[index] = bufferFBc1[index][0] + B1[j]; for (component = 1; component < TAMB1; component++) { min1E[index] = min1E[index]>bufferFBc1[index][component] - B1[j + component] ? bufferFBc1[index][component] - B1[j + component] : min1E[index]; max1D[index] = max1D[index]= TAMBFB - 1 + TAMBFB - 1) // i >= 8 { //Paso de valores y mover puntero de bufferFBc1ed if (aBFBc1[index] == pMaxFBc1ed[index]) { if (min1E[index] < bufferFBc1ed[index][pMaxFBc1ed[index]]) { if (p2MaxFBc1ed[index] == -1) { bufferFBc1ed[index][aFBc1x[index]] = min1E[index]; v2aux[index] = INT16_MIN; vaux[index] = bufferFBc1ed[index][TAMBFB - 1]; pMaxFBc1ed[index] = TAMBFB - 1; for (j = TAMBFB - 2; j >= 0; j--) { if (bufferFBc1ed[index][j] > vaux[index]) { v2aux[index] = vaux[index]; vaux[index] = bufferFBc1ed[index][j]; p2MaxFBc1ed[index] = pMaxFBc1ed[index]; pMaxFBc1ed[index] = j; } else if (bufferFBc1ed[index][j] > v2aux[index]) { v2aux[index] = bufferFBc1ed[index][j]; p2MaxFBc1ed[index] = j; } } } else if (min1E[index] < bufferFBc1ed[index][p2MaxFBc1ed[index]]) { pMaxFBc1ed[index] = p2MaxFBc1ed[index]; p2MaxFBc1ed[index] = -1; } } } else if (min1E[index] >= bufferFBc1ed[index][pMaxFBc1ed[index]]) { p2MaxFBc1ed[index] = pMaxFBc1ed[index]; pMaxFBc1ed[index] = aFBc1x[index]; } else if (aFBc1x[index] == p2MaxFBc1ed[index]) { if (min1E[index] < bufferFBc1ed[index][p2MaxFBc1ed[index]]) p2MaxFBc1ed[index] = -1; } else if (p2MaxFBc1ed[index] != -1 && min1E[index] >= bufferFBc1ed[index][p2MaxFBc1ed[index]]) p2MaxFBc1ed[index] = aFBc1x[index]; bufferFBc1ed[index][aFBc1x[index]] = min1E[index]; if (aFBc1x[index] == pMinFBc1de[index]) { if (max1D[index] > bufferFBc1de[index][pMinFBc1de[index]]) { if (p2MinFBc1de[index] == -1) { bufferFBc1de[index][aFBc1x[index]] = max1D[index]; v2aux[index] = INT16_MAX; vaux[index] = bufferFBc1de[index][TAMBFB - 1]; pMinFBc1de[index] = TAMBFB - 1; for (j = TAMBFB - 2; j >= 0; j--) { if (bufferFBc1de[index][j] < vaux[index]) { v2aux[index] = vaux[index]; vaux[index] = bufferFBc1de[index][j]; p2MinFBc1de[index] = pMinFBc1de[index]; pMinFBc1de[index] = j; } else if (bufferFBc1de[index][j] < v2aux[index]) { v2aux[index] = bufferFBc1de[index][j]; p2MinFBc1de[index] = j; } } } else if (max1D[index] > bufferFBc1de[index][p2MinFBc1de[index]]) { pMinFBc1de[index] = p2MinFBc1de[index]; p2MinFBc1de[index] = -1; } } } else if (max1D[index] <= bufferFBc1de[index][pMinFBc1de[index]]) { p2MinFBc1de[index] = pMinFBc1de[index]; pMinFBc1de[index] = aFBc1x[index]; } else if (aFBc1x[index] == p2MinFBc1de[index]) { if (max1D[index] > bufferFBc1de[index][p2MinFBc1de[index]]) p2MinFBc1de[index] = -1; } else if (p2MinFBc1de[index] != -1 && max1D[index] <= bufferFBc1de[index][p2MinFBc1de[index]]) p2MinFBc1de[index] = aFBc1x[index]; bufferFBc1de[index][aFBc1x[index]] = max1D[index]; } if (aFBc1x[index] != TAMBFB - 1) (aFBc1x[index])++; else aFBc1x[index] = 0; } #endif //HIGH_FREQ==1 } } void proceso(int16_t index) { int16_t i; #if HIGH_FREQ==1 int16_t j, component; #endif while (actEntrada[index] < samplesRead[index]) { //printf("core %d. %d:%d\n", rt_core_id(), actEntrada[index], samplesRead[index]); if (aBEB0[index] == pMinEB0[index]) { if (bufferEntrada[index][actEntrada[index]] > bufferEB0[index][pMinEB0[index]]) { if (p2MinEB0[index] == -1) { bufferEB0[index][aBEB0[index]] = bufferEntrada[index][actEntrada[index]]; v2aux[index] = INT16_MAX; vaux[index] = bufferEB0[index][TAMB0 - 1]; pMinEB0[index] = TAMB0 - 1; for (i = TAMB0 - 2; i >= 0; i--) { if (bufferEB0[index][i] < vaux[index]) { v2aux[index] = vaux[index]; vaux[index] = bufferEB0[index][i]; p2MinEB0[index] = pMinEB0[index]; pMinEB0[index] = i; } else if (bufferEB0[index][i] < v2aux[index]) { v2aux[index] = bufferEB0[index][i]; p2MinEB0[index] = i; } } // return 0; } else if (bufferEntrada[index][actEntrada[index]] > bufferEB0[index][p2MinEB0[index]]) { pMinEB0[index] = p2MinEB0[index] ; p2MinEB0[index] = -1; } } } else if (bufferEntrada[index][actEntrada[index]] <= bufferEB0[index][pMinEB0[index]]) { p2MinEB0[index] = pMinEB0[index]; pMinEB0[index] = aBEB0[index]; } else if (aBEB0[index] == p2MinEB0[index] ) { if (bufferEntrada[index][actEntrada[index]] > bufferEB0[index][p2MinEB0[index]]) { p2MinEB0[index] = -1; } } else if (p2MinEB0[index] != -1 && bufferEntrada[index][actEntrada[index]] <= bufferEB0[index][p2MinEB0[index]]) { p2MinEB0[index] = aBEB0[index]; } bufferEnt[index][aBEnt[index]] = bufferEntrada[index][actEntrada[index]]; if (aBEnt[index] != TAMBEnt - 1) { (aBEnt[index])++; } else { aBEnt[index] = 0; } bufferEB0[index][aBEB0[index]] = bufferEntrada[index][(actEntrada[index])++]; if (aBEB0[index] != TAMB0 - 1) { (aBEB0[index])++; } else { (aBEB0[index]) = 0; } if (aBDB0[index] == pMaxDB0[index] ) { if (bufferEB0[index][pMinEB0[index]] < bufferDB0[index][pMaxDB0[index]]) { if (p2MaxDB0[index] == -1) { bufferDB0[index][aBDB0[index]] = bufferEB0[index][pMinEB0[index]]; v2aux[index] = INT16_MIN; vaux[index] = bufferDB0[index][TAMB0 - 1]; pMaxDB0[index] = TAMB0 - 1; for (i = TAMB0 - 2; i >= 0; i--) { if (bufferDB0[index][i] > vaux[index]) { v2aux[index] = vaux[index]; vaux[index] = bufferDB0[index][i]; p2MaxDB0[index] = pMaxDB0[index] ; pMaxDB0[index] = i; } else if (bufferDB0[index][i] > v2aux[index]) { v2aux[index] = bufferDB0[index][i]; p2MaxDB0[index] = i; } } // return 0; } else if (bufferEB0[index][pMinEB0[index]] < bufferDB0[index][p2MaxDB0[index]]) { pMaxDB0[index] = p2MaxDB0[index] ; p2MaxDB0[index] = -1; } } } else if (bufferEB0[index][pMinEB0[index]] >= bufferDB0[index][pMaxDB0[index]]) { p2MaxDB0[index] = pMaxDB0[index] ; pMaxDB0[index] = aBDB0[index] ; } else if (aBDB0[index] == p2MaxDB0[index] ) { if (bufferEB0[index][pMinEB0[index]] < bufferDB0[index][p2MaxDB0[index]]) { p2MaxDB0[index] = -1; } } else if (p2MaxDB0[index] != -1 && bufferEB0[index][pMinEB0[index]] >= bufferDB0[index][p2MaxDB0[index]]) { p2MaxDB0[index] = aBDB0[index]; } bufferDB0[index][aBDB0[index]] = bufferEB0[index][pMinEB0[index]]; if (aBDB0[index] != TAMB0 - 1) { (aBDB0[index] )++; } else { aBDB0[index] = 0; } //Paso de datos al buffer DBc si se ha llenado el buffer DB0. // if (!firstPass[k] || actEntrada[k] >= TAMB0 + (TAMB0/2) - 1) { // 74 //VICTOR: he cambiado esto if (contador[index] >= TAMB0 + (TAMB0 / 2) - 1) { if (aBDBc[index] == pMaxDBc[index]) { if (bufferDB0[index][pMaxDB0[index]] < bufferDBc[index][pMaxDBc[index]]) { if (p2MaxDBc[index] == -1) { bufferDBc[index][aBDBc[index] ] = bufferDB0[index][pMaxDB0[index] ]; v2aux[index] = INT16_MIN; vaux[index] = bufferDBc[index][TAMBc - 1]; pMaxDBc[index] = TAMBc - 1; for (i = TAMBc - 2; i >= 0; i--) { if (bufferDBc[index][i] > vaux[index]) { v2aux[index] = vaux[index]; vaux[index] = bufferDBc[index][i]; p2MaxDBc[index] = pMaxDBc[index]; pMaxDBc[index] = i; } else if (bufferDBc[index][i] > v2aux[index]) { v2aux[index] = bufferDBc[index][i]; p2MaxDBc[index] = i; } } // return 0; } else if (bufferDB0[index][pMaxDB0[index]] < bufferDBc[index][p2MaxDBc[index]]) { pMaxDBc[index] = p2MaxDBc[index]; p2MaxDBc[index] = -1; } } } else if (bufferDB0[index][pMaxDB0[index]] >= bufferDBc[index][pMaxDBc[index]]) { p2MaxDBc[index] = pMaxDBc[index]; pMaxDBc[index] = aBDBc[index] ; } else if (aBDBc[index] == p2MaxDBc[index]) { if (bufferDB0[index][pMaxDB0[index]] < bufferDBc[index][p2MaxDBc[index]]) { p2MaxDBc[index] = -1; } } else if (p2MaxDBc[index] != -1 && bufferDB0[index][pMaxDB0[index]] >= bufferDBc[index][p2MaxDBc[index]]) { p2MaxDBc[index] = aBDBc[index]; } bufferDBc[index][aBDBc[index]] = bufferDB0[index][pMaxDB0[index]]; if (aBDBc[index] != TAMBc - 1) { (aBDBc[index] )++; } else { aBDBc[index] = 0; } //Paso de datos al buffer EBc si se ha llenado DBc //if (!firstPass[k] || actEntrada[k] >= (TAMB0*2) + (TAMB0/2) - 2) { //123 //VICTOR: he cambiado esto. if (contador[index] >= (TAMB0 * 2) + (TAMB0 / 2) - 2) { if (aBEBc[index] == pMinEBc[index]) { if (bufferDBc[index][pMaxDBc[index]] > bufferEBc[index][pMinEBc[index]]) { if (p2MinEBc[index] == -1) { bufferEBc[index][aBEBc[index]] = bufferDBc[index][pMaxDBc[index]]; v2aux[index] = INT16_MAX; vaux[index] = bufferEBc[index][TAMBc - 1]; pMinEBc[index] = TAMBc - 1; for (i = TAMBc - 2; i >= 0; i--) { if (bufferEBc[index][i] < vaux[index]) { v2aux[index] = vaux[index]; vaux[index] = bufferEBc[index][i]; p2MinEBc[index] = pMinEBc[index]; pMinEBc[index] = i; } else if (bufferEBc[index][i] < v2aux[index]) { v2aux[index] = bufferEBc[index][i]; p2MinEBc[index] = i; } } // return 0; } else if (bufferDBc[index][pMaxDBc[index]] > bufferEBc[index][p2MinEBc[index]]) { pMinEBc[index] = p2MinEBc[index]; p2MinEBc[index] = -1; } } } else if (bufferDBc[index][pMaxDBc[index]] <= bufferEBc[index][pMinEBc[index]]) { p2MinEBc[index] = pMinEBc[index]; pMinEBc[index] = aBEBc[index]; } else if (aBEBc[index] == p2MinEBc[index]) { if (bufferDBc[index][pMaxDBc[index]] > bufferEBc[index][p2MinEBc[index]]) { p2MinEBc[index] = -1; } } else if (p2MinEBc[index] != -1 && bufferDBc[index][pMaxDBc[index]] <= bufferEBc[index][p2MinEBc[index]]) { p2MinEBc[index] = aBEBc[index]; } bufferEBc[index][aBEBc[index]] = bufferDBc[index][pMaxDBc[index]]; if (aBEBc[index] != TAMBc - 1) { (aBEBc[index])++; } else { aBEBc[index] = 0; } //Paso de datos al buffer FBc1 si se ha llenado EBc //if (!firstPass[k] || actEntrada[k] >= (TAMB0*3) + (TAMB0/2) - (TAMBcm - TAMB0m) - 3) { //VICTOR: he cambiado esto. if (contador[index] >= (TAMB0 * 3) + (TAMB0 / 2) - (TAMBcm - TAMB0m) - 3) { #if HIGH_FREQ==1 bufferFBc1[index][aBFBc1[index]] = bufferEnt[index][rBEnt[index]] - bufferEBc[index][pMinEBc[index]]; if (aBFBc1[index] != TAMBFB - 1) (aBFBc1[index])++; else aBFBc1[index] = 0; #else storeOutput(bufferEnt[index][rBEnt[index]] - bufferEBc[index][pMinEBc[index]], index); #endif if (rBEnt[index] != TAMBEnt - 1) (rBEnt[index])++; else rBEnt[index] = 0; #if HIGH_FREQ==1 j = indiceB1[index]; if (indiceB1[index] != TAMB1*(TAMB1 - 1)) indiceB1[index] += TAMB1; else indiceB1[index] = 0; min1E[index] = bufferFBc1[index][0] - B1[j]; max1D[index] = bufferFBc1[index][0] + B1[j]; for (component = 1; component < TAMB1; component++) { if (min1E[index]>bufferFBc1[index][component] - B1[j + component]) min1E[index] = bufferFBc1[index][component] - B1[j + component]; if (max1D[index]= 0; j--) { if (bufferFBc1ed[index][j] > vaux[index]) { v2aux[index] = vaux[index]; vaux[index] = bufferFBc1ed[index][j]; p2MaxFBc1ed[index] = pMaxFBc1ed[index]; pMaxFBc1ed[index] = j; } else if (bufferFBc1ed[index][j] > v2aux[index]) { v2aux[index] = bufferFBc1ed[index][j]; p2MaxFBc1ed[index] = j; } } } else if (min1E[index] < bufferFBc1ed[index][p2MaxFBc1ed[index]]) { pMaxFBc1ed[index] = p2MaxFBc1ed[index]; p2MaxFBc1ed[index] = -1; } } } else if (min1E[index] >= bufferFBc1ed[index][pMaxFBc1ed[index]]) { p2MaxFBc1ed[index] = pMaxFBc1ed[index]; pMaxFBc1ed[index] = aFBc1x[index]; } else if (aFBc1x[index] == p2MaxFBc1ed[index]) { if (min1E[index] < bufferFBc1ed[index][p2MaxFBc1ed[index]]) p2MaxFBc1ed[index] = -1; } else if (p2MaxFBc1ed[index] != -1 && min1E[index] >= bufferFBc1ed[index][p2MaxFBc1ed[index]]) { p2MaxFBc1ed[index] = aFBc1x[index]; } bufferFBc1ed[index][aFBc1x[index]] = min1E[index]; if (aFBc1x[index] == pMinFBc1de[index]) { if (max1D[index] > bufferFBc1de[index][pMinFBc1de[index]]) { if (p2MinFBc1de[index] == -1) { bufferFBc1de[index][aFBc1x[index]] = max1D[index]; v2aux[index] = INT16_MAX; vaux[index] = bufferFBc1de[index][TAMBFB - 1]; pMinFBc1de[index] = TAMBFB - 1; for (j = TAMBFB - 2; j >= 0; j--) { if (bufferFBc1de[index][j] < vaux[index]) { v2aux[index] = vaux[index]; vaux[index] = bufferFBc1de[index][j]; p2MinFBc1de[index] = pMinFBc1de[index]; pMinFBc1de[index] = j; } else if (bufferFBc1de[index][j] < v2aux[index]) { v2aux[index] = bufferFBc1de[index][j]; p2MinFBc1de[index] = j; } } } else if (max1D[index] > bufferFBc1de[index][p2MinFBc1de[index]]) { pMinFBc1de[index] = p2MinFBc1de[index]; p2MinFBc1de[index] = -1; } } } else if (max1D[index] <= bufferFBc1de[index][pMinFBc1de[index]]) { p2MinFBc1de[index] = pMinFBc1de[index]; pMinFBc1de[index] = aFBc1x[index]; } else if (aFBc1x[index] == p2MinFBc1de[index]) { if (max1D[index] > bufferFBc1de[index][p2MinFBc1de[index]]) p2MinFBc1de[index] = -1; } else if (p2MinFBc1de[index] != -1 && max1D[index] <= bufferFBc1de[index][p2MinFBc1de[index]]) p2MinFBc1de[index] = aFBc1x[index]; bufferFBc1de[index][aFBc1x[index]] = max1D[index]; if (aFBc1x[index] != TAMBFB - 1) (aFBc1x[index])++; else aFBc1x[index] = 0; storeOutput((bufferFBc1ed[index][pMaxFBc1ed[index]] + bufferFBc1de[index][pMinFBc1de[index]]) >> 1, index); #endif //HIGH_FREQ==1 } //Si no esta lleno el bufferDBc //Llenamos el bufferEBc con los valores de DBc en la diferencia } else if (aBDBc[index] <= TAMBcm) { storeOutput(bufferEnt[index][rBEnt[index]] - bufferDBc[index][aBDBc[index] - 1], index); #if HIGH_FREQ==1 bufferFBc1[index][aBFBc1[index]] = bufferEnt[index][rBEnt[index]] - bufferDBc[index][aBDBc[index] - 1]; #else storeOutput(bufferEnt[index][rBEnt[index]] - bufferDBc[index][aBDBc[index] - 1], index); #endif if (rBEnt[index] != TAMBEnt - 1) (rBEnt[index])++; else rBEnt[index] = 0; #if HIGH_FREQ==1 if (aBFBc1[index] != TAMBFB - 1) (aBFBc1[index])++; else aBFBc1[index] = 0; if (bufferDBc[index][aBDBc[index] - 1] <= bufferEBc[index][pMinEBc[index]]) { p2MinEBc[index] = pMinEBc[index]; pMinEBc[index] = aBEBc[index]; } else if (p2MinEBc[index] != -1 && bufferDBc[index][aBDBc[index] - 1] <= bufferEBc[index][p2MinEBc[index]]) p2MinEBc[index] = aBEBc[index]; bufferEBc[index][aBEBc[index]] = bufferDBc[index][aBDBc[index] - 1]; (aBEBc[index])++; j = indiceB1[index]; if (indiceB1[index] != TAMB1*(TAMB1 - 1)) indiceB1[index] += TAMB1; else indiceB1[index] = 0; min1E[index] = bufferFBc1[index][0] - B1[j]; max1D[index] = bufferFBc1[index][0] + B1[j]; for (component = 1; componentbufferFBc1[index][component] - B1[j + component] ? bufferFBc1[index][component] - B1[j + component] : min1E[index]; max1D[index] = max1D[index]= 0; j--) { if (bufferFBc1ed[index][j] > vaux[index]) { v2aux[index] = vaux[index]; vaux[index] = bufferFBc1ed[index][j]; p2MaxFBc1ed[index] = pMaxFBc1ed[index]; pMaxFBc1ed[index] = j; } else if (bufferFBc1ed[index][j] > v2aux[index]) { v2aux[index] = bufferFBc1ed[index][j]; p2MaxFBc1ed[index] = j; } } } else if (min1E[index] < bufferFBc1ed[index][p2MaxFBc1ed[index]]) { pMaxFBc1ed[index] = p2MaxFBc1ed[index]; p2MaxFBc1ed[index] = -1; } } } else if (min1E[index] >= bufferFBc1ed[index][pMaxFBc1ed[index]]) { p2MaxFBc1ed[index] = pMaxFBc1ed[index]; pMaxFBc1ed[index] = aFBc1x[index]; } else if (aFBc1x[index] == p2MaxFBc1ed[index]) { if (min1E[index] < bufferFBc1ed[index][p2MaxFBc1ed[index]]) p2MaxFBc1ed[index] = -1; } else if (p2MaxFBc1ed[index] != -1 && min1E[index] >= bufferFBc1ed[index][p2MaxFBc1ed[index]]) p2MaxFBc1ed[index] = aFBc1x[index]; bufferFBc1ed[index][aFBc1x[index]] = min1E[index]; if (aFBc1x[index] == pMinFBc1de[index]) { if (max1D[index] > bufferFBc1de[index][pMinFBc1de[index]]) { if (p2MinFBc1de[index] == -1) { bufferFBc1de[index][aFBc1x[index]] = max1D[index]; v2aux[index] = INT16_MAX; vaux[index] = bufferFBc1de[index][TAMBFB - 1]; pMinFBc1de[index] = TAMBFB - 1; for (j = TAMBFB - 2; j >= 0; j--) { if (bufferFBc1de[index][j] < vaux[index]) { v2aux[index] = vaux[index]; vaux[index] = bufferFBc1de[index][j]; p2MinFBc1de[index] = pMinFBc1de[index]; pMinFBc1de[index] = j; } else if (bufferFBc1de[index][j] < v2aux[index]) { v2aux[index] = bufferFBc1de[index][j]; p2MinFBc1de[index] = j; } } } else if (max1D[index] > bufferFBc1de[index][p2MinFBc1de[index]]) { pMinFBc1de[index] = p2MinFBc1de[index]; p2MinFBc1de[index] = -1; } } } else if (max1D[index] <= bufferFBc1de[index][pMinFBc1de[index]]) { p2MinFBc1de[index] = pMinFBc1de[index]; pMinFBc1de[index] = aFBc1x[index]; } else if (aFBc1x[index] == p2MinFBc1de[index]) { if (max1D[index] > bufferFBc1de[index][p2MinFBc1de[index]]) p2MinFBc1de[index] = -1; } else if (p2MinFBc1de[index] != -1 && max1D[index] <= bufferFBc1de[index][p2MinFBc1de[index]]) p2MinFBc1de[index] = aFBc1x[index]; bufferFBc1de[index][aFBc1x[index]] = max1D[index]; if (aFBc1x[index] != TAMBFB - 1) (aFBc1x[index])++; else aFBc1x[index] = 0; storeOutput((bufferFBc1ed[index][pMaxFBc1ed[index]] + bufferFBc1de[index][pMinFBc1de[index]]) >> 1, index); #endif //HIGH_FREQ==1 } } }//while } int16_t filterSample(int16_t offset, int16_t read_data, int16_t index) { if (offset < TAMB0) { initBuffers(offset, read_data, index); } else { fill_in_filter(read_data, index); proceso(index); } return bufferSalida[index][0]; } void filterWindows(int32_t *arg[]) { int16_t off; int16_t *ecg_buffer = (int16_t*) arg[0]; int32_t *flag = arg[1]; int16_t *i_lead = (int16_t*) arg[2]; int32_t *bufferSize = arg[3]; if(*flag == 0){ off = 0; } else { off = TAMB0; } for(int indsample = 0; indsample<*bufferSize; indsample++) { - ecg_buffer[indsample + (dim+LONG_WINDOW) * (*i_lead)] = filterSample(off, ecg_buffer[indsample + (dim+LONG_WINDOW) * (*i_lead)], (*i_lead)); + ecg_buffer[indsample + (DIM+LONG_WINDOW) * (*i_lead)] = filterSample(off, ecg_buffer[indsample + (DIM+LONG_WINDOW) * (*i_lead)], (*i_lead)); off++; } } diff --git a/PULP/REWARD_R_peak_detection/peakDetection.c b/PULP/REWARD_R_peak_detection/peakDetection.c index 5a875c3..6cd08c4 100755 --- a/PULP/REWARD_R_peak_detection/peakDetection.c +++ b/PULP/REWARD_R_peak_detection/peakDetection.c @@ -1,407 +1,407 @@ #include "peakDetection.h" #include "rt/rt_api.h" #define ABS(X) ((X<0)?(-X):(X)) //Variables used to detect peaks RT_L2_DATA int32_t lastPeakIndex = 0; RT_L2_DATA int16_t lastPeakAmplitude = 0; RT_L2_DATA uint32_t numberOfAnalyzedWindows = 0; RT_L2_DATA uint8_t lastPeakWasIncomplete = 0; RT_L2_DATA uint16_t lastPeakWidth = INT16_MAX; RT_L2_DATA int32_t lastPeakIndex_BF = 0; RT_L2_DATA int16_t lastPeakWidth_BF = 0; RT_L2_DATA int16_t lastPeakAmplitude_BF = 0; void maxAndMinandMean(int16_t ecg[BUFFER_SIZE], int16_t* max, int16_t* min, int32_t* avg) { *max = ecg[0]; *min = ecg[0]; for (int16_t i = 1; i < BUFFER_SIZE; i++) { *avg += ecg[i]; if (ecg[i] > *max) { *max = ecg[i]; continue; } if (ecg[i] < *min) { *min = ecg[i]; } } *avg = *avg / (BUFFER_SIZE); } void maxAndMin(int16_t ecg[BUFFER_SIZE], int16_t* max, int16_t* min) { *max = ecg[0]; *min = ecg[0]; for (int16_t i = 1; i < BUFFER_SIZE; i++) { if (ecg[i] > *max) { *max = ecg[i]; continue; } if (ecg[i] < *min) { *min = ecg[i]; } } } //Get the index of the maximum value within a certain range of ecg values in the window int32_t getIndexOfMaxInRange(int16_t ecg[BUFFER_SIZE], uint16_t startIndex, uint16_t stopIndex) { int32_t result = 0; int16_t maxEcg = -9999; for (int16_t i = startIndex; i < stopIndex; i++) { if (ecg[i] > maxEcg) { maxEcg = ecg[i]; result = i; } } return result; } int32_t getIndexOfMinInRange(int16_t ecg[BUFFER_SIZE], uint16_t startIndex, uint16_t stopIndex) { int32_t result = 0; int16_t minEcg = INT16_MAX; for (int16_t i = startIndex; i < stopIndex; i++) { if (ecg[i] < minEcg) { minEcg = ecg[i]; result = i; } } return result; } void resetPeakDetection() { lastPeakIndex = 0; lastPeakAmplitude = 0; numberOfAnalyzedWindows = 0; lastPeakWasIncomplete = 0; lastPeakIndex_BF = 0; lastPeakWidth_BF = 0; lastPeakAmplitude_BF = 0; lastPeakWidth = INT16_MAX; } //Get the indices of the R peaks using a hysteresis comparator (using two thresholds to determine where peaks are located) //Inputs: ecgWindow - a window of the ECG // lastPeakIndex - the index of the peak located at the last index of the previous window // lastPeakAmplitude - amplitude of the aforementioned peak // numberOfAnalyzedWindows - the number of windows that have been analyzed so far. Used to compute peak indices relative to the beginning of the signal //Output: array of peak indices void getPeakIndicesThroughHysteresisComparator(int16_t ecgWindow[BUFFER_SIZE], uint8_t numberOfFoundPeaks, int32_t *output, int32_t offset_ind) { numberOfFoundPeaks = 0; uint8_t thisWindowIsIncomplete = 0; int32_t tempOutput[TEMPORARY_PEAK_BUFFER_SIZE]; //temporary indices of all found peaks before the false peaks are removed int16_t peakAmplitudes[TEMPORARY_PEAK_BUFFER_SIZE]; //amplitudes of found peaks, used to detect false positives int16_t peakWidths[TEMPORARY_PEAK_BUFFER_SIZE]; //Index and amplitude of the last peak of the previous window int32_t lastPeakIndexTemp = lastPeakIndex; int16_t lastPeakAmplitudeTemp = lastPeakAmplitude; //Generate the hysteresis thresholds int32_t avg = 0; int16_t max = 0; int16_t min = 0; maxAndMinandMean(ecgWindow, &max, &min, &avg); //Initializing output buffer for (int32_t i = 0;i < MAX_BEATS_PER_MIN;i++) tempOutput[i] = 0; uint16_t numberOfAnalyzedPeaks = 0; //# of detected peaks by the algorithm uint16_t peakWidth; //peak width used in the T wave check #ifdef NEGATIVE_PEAK if ( (ABS(max - avg)) < (TH_NEGATIVE_PEAK*ABS(min - avg))/100) { //Negative peak int16_t lowerThreshold = avg - (BIG_THRESHOLD * ABS(min - avg))/100; int16_t upperThreshold = avg - (SMALL_THRESHOLD * ABS(min - avg))/100; #ifdef PRINT_THR for(int32_t i_t = 0; i_t upperThreshold) { //end of a peak endIndex = i; analyzingPeak = 0; //There is a previous peak that needs to be finished if (startIndex < 0.03*ECG_SAMPLING_FREQUENCY && lastPeakWasIncomplete == 1 && numberOfAnalyzedPeaks == 0) { minIndex = getIndexOfMinInRange(ecgWindow, startIndex, endIndex); peakWidth = lastPeakWidth + endIndex - startIndex; if (ecgWindow[minIndex] < lastPeakAmplitudeTemp) { //this peak is "more negative" than the previous one tempOutput[numberOfAnalyzedPeaks] = minIndex + offset_ind; peakAmplitudes[numberOfAnalyzedPeaks] = ecgWindow[minIndex]; } else { //last peak amplitude was "more negative" - tempOutput[numberOfAnalyzedPeaks] = lastPeakIndexTemp + offset_ind - dim; + tempOutput[numberOfAnalyzedPeaks] = lastPeakIndexTemp + offset_ind - DIM; peakAmplitudes[numberOfAnalyzedPeaks] = lastPeakAmplitudeTemp; } peakWidths[numberOfAnalyzedPeaks] = peakWidth; numberOfAnalyzedPeaks++; }//The previous peak finished at the boundary and its value needs to be recorded else if (lastPeakWasIncomplete == 1 && numberOfAnalyzedPeaks == 0) { //Save previous peak - tempOutput[numberOfAnalyzedPeaks] = lastPeakIndexTemp + offset_ind - dim; + tempOutput[numberOfAnalyzedPeaks] = lastPeakIndexTemp + offset_ind - DIM; peakAmplitudes[numberOfAnalyzedPeaks] = lastPeakAmplitudeTemp; peakWidths[numberOfAnalyzedPeaks] = lastPeakWidth; numberOfAnalyzedPeaks++; //Save new peak minIndex = getIndexOfMinInRange(ecgWindow, startIndex, endIndex); peakWidth = endIndex - startIndex; tempOutput[numberOfAnalyzedPeaks] = minIndex + offset_ind; peakAmplitudes[numberOfAnalyzedPeaks] = ecgWindow[minIndex]; peakWidths[numberOfAnalyzedPeaks] = peakWidth; numberOfAnalyzedPeaks++; } else {//We do not need to care about previous peaks minIndex = getIndexOfMinInRange(ecgWindow, startIndex, endIndex); peakWidth = endIndex - startIndex; tempOutput[numberOfAnalyzedPeaks] = minIndex+ offset_ind; peakAmplitudes[numberOfAnalyzedPeaks] = ecgWindow[minIndex]; peakWidths[numberOfAnalyzedPeaks] = peakWidth; numberOfAnalyzedPeaks++; } } else if (analyzingPeak == 1 && i == BUFFER_SIZE - 1) { //peak is being analyzed when window ends minIndex = getIndexOfMinInRange(ecgWindow, startIndex, BUFFER_SIZE); lastPeakAmplitude = ecgWindow[minIndex]; lastPeakIndex = minIndex; lastPeakWidth = BUFFER_SIZE - 1 - startIndex; thisWindowIsIncomplete = 1; } } } else { //Positive peak #endif /*======================== POSITIVE PEAK ALWAYS RUN: START ========================*/ int16_t lowerThreshold = avg + (SMALL_THRESHOLD * (max - avg))/100; int16_t upperThreshold = avg + (BIG_THRESHOLD * (max - avg))/100; #ifdef PRINT_THR printf("%d\t%d\n",(int32_t)lowerThreshold,(int32_t)upperThreshold); #endif uint8_t analyzingPeak = 0; //boolean indicating if a peak is being analyzed uint16_t startIndex = 0; //start index of analyzed peak uint16_t endIndex = 0; //end index of analyzed peak int32_t maxIndex = 0; //index of a local maximum (for positive peaks) //Loop through Xecg for (uint16_t i = 0; i < BUFFER_SIZE; i++) { #ifdef PRINT_SIG_INPUT_PEAKS printf("%d\n", ecgWindow[i]); #endif if (ecgWindow[i] >= upperThreshold && analyzingPeak == 0) { //beginning of a peak startIndex = i; analyzingPeak = 1; } else if (analyzingPeak == 1 && ecgWindow[i] <= lowerThreshold) { //end of a peak endIndex = i; analyzingPeak = 0; //There is a previous peak that needs to be finished if (startIndex < 0.03*ECG_SAMPLING_FREQUENCY && lastPeakWasIncomplete == 1 && numberOfAnalyzedPeaks == 0) { maxIndex = getIndexOfMaxInRange(ecgWindow, startIndex, endIndex); peakWidth = lastPeakWidth + endIndex - startIndex; if (ecgWindow[maxIndex] > lastPeakAmplitudeTemp) { //this peak is greater than the previous one tempOutput[numberOfAnalyzedPeaks] = maxIndex + offset_ind; peakAmplitudes[numberOfAnalyzedPeaks] = ecgWindow[maxIndex]; } else { //last peak amplitude was greater - tempOutput[numberOfAnalyzedPeaks] = lastPeakIndexTemp + offset_ind - dim; + tempOutput[numberOfAnalyzedPeaks] = lastPeakIndexTemp + offset_ind - DIM; peakAmplitudes[numberOfAnalyzedPeaks] = lastPeakAmplitudeTemp; } peakWidths[numberOfAnalyzedPeaks] = peakWidth; numberOfAnalyzedPeaks++; lastPeakWidth = peakWidth; }//The previous peak finished at the boundary and its value needs to be recorded else if (lastPeakWasIncomplete == 1 && numberOfAnalyzedPeaks == 0) { //Save previous peak - tempOutput[numberOfAnalyzedPeaks] = lastPeakIndexTemp + offset_ind - dim; + tempOutput[numberOfAnalyzedPeaks] = lastPeakIndexTemp + offset_ind - DIM; peakAmplitudes[numberOfAnalyzedPeaks] = lastPeakAmplitudeTemp; peakWidths[numberOfAnalyzedPeaks] = lastPeakWidth; numberOfAnalyzedPeaks++; //Save new peak maxIndex = getIndexOfMaxInRange(ecgWindow, startIndex, endIndex); peakWidth = endIndex - startIndex; tempOutput[numberOfAnalyzedPeaks] = maxIndex + offset_ind; peakAmplitudes[numberOfAnalyzedPeaks] = ecgWindow[maxIndex]; peakWidths[numberOfAnalyzedPeaks] = peakWidth; numberOfAnalyzedPeaks++; } else {//We do not need to care about previous peaks maxIndex = getIndexOfMaxInRange(ecgWindow, startIndex, endIndex); peakWidth = endIndex - startIndex; tempOutput[numberOfAnalyzedPeaks] = maxIndex + offset_ind; peakAmplitudes[numberOfAnalyzedPeaks] = ecgWindow[maxIndex]; peakWidths[numberOfAnalyzedPeaks] = peakWidth; numberOfAnalyzedPeaks++; } } else if (analyzingPeak == 1 && i == BUFFER_SIZE - 1) { //peak is being analyzed when window ends maxIndex = getIndexOfMaxInRange(ecgWindow, startIndex, BUFFER_SIZE); lastPeakAmplitude = ecgWindow[maxIndex]; lastPeakIndex = maxIndex; lastPeakWidth = BUFFER_SIZE - 1 - startIndex; thisWindowIsIncomplete = 1; } } /*======================== POSITIVE PEAK ALWAYS RUN: END ========================*/ #ifdef NEGATIVE_PEAK } #endif #ifdef PRINT_RPEAKS_BEFORE_T_CHECK for(int i=0; i0){ printf("%d\n",tempOutput[i]); } } #endif //Loop through output to make sure peaks are far enough away from one another if (numberOfAnalyzedPeaks > 1) { //add last peak of the previous BS if(numberOfAnalyzedWindows>0){ for(int32_t i = numberOfAnalyzedPeaks; i > 0; i--){ tempOutput[i] = tempOutput[i-1]; peakWidths[i] = peakWidths[i-1]; peakAmplitudes[i] = peakAmplitudes[i-1]; } numberOfAnalyzedPeaks++; tempOutput[0] = lastPeakIndex_BF; peakWidths[0] = lastPeakWidth_BF; peakAmplitudes[0] = lastPeakAmplitude_BF; } for (int16_t j = (numberOfAnalyzedPeaks - 1); j > 0; j--) { int16_t diff_peaks = tempOutput[j] - tempOutput[j - 1]; if (diff_peaks >= NORMAL_PEAKS_DISTANCE) { //peaks are more than 0.5 seconds apart //All is well } else { if (diff_peaks >= MIN_PEAKS_DISTANCE && peakWidths[j] != INT16_MIN && peakAmplitudes[j] != 0) { //select the peak with the lowest width int16_t peakWidthRatio = (peakWidths[j - 1] * 100) / peakWidths[j]; if (peakWidthRatio <= TH_LOW_WIDTH_RATIO || peakWidthRatio >= TH_HIGH_WIDTH_RATIO) { // peaks are not in the same range if (peakWidths[j] < peakWidths[j - 1]) { tempOutput[j - 1] = tempOutput[j]; tempOutput[j] = 0; peakWidths[j - 1] = peakWidths[j]; peakWidths[j] = 0; } else { tempOutput[j] = 0; peakWidths[j] = 0; } } } else { int16_t peakWidthRatio = (peakWidths[j - 1] * 100) / peakWidths[j]; if(peakWidthRatio >= TH_HIGH_WIDTH_RATIO){ tempOutput[j - 1] = tempOutput[j]; tempOutput[j] = 0; peakWidths[j - 1] = peakWidths[j]; peakWidths[j] = 0; }else{ tempOutput[j] = 0; peakWidths[j] = 0; } } } } } //Load temporary result buffer into final output buffer int32_t numberOfActualPeaks = 0; for (int32_t m = 0; m <= numberOfAnalyzedPeaks; m++) { if (tempOutput[m] > 0) { numberOfFoundPeaks = numberOfFoundPeaks + 1; //get rid of redundant variable output[numberOfActualPeaks] = tempOutput[m]; numberOfActualPeaks++; lastPeakIndex_BF = tempOutput[m] ; lastPeakWidth_BF = peakWidths[m]; lastPeakAmplitude_BF = peakAmplitudes[m]; } } lastPeakWasIncomplete = thisWindowIsIncomplete; } uint16_t startnext = 0; void getPeaks_w(int32_t *arg[]){ int16_t* xRE = (int16_t*) arg[0]; int32_t* indicesRpeaks = arg[1]; int32_t* offset_ind = arg[2]; int32_t outputSingleBuff[MAX_BEATS_PER_MIN]; //This should be set to 0 every time we delineate 8 beats startnext = 0; numberOfAnalyzedWindows = 0; uint8_t numberOfDetectedPeaks =0; for(int32_t idx = 0; idx 0) { if (indicesRpeaks[startnext-1] != outputSingleBuff[m]) { indicesRpeaks[startnext] = outputSingleBuff[m]; startnext++; } } } numberOfAnalyzedWindows++; } } diff --git a/PULP/adaptive_Rpeak_detection/adaptiveRpeakDetection.c b/PULP/adaptive_Rpeak_detection/adaptiveRpeakDetection.c index b2e3336..1532bf7 100755 --- a/PULP/adaptive_Rpeak_detection/adaptiveRpeakDetection.c +++ b/PULP/adaptive_Rpeak_detection/adaptiveRpeakDetection.c @@ -1,255 +1,259 @@ #include "adaptiveRpeakDetection.h" #include "../defines.h" #include "../profiling/profile.h" #include "../data/signal.h" #include "../Morph_filt/morpho_filtering.h" #include "../Morph_filt/defines_globals.h" #include "../error_detection/error_detection.h" -#define N_WINDOWS (int) (2*((ECG_VECTOR_SIZE-LONG_WINDOW)/dim)+1)// Counting the worst case scenario when overlap is dim +#define N_WINDOWS (int) (2*((ECG_VECTOR_SIZE-LONG_WINDOW)/DIM)+1)// Counting the worst case scenario when overlap is DIM -RT_L2_DATA int16_t ecg_buff[(LONG_WINDOW+dim)*(NLEADS+1)]; +RT_L2_DATA int16_t ecg_buff[(LONG_WINDOW+DIM)*(NLEADS+1)]; RT_L2_DATA rt_perf_t perf[NUM_CORES]; #ifdef MODULE_MF RT_L2_DATA int32_t *argMF[4]; RT_L2_DATA int32_t buffSize_windowMF; #endif #ifdef MODULE_RELEN RT_L2_DATA int32_t *argRelEn[4]; RT_L2_DATA int32_t start_RelEn = 1; RT_L2_DATA int32_t buffSize_windowRelEn; #endif #ifdef MODULE_RPEAK_REWARD RT_L2_DATA int32_t *argRW_Rpeak[3]; RT_L2_DATA int32_t indicesRpeaks[H_B+1]; #endif #ifdef MODULE_ERROR_DETECTION RT_L2_DATA int32_t *argErrDet[5]; RT_L2_DATA int32_t lastRpeak = 0; RT_L2_DATA int32_t lastRR = 0; RT_L2_DATA int32_t error_RWindow = 0; #endif RT_L2_DATA int32_t overlap; RT_L2_DATA int32_t rWindow; void clearRelEn() { clearAndResetRelEn(); resetPeakDetection(); } void adaptiveRpeakDetection(){ int32_t count_sample = 0; int32_t offset_window = 0; int32_t offset_ind = LONG_WINDOW/2+1; int32_t tot_overlap = 0; overlap = 0; #ifdef MODULE_MF int32_t flagMF = 0; int32_t i_lead = 0; - buffSize_windowMF = LONG_WINDOW+dim; + buffSize_windowMF = LONG_WINDOW+DIM; argMF[0] = (int32_t*) ecg_buff; argMF[1] = &flagMF; argMF[2] = &i_lead; argMF[3] = &buffSize_windowMF; init_filtering(); #endif #ifdef MODULE_RELEN - buffSize_windowRelEn = LONG_WINDOW+dim; + buffSize_windowRelEn = LONG_WINDOW+DIM; argRelEn[0] = (int32_t*) ecg_buff; - argRelEn[1] = (int32_t*) &ecg_buff[(LONG_WINDOW+dim)*NLEADS]; + argRelEn[1] = (int32_t*) &ecg_buff[(LONG_WINDOW+DIM)*NLEADS]; argRelEn[2] = &start_RelEn; argRelEn[3] = &buffSize_windowRelEn; clearRelEn(); #endif #ifdef MODULE_RPEAK_REWARD int32_t rpeaks_counter = 0; - argRW_Rpeak[0] = (int32_t*) &ecg_buff[LONG_WINDOW+(LONG_WINDOW + dim)*NLEADS]; + argRW_Rpeak[0] = (int32_t*) &ecg_buff[LONG_WINDOW+(LONG_WINDOW + DIM)*NLEADS]; argRW_Rpeak[1] = indicesRpeaks; argRW_Rpeak[2] = &offset_ind; #endif for(rWindow=0; rWindow= ECG_VECTOR_SIZE){ + if((rWindow+1)*DIM + LONG_WINDOW -1 - tot_overlap >= ECG_VECTOR_SIZE){ return; } if(rWindow > 0){ offset_window = LONG_WINDOW; } else{ offset_window = 0; } if (rWindow > 0) { for(int32_t i=0; i 0) start_RelEn = 0; argRelEn[0] = (int32_t*) &ecg_buff[offset_window + overlap]; - argRelEn[1] = (int32_t*) &ecg_buff[offset_window + (LONG_WINDOW + dim)*NLEADS+overlap]; - buffSize_windowRelEn = LONG_WINDOW - offset_window + dim-overlap; + argRelEn[1] = (int32_t*) &ecg_buff[offset_window + (LONG_WINDOW + DIM)*NLEADS+overlap]; + buffSize_windowRelEn = LONG_WINDOW - offset_window + DIM-overlap; #endif relEn_w(argRelEn); #ifdef HWPERF_MODULES profile_stop(perf); #endif #ifdef PRINT_RELEN - for(int32_t sample = offset_window + (LONG_WINDOW + dim)*NLEADS; sample< (LONG_WINDOW + dim)*(NLEADS+1); sample++) { + for(int32_t sample = offset_window + (LONG_WINDOW + DIM)*NLEADS; sample< (LONG_WINDOW + DIM)*(NLEADS+1); sample++) { printf("%d\n", ecg_buff[sample]); } #endif #endif #ifdef MODULE_RPEAK_REWARD #ifdef HWPERF_MODULE_RPEAK_REWARD || HWPERF_MODULES profile_start(perf); #endif getPeaks_w(argRW_Rpeak); rpeaks_counter = 0; while(indicesRpeaks[rpeaks_counter]!=0) { rpeaks_counter++; } #ifdef HWPERF_MODULE_RPEAK_REWARD || HWPERF_MODULES profile_stop(perf); #endif #ifdef PRINT_RPEAKS for(int32_t indR=0; indR