Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependencies: C12832_lcd crossCorrelation mbed-rtos mbed
main.cpp
- Committer:
- nleoni
- Date:
- 2014-03-26
- Revision:
- 0:025037057a21
File content as of revision 0:025037057a21:
#include "mbed.h"
#include "rtos.h"
#include "C12832_lcd.h"
#include "stdint.h"
#include <string.h>
#include <math.h>
#include <stdio.h>
#define DEBUG
#define SAMPLINGPERIOD 60 //us, 20 us would correspond to a 50 kHz sampling rate
#define EVENTLENGTH 1000//number of sample to collect a full event
#define EVENTLOGSIZE 20 //Events are stored in this log, eventually read and cleared
#define TRIGGERHIGH 0xC000
#define TRIGGERLOW 0x4000
#define PRETRIGSAMPLES 20 //samples to keep prior to trigger time.
#define SAMPLEDELAY 20
#define BUFFER 20 //serial terminal input command buffer
//define signals
#define COMPARESIGNAL 0x01//use this signal to signal the onDAQ thread to check for a trigger.
#define PROCESSINGSIGNAL 0x10 //use this signal to start the processing thread
//There will be a thread checking on error conditions
//this Thread will print to a terminal causes of error conditions and the exit
//the program
//signals related to error conditions
#define NULLPOINTER 0xE1
AnalogIn FLMic(p20),FRMic(p19);
AnalogOut FLMout(p18);
DigitalOut ISRcheck(p26);
DigitalOut circularCheck(p24);
LocalFileSystem local("local"); //use the MBED file system to store debug files
uint16_t FLMbuffer[EVENTLENGTH],FRMbuffer[EVENTLENGTH],flmLastValue,frmLastValue;
float eventLog[2][EVENTLOGSIZE]; //down the line make an event class, and have an array of events.
uint16_t *ptrflm,*ptrflmStart,*ptrfrm,*ptrfrmStart; //These pointers are used to implement a dual circular buffer architecture
int indexMax,delayMax;
int Max;
Ticker audioDAQ;
void acquireISR(void);//ISR routine for acquiring the microphone audio data
Thread *onDAQTrigger;
Thread *processingCrossCorr;
Serial pc(USBTX, USBRX); //serial communication terminal
//define DirMic state type
typedef enum {
ACQUIRING,
TRIGGERED,
PROCESSING,
IDLE //state to enter for debugginr purposes
} DicMicStateType;
DicMicStateType dicMicState;
/******************************************************************
*
*This
*
*******************************************************************/
void readTerminal(void const *args){
int tempLFM,tempRFM,i;
char buffer[BUFFER];
int filecounter;
char *ptrChar;
ptrChar=buffer;
FILE *fp;
char filename[16],outputstr[16];
//Test pointers
uint16_t testbuffer[10];
pc.printf(">Enter a command: (a..arm acquisition; t..trigger acquisition; s..state; r..results)\n>");
filecounter=0;
while(1){
//Note the choice of using getc instead of scanf to read the fortune cookie,
//this is a non-blocking call and allows the rest of our threads to continue operating
//only when a new character is typed this thread executes its body otherwise
//it immediately yields to other threads.
if( pc.readable() ){
*ptrChar=pc.getc();
pc.putc(*ptrChar);
if((*ptrChar=='\n') || ((ptrChar-buffer)>=(BUFFER-1)) ){
if((ptrChar-buffer)>=(BUFFER-1)) *++ptrChar='\n';
*ptrChar='\0';
//Check the entered command
switch(buffer[0]){
case 'a': //arm command, to be used after a trigger event
dicMicState=ACQUIRING;
audioDAQ.attach_us(&acquireISR,200);
#ifdef DEBUG
pc.printf("State is %i\n",dicMicState);
#endif
break;
case 's': //check current state command
pc.printf("State is %i\n>",dicMicState);
break;
case 'r': //check current state command
pc.printf("Last Correlation results: delay=%d\n>",delayMax);
break;
case 'f': //pointer test command
fp=fopen("/local/out.txt", "w");
fprintf(fp, "Hello World!");
fclose(fp);
break;
case 'o': //output file
filecounter++;
sprintf(filename,"/local/data%d.txt",filecounter);
pc.printf("Data file:%s\n>",filename);
fp=fopen(filename, "w"); // Open filename on the local file system for writing
if(fp!=NULL){
for(i=0;i<EVENTLENGTH;i++){
tempLFM=(int)FLMbuffer[i]-0x8000;
tempRFM=(int)FRMbuffer[i]-0x8000;
sprintf(outputstr,"%d,%d%c",tempLFM,tempRFM,13);
pc.printf("%s",outputstr);
fprintf(fp,outputstr);
}//for i loop
fclose(fp);
} else {
pc.printf("Error Opening File\n>");
}//if fp!=null
}//end of switch
pc.printf(">Enter a command: (a..arm acquisition; t..trigger acquisition)\n>");
ptrChar=buffer;
} else {
ptrChar++;
}//if ptrchar... check for buffer overflow
}//if pc readable
//A 100 ms wait seems like reasonable delay which allows operation of the remaining threads.
Thread::wait(100);
}//while(1)
}//thread function
//*****************************************************************************************
//Comparison thread
//This thread is called with a signal from the timer interrupt
//it checks whether a trigger level is exceeded and if so chanegs the state
//to storage
void onDAQ(void const *args){
int sampleCounter=0;
while(1){
Thread::signal_wait(COMPARESIGNAL);
//Here we check if signal exceeded trigger, currently only triggering on one mic
switch(dicMicState){
case ACQUIRING:
if( ( (flmLastValue) > TRIGGERHIGH ) || ( (flmLastValue) < TRIGGERLOW ) ){//signal exceeded trigger
dicMicState=TRIGGERED;
#ifdef DEBUG
pc.printf("State is %i\n>",dicMicState);
#endif
}
sampleCounter=0;
break;
case TRIGGERED:
if(sampleCounter==0) pc.printf("Entered countdown trigger phase\n>");
sampleCounter++;
if(sampleCounter>(EVENTLENGTH-PRETRIGSAMPLES)){
//if(sampleCounter>100){
dicMicState=PROCESSING; //switching states should be done prior to detaching the interrup...
#ifdef DEBUG
pc.printf("State is %i\n>",dicMicState);
Thread::wait(10);
#endif
processingCrossCorr->signal_set(PROCESSINGSIGNAL);
audioDAQ.detach();//detach interrupt, this allows gathering data after the trigger yet leaving PRETRIGSAMPLES before trigger time
}
break;
}
}
}
//Processing thread
void crossCorrelationThread(void const *args){
int i,j,k,ndelays,delay;
ndelays=2*SAMPLEDELAY+1;
int correlationArray[ndelays],tempLFM,tempRFM;
//This thread waits for the processing signal and then perform one correlation calculation
//This very simple cross correlation will for the time being have no Thread::wait....as it runs alone
while(1){
Thread::signal_wait(PROCESSINGSIGNAL);
Max=0; //Store max computed value of correlation
indexMax=0;
delayMax=2*SAMPLEDELAY;//safe value to know if it did not run
for(j=0;j<ndelays;j++){
correlationArray[j]=0;
delay=-SAMPLEDELAY+j;
for(i=0;i<EVENTLENGTH;i++){
//compute k
k=i+delay;
if(k<0) k=EVENTLENGTH+k;
if(k>(EVENTLENGTH-1)) k=k-EVENTLENGTH;
tempLFM=(int)FLMbuffer[i]-0x8000;
tempRFM=(int)FRMbuffer[k]-0x8000;
correlationArray[j]+=tempLFM*tempRFM;
} //end of for i
if(correlationArray[j]>Max){
Max=correlationArray[j];
indexMax=j;
delayMax=delay;
}
#ifdef DEBUG//debugging printout of calculated correlation values
pc.printf("Correlation[%i]=%.0f\n>",j,(double)correlationArray[j]);
pc.printf("Max=%.0f\n>",(double)Max);
pc.printf("delayMax=%.0f\n>",(double)delayMax);
#endif
}//end of for j loop
pc.printf("Correlation results: delay=%i\n>",delayMax);
#ifdef DEBUG
dicMicState=IDLE;//processing is done set to idle until manually armed
#else
dicMicState=ACQUIRING; //the systems goes back to aqcuiring after finished processing
audioDAQ.attach_us(&acquireISR,SAMPLINGPERIOD);
#endif
}//end of while loop for thread
}
int main() {
pc.printf("Directional Microphone\n");
audioDAQ.attach_us(&acquireISR,SAMPLINGPERIOD);
ptrflm=FLMbuffer;
ptrfrm=FRMbuffer;
dicMicState=IDLE;
#ifdef DEBUG
pc.printf("State is %i\n",dicMicState);
#endif
Thread thread(onDAQ);
onDAQTrigger=&thread;
Thread thread2(crossCorrelationThread);
processingCrossCorr=&thread2;
Thread thread3(readTerminal);
while(1) {
}
}
void acquireISR(void){
if(dicMicState==ACQUIRING || dicMicState==TRIGGERED ){
#ifdef DEBUG
ISRcheck=1;
#endif
if(ptrflm && ptrfrm){//check if pointer not null
//Note that two calls to read_u16 take overall 50 us!!!
*ptrflm=FLMic.read_u16();
flmLastValue=*ptrflm;
#ifdef DEBUG
FLMout.write_u16(*ptrflm);
#endif
*ptrfrm=FRMic.read_u16();
frmLastValue=*ptrfrm;
if( ((ptrflm-FLMbuffer)) >= (EVENTLENGTH-1) ){
ptrflm=FLMbuffer;//here we should wrap the pointer around the eventlength
ptrfrm=FRMbuffer;
#ifdef DEBUG//Confirm that pointer wraps to beginning of array
//Test passed!
circularCheck=!circularCheck;
#endif
} else {
ptrflm++;
ptrfrm++;
}
} else {
onDAQTrigger->signal_set(NULLPOINTER);
exit(1);
}
onDAQTrigger->signal_set(COMPARESIGNAL);
#ifdef DEBUG
ISRcheck=0;
#endif
}
}