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
Diff: main.cpp
- Revision:
- 0:025037057a21
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/main.cpp Wed Mar 26 05:44:21 2014 +0000
@@ -0,0 +1,281 @@
+#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
+ }
+}
\ No newline at end of file