Main fish project files

Dependencies:   SDHCFileSystem wave_player

Fork of billy by Steve Ravet

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers main.cpp Source File

main.cpp

00001 
00002 #include "mbed.h"
00003 
00004 //The next two includes are from the SDHC File System
00005  #include "string"
00006  #include "SDHCFileSystem.h"
00007 
00008 #define SAMPLE_FREQ 40000
00009 #define BUF_SIZE (SAMPLE_FREQ/10)
00010 #define SLICE_BUF_SIZE 1
00011 
00012 // include this #define to enable lots of serial output
00013 //#define VERBOSE
00014 
00015 
00016 
00017 typedef struct uFMT_STRUCT {
00018   short comp_code;
00019   short num_channels;
00020   unsigned sample_rate;
00021   unsigned avg_Bps;
00022   short block_align;
00023   short sig_bps;
00024 } FMT_STRUCT;
00025 
00026 
00027 typedef struct uMOV_STRUCT {
00028   long sample;
00029   unsigned motor;
00030   unsigned duty_cycle;
00031   unsigned played;
00032 } MOV_STRUCT;
00033 
00034 // global MBED things
00035 AnalogOut DACout(p18);
00036 DigitalOut led1(LED1);
00037 DigitalOut led2(LED2);
00038 DigitalOut led3(LED3);
00039 DigitalOut led4(LED4);
00040 DigitalOut digout(p8);
00041 DigitalIn pushbutton(p22);
00042 PwmOut body(p25);
00043 PwmOut mouth(p24);
00044 PwmOut tail(p23);
00045 Ticker tick;
00046 SDFileSystem sd(p5, p6, p7, p13, "sd"); 
00047 
00048 // global variables used both by the main program and the ISR
00049 short DAC_fifo[256];    // FIFO for the DAC
00050 short DAC_wptr;            // FIFO pointer
00051 volatile short DAC_rptr;            // FIFO pointer
00052 long slice;
00053 unsigned num_movements;
00054 unsigned current_movement;
00055 MOV_STRUCT movements[500];
00056 
00057 void dac_out(void);
00058 void play_wave(char *,char *,unsigned);
00059 void cleanup(char *);
00060 unsigned process_movement_file (char *mfname, MOV_STRUCT *mv,unsigned samp_rate);
00061 
00062 
00063 int main() {
00064         FILE *cmdfile;
00065         char cmdline[100];
00066         char *movfile,*tmp;
00067         char cmdfile_name[]="/sd/fish.txt";
00068         unsigned slow_mode=0;
00069   if (pushbutton) slow_mode=1;
00070   led1=0; wait(.5); led1=1; wait(.5); led1=0;
00071   printf("\nHello, world!\n");
00072   if (slow_mode) printf("Slooooow mode enabled...\n");
00073   printf("Waiting for button push\n");
00074   while (!pushbutton);
00075   printf("Button pushed\n");
00076   while (1) {
00077     cmdfile=fopen(cmdfile_name,"rb");
00078     if (!cmdfile) {
00079       printf("Unable to open command file '%s'\n",cmdfile_name);
00080       exit(1);
00081     }
00082   
00083     fgets(cmdline,100,cmdfile);
00084     while (!feof(cmdfile)) {
00085       printf("Parsing '%s' from command file '%s'\n",cmdline,cmdfile_name);  
00086       tmp=strchr(cmdline,'#');
00087       if (tmp) *tmp=0;
00088       movfile=strchr(cmdline,' ');
00089       if (movfile) {
00090         *movfile=0;
00091         movfile++;
00092         tmp=strchr(movfile,'\n');
00093         cleanup(movfile);
00094         if (tmp) *tmp=0;
00095 
00096 #ifdef USE_PUSHBUTTON
00097         printf("Waiting for button push\n");
00098         while (!pushbutton);
00099         printf("Button pushed\n");
00100 #else
00101         wait_ms(2000);
00102 #endif
00103         play_wave(cmdline,movfile,slow_mode);
00104         printf("Back from play_wave()\n");
00105       } else {
00106         printf("Unable to parse '%s' from command file '%s'\n",cmdline,cmdfile_name);
00107       }
00108       fgets(cmdline,100,cmdfile);
00109     }
00110     fclose(cmdfile);
00111     printf("Goodbye, world!\n");
00112   }
00113 }
00114   
00115 void play_wave(char *wavname,char *movname,unsigned slow)
00116 {
00117         unsigned chunk_id,chunk_size,channel;
00118         unsigned data,samp_int,i;
00119         short dac_data;
00120         char *slice_buf;
00121         short *data_sptr;
00122         unsigned char *data_bptr;
00123         int *data_wptr;
00124         FMT_STRUCT wav_format;
00125         FILE *wavfile;
00126         long num_slices;
00127         long long slice_value;
00128         int verbosity=0;
00129   DAC_wptr=0;
00130   DAC_rptr=0;
00131   for (i=0;i<256;i+=2) {
00132     DAC_fifo[i]=0;
00133     DAC_fifo[i+1]=3000;
00134   }
00135   DAC_wptr=4;
00136 
00137   body.period_us(100);
00138   mouth.period_us(100);
00139   tail.period_us(100);
00140   led1=led2=led3=led4=0;
00141   
00142   printf("Playing wave file '%s', mov file '%s'\n",wavname,movname);
00143 
00144   wavfile=fopen(wavname,"rb");
00145   if (!wavfile) {
00146     printf("Unable to open wav file '%s'\n",wavname);
00147     return;
00148   }
00149 
00150 
00151   fread(&chunk_id,4,1,wavfile);
00152   fread(&chunk_size,4,1,wavfile);
00153   while (!feof(wavfile)) {
00154     printf("Read chunk ID 0x%x, size 0x%x\n",chunk_id,chunk_size);
00155     switch (chunk_id) {
00156       case 0x46464952:
00157         fread(&data,4,1,wavfile);
00158         printf("RIFF chunk\n");
00159         printf("  chunk size %d (0x%x)\n",chunk_size,chunk_size);
00160         printf("  RIFF type 0x%x\n",data);
00161         break;
00162       case 0x20746d66:
00163         fread(&wav_format,sizeof(wav_format),1,wavfile);
00164         printf("FORMAT chunk\n");
00165         printf("  chunk size %d (0x%x)\n",chunk_size,chunk_size);
00166         printf("  compression code %d\n",wav_format.comp_code);
00167         printf("  %d channels\n",wav_format.num_channels);
00168         printf("  %d samples/sec\n",wav_format.sample_rate);
00169         printf("  %d bytes/sec\n",wav_format.avg_Bps);
00170         printf("  block align %d\n",wav_format.block_align);
00171         printf("  %d bits per sample\n",wav_format.sig_bps);
00172         if (chunk_size > sizeof(wav_format))
00173           fseek(wavfile,chunk_size-sizeof(wav_format),SEEK_CUR);
00174 // create a slice buffer large enough to hold multiple slices
00175         slice_buf=(char *)malloc(wav_format.block_align*SLICE_BUF_SIZE);
00176         if (!slice_buf) {
00177           printf("Unable to malloc slice buffer");
00178           exit(1);
00179         }
00180 // now that the sample rate is known, process the movement file
00181         num_movements=process_movement_file(movname,movements,wav_format.sample_rate);
00182         break;
00183 
00184       case 0x61746164:
00185         slice_buf=(char *)malloc(wav_format.block_align*SLICE_BUF_SIZE);
00186         if (!slice_buf) {
00187           printf("Unable to malloc slice buffer");
00188           exit(1);
00189         }        num_slices=chunk_size/wav_format.block_align;
00190         printf("DATA chunk\n");
00191         printf("  chunk size %d (0x%x)\n",chunk_size,chunk_size);
00192         printf("  %d slices\n",num_slices);
00193         printf("  Ideal sample interval=%d\n",(unsigned)(1000000.0/wav_format.sample_rate));
00194         samp_int=1000000/(wav_format.sample_rate);
00195         if (slow) samp_int*=1.5;
00196         printf("  programmed interrupt tick interval=%d\n",samp_int);
00197 
00198 // starting up ticker to write samples out -- no printfs until tick.detach is called
00199         current_movement=0;
00200         tick.attach_us(&dac_out, samp_int); 
00201         led2=1;
00202         for (slice=0;slice<num_slices;slice+=SLICE_BUF_SIZE) {
00203           fread(slice_buf,wav_format.block_align*SLICE_BUF_SIZE,1,wavfile);
00204           if (feof(wavfile)) {
00205             printf("Oops -- not enough slices in the wave file\n");
00206             exit(1);
00207           }
00208           data_sptr=(short *)slice_buf;
00209           data_bptr=(unsigned char *)slice_buf;
00210           data_wptr=(int *)slice_buf;
00211           slice_value=0;
00212           for (i=0;i<SLICE_BUF_SIZE;i++) {
00213             for (channel=0;channel<wav_format.num_channels;channel++) {
00214               switch (wav_format.sig_bps) {
00215               case 16:
00216                 if (verbosity)
00217                   printf("16 bit channel %d data=%d ",channel,data_sptr[channel]);
00218                 slice_value+=data_sptr[channel];
00219                 break;
00220               case 32:
00221                 if (verbosity)
00222                   printf("32 bit channel %d data=%d ",channel,data_wptr[channel]);
00223                 slice_value+=data_wptr[channel];
00224                 break;
00225               case 8:
00226                 if (verbosity)
00227                   printf("8 bit channel %d data=%d ",channel,(int)data_bptr[channel]);
00228                 slice_value+=data_bptr[channel];
00229                 break;
00230               }
00231             }
00232             slice_value/=wav_format.num_channels;
00233 
00234 // slice_value is now averaged.  Next it needs to be scaled to an unsigned 16 bit value
00235 // with DC offset so it can be written to the DAC.
00236             switch (wav_format.sig_bps) {
00237               case 8:     slice_value<<=8;
00238                           break;
00239               case 16:    slice_value+=32768;
00240                           break;
00241               case 32:    slice_value>>=16;
00242                           slice_value+=32768;
00243                           break;
00244             }
00245             dac_data=(short unsigned )slice_value;
00246             if (verbosity)
00247               printf("sample %d wptr %d slice_value %d dac_data %u\n",slice,DAC_wptr,(int)slice_value,dac_data);
00248 
00249 // finally stick it in the DAC FIFO.  If the write pointer wraps around and meets the read pointer
00250 // the wait until the read pointer moves.
00251             DAC_fifo[DAC_wptr]=dac_data;
00252             DAC_wptr=(DAC_wptr+1) & 0xff;
00253             while (DAC_wptr==DAC_rptr) {
00254             }
00255           }
00256         }
00257         led2=0;
00258 // wait for ISR to drain FIFO
00259         wait_us(300);
00260         tick.detach();
00261         printf("Ticker detached\n");
00262         led3=1;
00263         free(slice_buf);
00264         break;
00265       case 0x5453494c:
00266         printf("INFO chunk, size %d\n",chunk_size);
00267         fseek(wavfile,chunk_size,SEEK_CUR);
00268         break;
00269       default:
00270         printf("unknown chunk type 0x%x, size %d\n",chunk_id,chunk_size);
00271         data=fseek(wavfile,chunk_size,SEEK_CUR);
00272         break;
00273     }
00274     fread(&chunk_id,4,1,wavfile);
00275     fread(&chunk_size,4,1,wavfile);
00276   }
00277   printf("Done with wave file\n");
00278   fclose(wavfile);
00279   led1=0;
00280   body.pulsewidth_us(0);
00281   mouth.pulsewidth_us(0);
00282   tail.pulsewidth_us(0);
00283 }
00284 
00285 
00286 void dac_out() {
00287  // This line declared but not used       int value;
00288     digout=1;
00289     if (!movements[current_movement].played) {
00290         if (movements[current_movement].sample<=slice) {
00291             if (movements[current_movement].motor==0) body.pulsewidth_us(movements[current_movement].duty_cycle);
00292             if (movements[current_movement].motor==1) mouth.pulsewidth_us(movements[current_movement].duty_cycle);
00293             if (movements[current_movement].motor==2) tail.pulsewidth_us(movements[current_movement].duty_cycle);
00294             movements[current_movement].played=1;
00295             current_movement++;
00296         }
00297     }
00298     DACout.write_u16(DAC_fifo[DAC_rptr]);
00299     DAC_rptr=(DAC_rptr+1) & 0xff;
00300     digout=0;
00301 }
00302 
00303 
00304 void cleanup(char *s)
00305 {
00306         char *t;
00307   t=strchr(s,'\n');
00308   if (t) *t=0;
00309   t=strchr(s,'\r');
00310   if (t) *t=0;
00311 }        
00312 
00313 unsigned process_movement_file (char *mfname, MOV_STRUCT *mv,unsigned samp_rate)
00314 {
00315         FILE *movfile;
00316         char line[100],*tmp;
00317         unsigned num_movements,i,j,x;
00318   movfile=fopen(mfname,"rb");
00319   if (!movfile) {
00320     printf("Unable to open mov file '%s'\n",mfname);
00321     return 0;
00322   }
00323   
00324   fgets(line,100,movfile);
00325   num_movements=0;
00326 #ifdef VERBOSE
00327   printf("Motor report...\n");
00328 #endif
00329   while (!feof(movfile)) {
00330     if (line[0]!='#') {
00331       tmp=line;
00332 // first thing on line is time in ms
00333       movements[num_movements].sample=(atol(tmp)*samp_rate)/1000;
00334 // skip digits (non whitespace)
00335       tmp=line;
00336       while (*tmp!=' ' && *tmp!='\t' && *tmp!=0)
00337         tmp++;
00338 // skip whitespace
00339       while ((*tmp==' ' | *tmp=='\t') && *tmp!=0)
00340         tmp++;
00341       if (strstr(tmp,"body"))
00342         movements[num_movements].motor=0;
00343       if (strstr(tmp,"mouth"))
00344         movements[num_movements].motor=1;
00345       if (strstr(tmp,"tail"))
00346         movements[num_movements].motor=2;
00347 // skip letters (non whitespace)
00348       while (*tmp!=' ' && *tmp!='\t')
00349         tmp++;
00350 // skip whitespace
00351       while (*tmp==' ' | *tmp=='\t')
00352         tmp++;
00353       if (tmp)
00354         movements[num_movements].duty_cycle=atoi(tmp);
00355         movements[num_movements].played=0;
00356 #ifdef VERBOSE
00357       printf("  moving motor %d at sample %ld with duty cycle %d\n",movements[num_movements].motor,movements[num_movements].sample,movements[num_movements].duty_cycle);
00358 #endif
00359       num_movements++;
00360     }
00361     fgets(line,100,movfile);
00362   }
00363   printf("  %d movements read\n",num_movements);
00364   printf("  sorting movements...");
00365   for (i=0;i<num_movements;i++) {
00366     for (j=i;j<num_movements;j++) {
00367       if (movements[j].sample < movements[i].sample) {
00368         x=movements[i].sample;    movements[i].sample=movements[j].sample;        movements[j].sample=x;
00369         x=movements[i].motor ;    movements[i].motor =movements[j].motor ;        movements[j].motor =x;
00370         x=movements[i].duty_cycle;movements[i].duty_cycle=movements[j].duty_cycle;movements[j].duty_cycle=x;
00371       }
00372     }
00373   }
00374   printf("done\n");
00375   return num_movements;
00376 }