Tommi Laurila / Mbed 2 deprecated Billy2

Dependencies:   EthernetNetIf mbed

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers main.cpp Source File

main.cpp

00001 
00002 
00003 #include "mbed.h"
00004 #include "SDHCFileSystem.h"
00005 #include "HTTPClient.h"
00006 #include "EthernetNetIf.h"
00007 
00008 #define SAMPLE_FREQ 40000
00009 #define BUF_SIZE (SAMPLE_FREQ/10)
00010 #define SLICE_BUF_SIZE 1
00011 
00012 typedef struct uFMT_STRUCT {
00013     short comp_code;
00014     short num_channels;
00015     unsigned sample_rate;
00016     unsigned avg_Bps;
00017     short block_align;
00018     short sig_bps;
00019 } FMT_STRUCT;
00020 
00021 short DAC_fifo[256];
00022 short DAC_wptr;
00023 short DAC_rptr;
00024 short DAC_on;
00025 
00026 DigitalOut led1(LED1);
00027 DigitalOut led2(LED2);
00028 DigitalOut led3(LED3);
00029 DigitalOut led4(LED4);
00030 
00031 SDFileSystem sd(p5, p6, p7, p13, "sd");
00032 
00033 EthernetNetIf eth;
00034 HTTPClient http;
00035 
00036 void download_bmf(void);
00037 void load_lipsync(char[]);
00038 void mouth(void);
00039 
00040 void dac_out(void);
00041 void dingdong(void);
00042 
00043 void body_move(int);
00044 void tail_flap(int);
00045 
00046 int dl(char[], char[]);
00047 void surf(char[]);
00048 void pollserver(void);
00049 
00050 DigitalOut ruu1(p21); //tail
00051 DigitalOut ruu2(p22); //body
00052 DigitalOut suu1(p23);
00053 DigitalOut suu2(p24);
00054 DigitalOut ena(p25); //enable
00055 
00056 Ticker tick;
00057 Ticker polltick;
00058 #define POLLINTERVAL 10 //server polling interval in seconds
00059 bool pollfound = false; //flag goes up if there is something to play
00060 
00061 AnalogOut DACout(p18);
00062 DigitalOut relay1(p29);
00063 
00064 InterruptIn doorbell(p30);
00065 void dummy(void);
00066 
00067 void play_wave(char *, bool);
00068 
00069 Ticker movetick; //runs the lipsync function
00070 #define SAYSPEED 0.085 //speed of lipsync in seconds
00071 char lipmoves[300]; //array for lipmove bits
00072 int lippos;
00073 
00074 bool doorint = false; //doorbell interrupt flag
00075 
00076 
00077 int main() {
00078 
00079 //setup ethernet connection
00080 printf("Setting up ethernet...\n");
00081 EthernetErr ethErr = eth.setup();
00082 if(ethErr) {
00083     printf("Error %d in ethernet setup.\n", ethErr);
00084 }//if
00085 
00086 printf("Ethernet setup OK\n");
00087 
00088 //putting doorbell pin(p30) in pullup mode so it pulls up the voltage
00089 //between interrupts that pull it down
00090 doorbell.mode(PullUp);
00091 
00092 //run interrupt function when detecting a falling edge on p30
00093 doorbell.fall(&dummy);
00094 doorbell.fall(&dingdong);
00095 
00096 lippos = 0;
00097 suu1 = suu2 = ruu1 = ruu2 = 0;
00098 ena = 1; //enable L293 chip
00099 
00100 //starting http server polling ticker (10 second intervals)
00101 polltick.attach(&pollserver, POLLINTERVAL);
00102     
00103 while(1) {
00104     //check if polling flag is up
00105     if(pollfound==true) {
00106         polltick.detach();
00107         doorbell.fall(&dummy);
00108         
00109         //TODO: dl an effect description file or an sfx sound file
00110    
00111         //download lipsync file and load it into the array
00112         if(dl("http://192.168.1.2/talk/snd.bmf", "/sd/snd.bmf")==0) {
00113             load_lipsync("/sd/snd.bmf");
00114         }//inner if
00115 
00116         //flap the tail before playing
00117         tail_flap(2);
00118    
00119          //play downloaded file (new waveplayer code)
00120          play_wave("/sd/snd.wav", true);
00121          
00122          //add event to eventlog (info=type:sender:description)
00123          surf("http://192.168.1.2/talk/addevent.php?info=info:Billy:Played%20wavefile%20snd.wav");
00124 
00125          //delete played sound file
00126          surf("http://192.168.1.2/talk/dlok.php?delete=yes");
00127          
00128          //add event to eventlog (info=type:sender:description)
00129          surf("http://192.168.1.2/talk/addevent.php?info=info:Billy:Deleted%20wavefile%20snd.wav%20from%20server.");
00130          
00131          //reset pollfound flag
00132          pollfound = false;
00133          polltick.attach(&pollserver, POLLINTERVAL);
00134          doorbell.fall(&dingdong);        
00135     }//if pollfound
00136 
00137    //check if doorbell flag is raised for doorbell press
00138    if(doorint==true) {
00139         printf("Doorbell press detected..\n");
00140         
00141         polltick.detach();
00142                
00143         play_wave("/sd/ns.wav", false); //doorbell sound, no lipmoves
00144         
00145         load_lipsync("/sd/tulossa.bmf");
00146         
00147         ruu2 = 1;//raise body
00148         play_wave("/sd/tulossa.wav", true);
00149         ruu2 = 0;//lower body
00150         
00151         //add event to eventlog (info=type:sender:description)
00152         surf("http://192.168.1.2/talk/addevent.php?info=info:Billy:Doorbell%20pressed");
00153         
00154         //reattach polling ticker
00155         polltick.attach(&pollserver, POLLINTERVAL);    
00156          
00157         //reset doorbell interrupt flag
00158         doorint = false;        
00159    }//if doorint
00160 }//while 1
00161 
00162 }///////////// main ends //////////////////
00163 
00164 //dummy function for the interruptin 'fix'
00165 void dummy() {}
00166 
00167 
00168 //this function is attached to polltick, and it polls the server
00169 //every 10 seconds looking for something to download and play
00170 void pollserver() {
00171    printf("Attempting download..\n");
00172    led1 = 1;
00173    
00174    //if download is successful, raise flag
00175    if (dl("http://192.168.1.2/talk/snd.wav", "/sd/snd.wav")==0) {
00176         pollfound = true;
00177         polltick.detach();
00178    }//if dl..
00179    
00180    led1 = 0;
00181 }//pollserver
00182 
00183 
00184 //http download function, takes url (http://mbed.org/example.wav)
00185 //and target file (/sd/example.wav) as parameters
00186 //returns 0 on success and 1 on failure
00187 int dl(char url[], char target[]) {
00188     int result;
00189     HTTPFile f(target);
00190     HTTPResult r = http.get(url, &f);
00191 
00192     if(r==HTTP_OK) {
00193       printf(" HTTP Result OK\n");
00194       result=0; 
00195     }
00196     else {
00197       printf("HTTP Error %d\n", r);
00198       result=1;
00199     }//else 
00200     
00201     return result; 
00202 }//dl
00203 
00204 
00205 //http get function "surfing the web"
00206 void surf(char url[]) {
00207     HTTPText txt;
00208 
00209     HTTPResult r = http.get(url, &txt);
00210     if(r==HTTP_OK) {
00211         printf("Surfing result :\"%s\"\n", txt.gets()); 
00212     }//if
00213     else {
00214         printf("Surfing error %d\n", r);
00215     }//else
00216 }//surf
00217 
00218 
00219 //doorbell interrupt code here
00220 //remember not to put any large operations in the interrupt handler
00221 void dingdong() {
00222    doorint = true;       
00223 }//dingdong
00224 
00225 
00226 //load lipsync data from bmf file to array in RAM
00227 void load_lipsync(char syncfile[]) {
00228    printf("Reading lipsync from sd file\n");
00229    FILE * pFile = fopen (syncfile , "r");
00230    if (pFile != NULL) {
00231      fgets (lipmoves , 300 , pFile);
00232      printf("Lipmoves file is: %s\n", lipmoves);
00233      fclose (pFile);
00234    }//if
00235 }//lipsync
00236 
00237 
00238 //mouth function is attached to movetick ticker
00239 //and it moves billys mouth when activated
00240 void mouth() {
00241    if(lippos < 300) {
00242       suu1 = 0;
00243 
00244       char tmpmrk;
00245       tmpmrk = lipmoves[lippos];
00246       int num = atoi(&tmpmrk);
00247       //printf("suu on %d  ", num);
00248       suu2 = num;
00249       lippos++;
00250    }//if
00251 }//mouth
00252 
00253 
00254 void body_move(int secs) {
00255     printf("making body move %d",secs);
00256     ruu2 = 1;
00257     wait(secs);
00258     ruu2 = 0;
00259 }
00260 
00261 
00262 //tail flapping function
00263 void tail_flap(int howmany) {
00264     for(int i=0;i<howmany;i++) {
00265       ruu1=1;
00266       wait(0.2);
00267       ruu1=ruu2=0;
00268       wait(0.2);
00269     }//for
00270     wait(0.3);
00271 }//tailflap
00272 
00273 
00274 void play_wave(char *wavname, bool lipmoves) {
00275 
00276     //enable audio amps via relay 1
00277     relay1=1;
00278   
00279     unsigned chunk_id,chunk_size,channel;
00280     unsigned data,samp_int,i;
00281     short dac_data;
00282     char *slice_buf;
00283     short *data_sptr;
00284     FMT_STRUCT wav_format;
00285     FILE *wavfile;
00286     long slice,num_slices;
00287     DAC_wptr=0;
00288     DAC_rptr=0;
00289 
00290     size_t result;
00291 
00292     for (i=0;i<256;i+=2) {
00293         DAC_fifo[i]=0;
00294         DAC_fifo[i+1]=3000;
00295     }
00296     DAC_wptr=4;
00297     DAC_on=0;
00298 
00299     printf("Playing wave file '%s'\r\n",wavname);
00300 
00301     wavfile=fopen(wavname,"rb");
00302     if (!wavfile) {
00303         printf("Unable to open wav file '%s'\r\n",wavname);
00304         exit(1);
00305     }
00306 
00307     fread(&chunk_id,4,1,wavfile);
00308     fread(&chunk_size,4,1,wavfile);
00309     while (!feof(wavfile)) {
00310         printf("Read chunk ID 0x%x, size 0x%x\r\n",chunk_id,chunk_size);
00311         switch (chunk_id) {
00312             case 0x46464952:
00313                 fread(&data,4,1,wavfile);
00314                 printf("RIFF chunk\r\n");
00315                 printf("  chunk size %d (0x%x)\r\n",chunk_size,chunk_size);
00316                 printf("  RIFF type 0x%x\r\n",data);
00317                 break;
00318             case 0x20746d66:
00319                 fread(&wav_format,sizeof(wav_format),1,wavfile);
00320                 printf("FORMAT chunk\r\n");
00321                 printf("  chunk size %d (0x%x)\r\n",chunk_size,chunk_size);
00322                 printf("  compression code %d\r\n",wav_format.comp_code);
00323                 printf("  %d channels\r\n",wav_format.num_channels);
00324                 printf("  %d samples/sec\r\n",wav_format.sample_rate);
00325                 printf("  %d bytes/sec\r\n",wav_format.avg_Bps);
00326                 printf("  block align %d\r\n",wav_format.block_align);
00327                 printf("  %d bits per sample\r\n",wav_format.sig_bps);
00328                 if (chunk_size > sizeof(wav_format))
00329                     fseek(wavfile,chunk_size-sizeof(wav_format),SEEK_CUR);
00330 // create a slice buffer large enough to hold multiple slices
00331                 slice_buf=(char *)malloc(wav_format.block_align*SLICE_BUF_SIZE);
00332                 if (!slice_buf) {
00333                     printf("Unable to malloc slice buffer");
00334                     exit(1);
00335                 }
00336                 break;
00337             case 0x61746164:
00338                 slice_buf=(char *)malloc(wav_format.block_align*SLICE_BUF_SIZE);
00339                 if (!slice_buf) {
00340                     printf("Unable to malloc slice buffer");
00341                     exit(1);
00342                 }
00343                 num_slices=chunk_size/wav_format.block_align;
00344                 printf("DATA chunk\r\n");
00345                 printf("  chunk size %d (0x%x)\r\n",chunk_size,chunk_size);
00346                 printf("  %d slices\r\n",num_slices);
00347                 printf("  Ideal sample interval=%d\r\n",(unsigned)(1000000.0/wav_format.sample_rate));
00348                 samp_int=1000000/(wav_format.sample_rate);
00349                 printf("  programmed interrupt tick interval=%d\r\n",samp_int);
00350 
00351 // starting up ticker to write samples out -- no printfs until tick.detach is called
00352                 if(lipmoves==true) {
00353                     lippos = 0; //reset lipmoves position counter
00354                     movetick.attach(&mouth, SAYSPEED);
00355                 }
00356                 tick.attach_us(&dac_out, samp_int);
00357                
00358                 DAC_on=1;
00359                 for (slice=0;slice<num_slices;slice+=SLICE_BUF_SIZE) {
00360 
00361                     result = fread(slice_buf,wav_format.block_align*SLICE_BUF_SIZE,1,wavfile);
00362                     if (feof(wavfile)) {
00363                         printf("Oops -- not enough slices in the wave file\r\n");
00364 
00365                         break;
00366                     }
00367 
00368                     data_sptr=(short *)slice_buf;
00369                     for (i=0;i<SLICE_BUF_SIZE;i++) {
00370                         dac_data=0;
00371 
00372 // for a stereo wave file average the two channels.
00373                         for (channel=0;channel<wav_format.num_channels;channel++) {
00374                             switch (wav_format.sig_bps) {
00375                                 case 16:
00376                                     dac_data+=(  ((int)(*data_sptr++)) +32768 );
00377                                     break;
00378                                 case 8:
00379                                     dac_data+=(  ((int)(*data_sptr++)) +32768 <<8);
00380                                     break;
00381                             }
00382                         }
00383                         DAC_fifo[DAC_wptr]=dac_data;
00384                         DAC_wptr=(DAC_wptr+1) & 0xff;
00385                         while (DAC_wptr==DAC_rptr) {
00386                             wait_us(10);
00387                         }
00388                     }
00389                 }
00390                 DAC_on=0;
00391                 suu1 = suu2 = 0;
00392                 tick.detach();
00393                 if(lipmoves==true) {
00394                     movetick.detach();
00395                 }
00396                 printf("Tickers detached\r\n");
00397                 free(slice_buf);
00398                 break;
00399             case 0x5453494c:
00400                 printf("INFO chunk, size %d\r\n",chunk_size);
00401                 fseek(wavfile,chunk_size,SEEK_CUR);
00402                 break;
00403             default:
00404                 printf("unknown chunk type 0x%x, size %d\r\n",chunk_id,chunk_size);
00405                 data=fseek(wavfile,chunk_size,SEEK_CUR);
00406                 break;
00407         }
00408         fread(&chunk_id,4,1,wavfile);
00409         fread(&chunk_size,4,1,wavfile);
00410     }
00411     printf("++++++++++++ Done with wave file ++++++++++\r\n");
00412     fclose(wavfile);
00413     
00414     //disable audio amps via relay 1
00415     relay1=0;
00416 }//play-wave
00417 
00418 
00419 void dac_out() {
00420     if (DAC_on) {
00421         DACout.write_u16(DAC_fifo[DAC_rptr]);
00422         DAC_rptr=(DAC_rptr+1) & 0xff;
00423     }//if
00424 }//dac-out