My Billy Bass program, see my notebook for details

Dependencies:   EthernetNetIf mbed

Revision:
0:7613b886e052
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/main.cpp	Sat Aug 14 19:00:53 2010 +0000
@@ -0,0 +1,424 @@
+
+
+#include "mbed.h"
+#include "SDHCFileSystem.h"
+#include "HTTPClient.h"
+#include "EthernetNetIf.h"
+
+#define SAMPLE_FREQ 40000
+#define BUF_SIZE (SAMPLE_FREQ/10)
+#define SLICE_BUF_SIZE 1
+
+typedef struct uFMT_STRUCT {
+    short comp_code;
+    short num_channels;
+    unsigned sample_rate;
+    unsigned avg_Bps;
+    short block_align;
+    short sig_bps;
+} FMT_STRUCT;
+
+short DAC_fifo[256];
+short DAC_wptr;
+short DAC_rptr;
+short DAC_on;
+
+DigitalOut led1(LED1);
+DigitalOut led2(LED2);
+DigitalOut led3(LED3);
+DigitalOut led4(LED4);
+
+SDFileSystem sd(p5, p6, p7, p13, "sd");
+
+EthernetNetIf eth;
+HTTPClient http;
+
+void download_bmf(void);
+void load_lipsync(char[]);
+void mouth(void);
+
+void dac_out(void);
+void dingdong(void);
+
+void body_move(int);
+void tail_flap(int);
+
+int dl(char[], char[]);
+void surf(char[]);
+void pollserver(void);
+
+DigitalOut ruu1(p21); //tail
+DigitalOut ruu2(p22); //body
+DigitalOut suu1(p23);
+DigitalOut suu2(p24);
+DigitalOut ena(p25); //enable
+
+Ticker tick;
+Ticker polltick;
+#define POLLINTERVAL 10 //server polling interval in seconds
+bool pollfound = false; //flag goes up if there is something to play
+
+AnalogOut DACout(p18);
+DigitalOut relay1(p29);
+
+InterruptIn doorbell(p30);
+void dummy(void);
+
+void play_wave(char *, bool);
+
+Ticker movetick; //runs the lipsync function
+#define SAYSPEED 0.085 //speed of lipsync in seconds
+char lipmoves[300]; //array for lipmove bits
+int lippos;
+
+bool doorint = false; //doorbell interrupt flag
+
+
+int main() {
+
+//setup ethernet connection
+printf("Setting up ethernet...\n");
+EthernetErr ethErr = eth.setup();
+if(ethErr) {
+    printf("Error %d in ethernet setup.\n", ethErr);
+}//if
+
+printf("Ethernet setup OK\n");
+
+//putting doorbell pin(p30) in pullup mode so it pulls up the voltage
+//between interrupts that pull it down
+doorbell.mode(PullUp);
+
+//run interrupt function when detecting a falling edge on p30
+doorbell.fall(&dummy);
+doorbell.fall(&dingdong);
+
+lippos = 0;
+suu1 = suu2 = ruu1 = ruu2 = 0;
+ena = 1; //enable L293 chip
+
+//starting http server polling ticker (10 second intervals)
+polltick.attach(&pollserver, POLLINTERVAL);
+    
+while(1) {
+    //check if polling flag is up
+    if(pollfound==true) {
+        polltick.detach();
+        doorbell.fall(&dummy);
+        
+        //TODO: dl an effect description file or an sfx sound file
+   
+        //download lipsync file and load it into the array
+        if(dl("http://192.168.1.2/talk/snd.bmf", "/sd/snd.bmf")==0) {
+            load_lipsync("/sd/snd.bmf");
+        }//inner if
+
+        //flap the tail before playing
+        tail_flap(2);
+   
+         //play downloaded file (new waveplayer code)
+         play_wave("/sd/snd.wav", true);
+         
+         //add event to eventlog (info=type:sender:description)
+         surf("http://192.168.1.2/talk/addevent.php?info=info:Billy:Played%20wavefile%20snd.wav");
+
+         //delete played sound file
+         surf("http://192.168.1.2/talk/dlok.php?delete=yes");
+         
+         //add event to eventlog (info=type:sender:description)
+         surf("http://192.168.1.2/talk/addevent.php?info=info:Billy:Deleted%20wavefile%20snd.wav%20from%20server.");
+         
+         //reset pollfound flag
+         pollfound = false;
+         polltick.attach(&pollserver, POLLINTERVAL);
+         doorbell.fall(&dingdong);        
+    }//if pollfound
+
+   //check if doorbell flag is raised for doorbell press
+   if(doorint==true) {
+        printf("Doorbell press detected..\n");
+        
+        polltick.detach();
+               
+        play_wave("/sd/ns.wav", false); //doorbell sound, no lipmoves
+        
+        load_lipsync("/sd/tulossa.bmf");
+        
+        ruu2 = 1;//raise body
+        play_wave("/sd/tulossa.wav", true);
+        ruu2 = 0;//lower body
+        
+        //add event to eventlog (info=type:sender:description)
+        surf("http://192.168.1.2/talk/addevent.php?info=info:Billy:Doorbell%20pressed");
+        
+        //reattach polling ticker
+        polltick.attach(&pollserver, POLLINTERVAL);    
+         
+        //reset doorbell interrupt flag
+        doorint = false;        
+   }//if doorint
+}//while 1
+
+}///////////// main ends //////////////////
+
+//dummy function for the interruptin 'fix'
+void dummy() {}
+
+
+//this function is attached to polltick, and it polls the server
+//every 10 seconds looking for something to download and play
+void pollserver() {
+   printf("Attempting download..\n");
+   led1 = 1;
+   
+   //if download is successful, raise flag
+   if (dl("http://192.168.1.2/talk/snd.wav", "/sd/snd.wav")==0) {
+        pollfound = true;
+        polltick.detach();
+   }//if dl..
+   
+   led1 = 0;
+}//pollserver
+
+
+//http download function, takes url (http://mbed.org/example.wav)
+//and target file (/sd/example.wav) as parameters
+//returns 0 on success and 1 on failure
+int dl(char url[], char target[]) {
+    int result;
+    HTTPFile f(target);
+    HTTPResult r = http.get(url, &f);
+
+    if(r==HTTP_OK) {
+      printf(" HTTP Result OK\n");
+      result=0; 
+    }
+    else {
+      printf("HTTP Error %d\n", r);
+      result=1;
+    }//else 
+    
+    return result; 
+}//dl
+
+
+//http get function "surfing the web"
+void surf(char url[]) {
+    HTTPText txt;
+
+    HTTPResult r = http.get(url, &txt);
+    if(r==HTTP_OK) {
+        printf("Surfing result :\"%s\"\n", txt.gets()); 
+    }//if
+    else {
+        printf("Surfing error %d\n", r);
+    }//else
+}//surf
+
+
+//doorbell interrupt code here
+//remember not to put any large operations in the interrupt handler
+void dingdong() {
+   doorint = true;       
+}//dingdong
+
+
+//load lipsync data from bmf file to array in RAM
+void load_lipsync(char syncfile[]) {
+   printf("Reading lipsync from sd file\n");
+   FILE * pFile = fopen (syncfile , "r");
+   if (pFile != NULL) {
+     fgets (lipmoves , 300 , pFile);
+     printf("Lipmoves file is: %s\n", lipmoves);
+     fclose (pFile);
+   }//if
+}//lipsync
+
+
+//mouth function is attached to movetick ticker
+//and it moves billys mouth when activated
+void mouth() {
+   if(lippos < 300) {
+      suu1 = 0;
+
+      char tmpmrk;
+      tmpmrk = lipmoves[lippos];
+      int num = atoi(&tmpmrk);
+      //printf("suu on %d  ", num);
+      suu2 = num;
+      lippos++;
+   }//if
+}//mouth
+
+
+void body_move(int secs) {
+    printf("making body move %d",secs);
+    ruu2 = 1;
+    wait(secs);
+    ruu2 = 0;
+}
+
+
+//tail flapping function
+void tail_flap(int howmany) {
+    for(int i=0;i<howmany;i++) {
+      ruu1=1;
+      wait(0.2);
+      ruu1=ruu2=0;
+      wait(0.2);
+    }//for
+    wait(0.3);
+}//tailflap
+
+
+void play_wave(char *wavname, bool lipmoves) {
+
+    //enable audio amps via relay 1
+    relay1=1;
+  
+    unsigned chunk_id,chunk_size,channel;
+    unsigned data,samp_int,i;
+    short dac_data;
+    char *slice_buf;
+    short *data_sptr;
+    FMT_STRUCT wav_format;
+    FILE *wavfile;
+    long slice,num_slices;
+    DAC_wptr=0;
+    DAC_rptr=0;
+
+    size_t result;
+
+    for (i=0;i<256;i+=2) {
+        DAC_fifo[i]=0;
+        DAC_fifo[i+1]=3000;
+    }
+    DAC_wptr=4;
+    DAC_on=0;
+
+    printf("Playing wave file '%s'\r\n",wavname);
+
+    wavfile=fopen(wavname,"rb");
+    if (!wavfile) {
+        printf("Unable to open wav file '%s'\r\n",wavname);
+        exit(1);
+    }
+
+    fread(&chunk_id,4,1,wavfile);
+    fread(&chunk_size,4,1,wavfile);
+    while (!feof(wavfile)) {
+        printf("Read chunk ID 0x%x, size 0x%x\r\n",chunk_id,chunk_size);
+        switch (chunk_id) {
+            case 0x46464952:
+                fread(&data,4,1,wavfile);
+                printf("RIFF chunk\r\n");
+                printf("  chunk size %d (0x%x)\r\n",chunk_size,chunk_size);
+                printf("  RIFF type 0x%x\r\n",data);
+                break;
+            case 0x20746d66:
+                fread(&wav_format,sizeof(wav_format),1,wavfile);
+                printf("FORMAT chunk\r\n");
+                printf("  chunk size %d (0x%x)\r\n",chunk_size,chunk_size);
+                printf("  compression code %d\r\n",wav_format.comp_code);
+                printf("  %d channels\r\n",wav_format.num_channels);
+                printf("  %d samples/sec\r\n",wav_format.sample_rate);
+                printf("  %d bytes/sec\r\n",wav_format.avg_Bps);
+                printf("  block align %d\r\n",wav_format.block_align);
+                printf("  %d bits per sample\r\n",wav_format.sig_bps);
+                if (chunk_size > sizeof(wav_format))
+                    fseek(wavfile,chunk_size-sizeof(wav_format),SEEK_CUR);
+// create a slice buffer large enough to hold multiple slices
+                slice_buf=(char *)malloc(wav_format.block_align*SLICE_BUF_SIZE);
+                if (!slice_buf) {
+                    printf("Unable to malloc slice buffer");
+                    exit(1);
+                }
+                break;
+            case 0x61746164:
+                slice_buf=(char *)malloc(wav_format.block_align*SLICE_BUF_SIZE);
+                if (!slice_buf) {
+                    printf("Unable to malloc slice buffer");
+                    exit(1);
+                }
+                num_slices=chunk_size/wav_format.block_align;
+                printf("DATA chunk\r\n");
+                printf("  chunk size %d (0x%x)\r\n",chunk_size,chunk_size);
+                printf("  %d slices\r\n",num_slices);
+                printf("  Ideal sample interval=%d\r\n",(unsigned)(1000000.0/wav_format.sample_rate));
+                samp_int=1000000/(wav_format.sample_rate);
+                printf("  programmed interrupt tick interval=%d\r\n",samp_int);
+
+// starting up ticker to write samples out -- no printfs until tick.detach is called
+                if(lipmoves==true) {
+                    lippos = 0; //reset lipmoves position counter
+                    movetick.attach(&mouth, SAYSPEED);
+                }
+                tick.attach_us(&dac_out, samp_int);
+               
+                DAC_on=1;
+                for (slice=0;slice<num_slices;slice+=SLICE_BUF_SIZE) {
+
+                    result = fread(slice_buf,wav_format.block_align*SLICE_BUF_SIZE,1,wavfile);
+                    if (feof(wavfile)) {
+                        printf("Oops -- not enough slices in the wave file\r\n");
+
+                        break;
+                    }
+
+                    data_sptr=(short *)slice_buf;
+                    for (i=0;i<SLICE_BUF_SIZE;i++) {
+                        dac_data=0;
+
+// for a stereo wave file average the two channels.
+                        for (channel=0;channel<wav_format.num_channels;channel++) {
+                            switch (wav_format.sig_bps) {
+                                case 16:
+                                    dac_data+=(  ((int)(*data_sptr++)) +32768 );
+                                    break;
+                                case 8:
+                                    dac_data+=(  ((int)(*data_sptr++)) +32768 <<8);
+                                    break;
+                            }
+                        }
+                        DAC_fifo[DAC_wptr]=dac_data;
+                        DAC_wptr=(DAC_wptr+1) & 0xff;
+                        while (DAC_wptr==DAC_rptr) {
+                            wait_us(10);
+                        }
+                    }
+                }
+                DAC_on=0;
+                suu1 = suu2 = 0;
+                tick.detach();
+                if(lipmoves==true) {
+                    movetick.detach();
+                }
+                printf("Tickers detached\r\n");
+                free(slice_buf);
+                break;
+            case 0x5453494c:
+                printf("INFO chunk, size %d\r\n",chunk_size);
+                fseek(wavfile,chunk_size,SEEK_CUR);
+                break;
+            default:
+                printf("unknown chunk type 0x%x, size %d\r\n",chunk_id,chunk_size);
+                data=fseek(wavfile,chunk_size,SEEK_CUR);
+                break;
+        }
+        fread(&chunk_id,4,1,wavfile);
+        fread(&chunk_size,4,1,wavfile);
+    }
+    printf("++++++++++++ Done with wave file ++++++++++\r\n");
+    fclose(wavfile);
+    
+    //disable audio amps via relay 1
+    relay1=0;
+}//play-wave
+
+
+void dac_out() {
+    if (DAC_on) {
+        DACout.write_u16(DAC_fifo[DAC_rptr]);
+        DAC_rptr=(DAC_rptr+1) & 0xff;
+    }//if
+}//dac-out