xypad theremin for LPC1768

Dependencies:   MODDMA mbed

Files at this revision

API Documentation at this revision

Comitter:
exopiped
Date:
Mon Mar 14 23:37:58 2016 +0000
Parent:
0:8ee38453bad9
Child:
2:c5eeaf1c8e69
Commit message:
Eliminated audio glitches from touch screen

Changed in this revision

dma.cpp Show annotated file Show diff for this revision Revisions of this file
jswitch.cpp Show annotated file Show diff for this revision Revisions of this file
note.cpp Show annotated file Show diff for this revision Revisions of this file
touch.cpp Show annotated file Show diff for this revision Revisions of this file
wave.cpp Show annotated file Show diff for this revision Revisions of this file
--- a/dma.cpp	Sun Mar 13 01:12:40 2016 +0000
+++ b/dma.cpp	Mon Mar 14 23:37:58 2016 +0000
@@ -10,6 +10,8 @@
 int buffer[2][DMA_BUFSIZE];
 
 AnalogOut sig(p18);  // analog output object ( uses pin 18)
+DigitalOut led2(LED1);
+DigitalOut led3(LED2);
 
 MODDMA dma;
 MODDMA_Config *conf0, *conf1;
@@ -82,43 +84,42 @@
 }
 
 void dma_disable(void)
-{
+{    
+    // Get configuration pointer.
+    MODDMA_Config *config = dma.getConfig();
     
     // Finish the DMA cycle by shutting down the channel.
-    dma.Disable((MODDMA::CHANNELS)conf0->channelNum());
-    dma.Disable((MODDMA::CHANNELS)conf1->channelNum());
+    dma.Disable((MODDMA::CHANNELS)config->channelNum());
 
 }
 
 // Configuration callback on TC
 void TC0_callback(void) {
-     
-    dma.Disable((MODDMA::CHANNELS)conf0->channelNum());
-   
+    
+    dma_disable();
+    
     if (note_active()) {
         // Notify note.cpp that it is time to refill buffer[0]
         note_set_bufno(0);
-       
+
         // Swap to buffer1
         dma.Prepare( conf1 );
+    }
+    // Clear DMA IRQ flags.
+    if (dma.irqType() == MODDMA::TcIrq) dma.clearTcIrq(); 
 
-        // Clear DMA IRQ flags.
-        if (dma.irqType() == MODDMA::TcIrq) dma.clearTcIrq(); 
-    } else {
-        dma.Disable((MODDMA::CHANNELS)conf1->channelNum());
-    }
 }
 
 // Configuration callback on Error
 void ERR0_callback(void) {
+    led2=1;
     error("Oh no! My Mbed EXPLODED!");
 }
 
 // Configuration callback on TC
 void TC1_callback(void) {
     
-    // Finish the DMA cycle by shutting down the channel.
-    dma.Disable((MODDMA::CHANNELS)conf1->channelNum());
+    dma_disable();
     
     if (note_active()) {
         // Notify note.cpp that it is time to refill buffer[1]
@@ -126,16 +127,15 @@
 
         // Swap to buffer0
         dma.Prepare( conf0 );
-        
-        // Clear DMA IRQ flags.
-        if (dma.irqType() == MODDMA::TcIrq) dma.clearTcIrq(); 
-    } else {
-        dma.Disable((MODDMA::CHANNELS)conf0->channelNum());
     }
+    // Clear DMA IRQ flags.
+    if (dma.irqType() == MODDMA::TcIrq) dma.clearTcIrq(); 
 }
 
+
 // Configuration callback on Error
 void ERR1_callback(void) {
+    led3=1;
     error("Oh no! My Mbed EXPLODED!");
 }
 
--- a/jswitch.cpp	Sun Mar 13 01:12:40 2016 +0000
+++ b/jswitch.cpp	Mon Mar 14 23:37:58 2016 +0000
@@ -51,7 +51,6 @@
             js_official|=(js_now&js_old&js_older&js_oldest);
             if (js_official>0) {
                 js_msec=js_timer.read_ms();
-//                debug_hexbyte(js_official);
             }
         } else {
             js_now=0;
--- a/note.cpp	Sun Mar 13 01:12:40 2016 +0000
+++ b/note.cpp	Mon Mar 14 23:37:58 2016 +0000
@@ -12,7 +12,7 @@
 #include "jswitch.h"
 #include "note.h"
 
-DigitalOut led2(LED2);   // lit during NOTE_RELEASE state
+#define TURN_DMA_OFF_AFTER_EACH_NOTE 0
 
 typedef enum {NOTE_ATTACK,NOTE_DECAY,NOTE_SUSTAIN,NOTE_RELEASE,NOTE_OFF} NOTE_STATE;
 
@@ -60,15 +60,10 @@
     wave_reset(); 
     note_freq = touch_frequency();
     note_attack_bufs=envlp_get_attack_bufs();
-    debug_hexshort((short)note_attack_bufs);
-    debug_putch(' ');
     note_decay_bufs=envlp_get_decay_bufs();
     note_release_delta = envlp_get_release_delta();
     note_release_numerator = ENVLP_MAX - note_release_delta;
     note_release_denominator = ENVLP_MAX;
-    debug_hexshort((short)note_release_numerator);
-    debug_crlf();
-
     // fill first two buffers
     note_attack();
     note_set_bufno(0);
@@ -77,6 +72,7 @@
     note_set_bufno(1);
     note_state_machine();
     note_fill_buf();
+    note_bufno=NIL;    
     dma_enable();
 }
 
@@ -84,8 +80,7 @@
 {
     dma_disable();
     note_state=NOTE_OFF;
-    note_bufno=NIL;
-    led2 = 0;
+    note_bufno=NIL;   
 }
 
 /* 
@@ -101,10 +96,8 @@
 {
     // execute note state machine
     note_state_machine();
-
-    // if dma buffer sent, refill it
     if(note_bufno!=NIL) {
-       note_fill_buf();
+        note_fill_buf();
     }
 
     // handle presence or absence of touch
@@ -167,21 +160,22 @@
 void note_fill_buf(void)
 {
     int j,start_env,end_env,env_val,wave_val,buf_val,amplitude;
-    int *bufptr=NULL;
+    int *bufptr;
 
     bufptr = dma_get_bufptr(note_bufno);
     start_env = note_first_bufval; 
     end_env = note_last_bufval;
-    amplitude = touch_amplitude();
+    amplitude = touch_amplitude();  
 
     for (j=0;j<DMA_BUFSIZE;j++) {
-        env_val=start_env+(end_env - start_env)*j/DMA_BUFSIZE;
-        wave_val = wave_nextval(note_freq);
-        buf_val = wave_val * env_val / ENVLP_MAX;
-        buf_val=amplitude*buf_val/TOUCH_MAX_AMPLITUDE;
-        bufptr[j]= DAC_POWER_MODE | ((buf_val << 6) & 0xFFC0);   
+            env_val=start_env+(end_env - start_env)*j/DMA_BUFSIZE;
+            wave_val = wave_nextval(note_freq);
+            buf_val = wave_val * env_val / ENVLP_MAX;
+            buf_val=amplitude*buf_val/TOUCH_MAX_AMPLITUDE;
+            bufptr[j]= DAC_POWER_MODE | ((buf_val << 6) & 0xFFC0);   
     }
-    note_bufno = NIL;  // buffer is filled
+            
+    note_bufno = NIL;
     switch (note_state) {
     case NOTE_ATTACK:
         note_attack_bufcount++;
@@ -189,13 +183,15 @@
     case NOTE_DECAY:
         note_decay_bufcount++;
         break;
+    case NOTE_SUSTAIN:
+        note_first_bufval = note_last_bufval;
+        break;
     case NOTE_RELEASE:
         note_first_bufval = note_last_bufval; 
         note_last_bufval =
             note_first_bufval * note_release_numerator 
             / note_release_denominator;
         break;
-    case NOTE_SUSTAIN:
     case NOTE_OFF:
     default:
         ;
@@ -208,7 +204,6 @@
  */
 void note_release(void)
 {
-    led2 = 1;
     note_state = NOTE_RELEASE;
 }
 /*
--- a/touch.cpp	Sun Mar 13 01:12:40 2016 +0000
+++ b/touch.cpp	Mon Mar 14 23:37:58 2016 +0000
@@ -32,7 +32,7 @@
  *      
  */
 
-typedef enum {TOUCH_NOTOUCH,TOUCH_DEBOUNCE,TOUCH_PRESENT} TOUCH_STATE;
+typedef enum {TOUCH_NOTOUCH,TOUCH_DEBOUNCE,NOTOUCH_DEBOUNCE,TOUCH_PRESENT} TOUCH_STATE;
 
 
 #define TSC_ADDR  0x82     // (i2c address for touchscreen)<<1
@@ -100,12 +100,13 @@
 
 // GPIO_AF -- GPIO Alternate FunctionRegister
 #define GPIO_AF       0x17
-
+DigitalOut led1(LED1);
 DigitalOut led4(LED4);
 
 i2c_t touch_ctrl;  // i2c interface struct for touch screen
 
-static bool touch_present(void);
+static int touch_present(void);
+static void touch_reset(void);
 static void touch_compute_params(void);
 
 static char tsc_reset[2]={SYS_CTRL1, SOFT_RESET};
@@ -137,10 +138,17 @@
  
 // used by state machine that debounces touch detection 
 TOUCH_STATE touch_state=TOUCH_NOTOUCH;
-#define GOOD_TOUCH_COUNT 8
-#define NO_TOUCH_COUNT 8
+#define GOOD_TOUCH_COUNT 4
+#define NO_TOUCH_COUNT 4
+
+bool touch_init(void)
+{
+    touch_reset();
+    touch_state = TOUCH_NOTOUCH;
+    return true;    
+}
  
-bool touch_init(void)
+void touch_reset(void)
 {
     char chipid[2];
 
@@ -205,44 +213,55 @@
 
     i2c_write(&touch_ctrl,TSC_ADDR,ena_intrupt,2,1);
     wait_ms(1);
-
-    touch_state = TOUCH_NOTOUCH;
-    return true;
 }
 
 bool touch_debounce(void)
 {
     static int debounce_count=0;
+    int tret;
 
+    tret=touch_present();
     switch (touch_state) {
     case TOUCH_NOTOUCH:
-        if (touch_present()) {
+        if (tret>0) {
             debounce_count=0;
             touch_state = TOUCH_DEBOUNCE;
         }
         break;
 
     case TOUCH_DEBOUNCE:
-        if (touch_present()) {
+        if (tret>0) {
             if (++debounce_count > GOOD_TOUCH_COUNT) {
                 touch_state = TOUCH_PRESENT;
+                led1=1;
             }
-        } else {
+        } else if(tret == 0) {
             touch_state = TOUCH_NOTOUCH;
         }
         break;
+        
+    case NOTOUCH_DEBOUNCE:
+        if(tret>0) {
+            touch_state = TOUCH_PRESENT;
+        } else if(tret== 0) {
+            if(++debounce_count > NO_TOUCH_COUNT) {
+                debounce_count=0;
+                touch_state=TOUCH_NOTOUCH;
+            }
+        }
+        break;
 
     case TOUCH_PRESENT:
-        if (touch_present()) {
+        if (tret>0) {
             touch_compute_params();
-            return true;
-        } else {
-            touch_state = TOUCH_NOTOUCH;
+        } else if(tret==0) {
+            debounce_count=0;
+            touch_state=NOTOUCH_DEBOUNCE;
         }
         break;
 
     }
-    return false;
+    return ((touch_state==TOUCH_PRESENT) || (touch_state==NOTOUCH_DEBOUNCE));
 }
 
 int touch_frequency(void)
@@ -257,33 +276,35 @@
 void touch_compute_params(void)
 {
     if(0>touch_get_xy(&touch_x,&touch_y)) return;
-    touch_audio_freq = TOUCH_MIN_FREQUENCY 
+    if((touch_y>0x3F) && (touch_y!=0xFFF)) {
+        touch_audio_freq = (TOUCH_MIN_FREQUENCY 
         + (TOUCH_MAX_FREQUENCY - TOUCH_MIN_FREQUENCY)
-        * touch_y/0xFFF;
-    touch_audio_amplitude = TOUCH_MAX_AMPLITUDE*touch_x/0xFFF;
-//    debug_hexshort((short)touch_audio_freq);
-//    debug_putch(',');
-//    debug_hexshort((short)touch_audio_amplitude);
-//    debug_crlf();
+        * touch_y)>>12;
+    }
+    if((touch_x > 0x3F) && (touch_x != 0xFFF)) {
+        touch_audio_amplitude = (TOUCH_MAX_AMPLITUDE*touch_x)>>12;
+    }
 }
-
-bool touch_present(void)
+/*
+ * return 1 if touch present, 0 if touch absent, and -1
+ * if there was an i2c error
+ */
+int touch_present(void)
 {
-    i2c_init(&touch_ctrl,p28,p27); // sync i2c routines
-    i2c_frequency(&touch_ctrl,100000); // 100kHz clock
+// <<<<<   i2c_init(&touch_ctrl,p28,p27); // sync i2c routines
+// <<<<<    i2c_frequency(&touch_ctrl,100000); // 100kHz clock
 
     i2c_write(&touch_ctrl,TSC_ADDR,&tsc_ctrl,1,0);
     i2c_read(&touch_ctrl,TSC_ADDR,&touch_status,1,1);
 
-    if ((touch_status & TSC_EN_MASK)==0) {  // i2c error 
+    if ((touch_status & TSC_EN_MASK)==0) {  // i2c error
         led4=1;                             // disables screen
-        wait_ms(10);
-        touch_init();                       // re-init fixes
-        return false;
+        touch_reset();                       // re-init fixes
+        return -1;
     } else if ((touch_status & TSC_TOUCH_DET)>0) {
-        return true;
+        return 1;
     }
-    return false; 
+    return 0; 
 }
 
 int touch_get_xy(short *x,short *y)
@@ -313,10 +334,10 @@
     // 0xFFF or 0x000 is some kind of glitch
     if (*x==0xFFF && *y==0xFFF) return NIL;
     if (*x==0 && *y==0) return NIL;
-//    debug_hexshort(*x);
-//    debug_putch(',');
-//    debug_hexshort(*y);
-//    debug_crlf();
+    debug_hexshort(*x);
+    debug_putch(',');
+    debug_hexshort(*y);
+    debug_crlf();
     return 0; 
 }
 
--- a/wave.cpp	Sun Mar 13 01:12:40 2016 +0000
+++ b/wave.cpp	Mon Mar 14 23:37:58 2016 +0000
@@ -78,7 +78,7 @@
 
     delta_phi= 100000*freq/WAVE_SAMPLE_RATE;
     accum_phi = (accum_phi + delta_phi)%100000;
-    index = ((DMA_BUFSIZE - 1) * accum_phi)/100000;
+    index = (DMA_BUFSIZE * accum_phi)/100000;
     return waveform[wavetype][index];
 }