xypad theremin for LPC1768

Dependencies:   MODDMA mbed

Committer:
exopiped
Date:
Mon Mar 14 23:43:44 2016 +0000
Revision:
2:c5eeaf1c8e69
Parent:
1:aa184d2eb2e3
touch screen driver glitches removed; debug statements commented out

Who changed what in which revision?

UserRevisionLine numberNew contents of line
exopiped 0:8ee38453bad9 1 /*
exopiped 0:8ee38453bad9 2 * note.cpp -- manage production of notes in response to
exopiped 0:8ee38453bad9 3 * touch screen input
exopiped 0:8ee38453bad9 4 */
exopiped 0:8ee38453bad9 5 #include "mbed.h"
exopiped 0:8ee38453bad9 6 #include "InterruptIn.h"
exopiped 0:8ee38453bad9 7 #include "debug.h"
exopiped 0:8ee38453bad9 8 #include "dma.h"
exopiped 0:8ee38453bad9 9 #include "envlp.h"
exopiped 0:8ee38453bad9 10 #include "wave.h"
exopiped 0:8ee38453bad9 11 #include "touch.h"
exopiped 0:8ee38453bad9 12 #include "jswitch.h"
exopiped 0:8ee38453bad9 13 #include "note.h"
exopiped 0:8ee38453bad9 14
exopiped 1:aa184d2eb2e3 15 #define TURN_DMA_OFF_AFTER_EACH_NOTE 0
exopiped 0:8ee38453bad9 16
exopiped 0:8ee38453bad9 17 typedef enum {NOTE_ATTACK,NOTE_DECAY,NOTE_SUSTAIN,NOTE_RELEASE,NOTE_OFF} NOTE_STATE;
exopiped 0:8ee38453bad9 18
exopiped 0:8ee38453bad9 19 static void note_start(void);
exopiped 0:8ee38453bad9 20 static void note_state_machine(void);
exopiped 0:8ee38453bad9 21 static void note_fill_buf(void);
exopiped 0:8ee38453bad9 22 static void note_attack(void);
exopiped 0:8ee38453bad9 23 static bool note_attack_done(void);
exopiped 0:8ee38453bad9 24 static bool note_decay_done(void);
exopiped 0:8ee38453bad9 25 static void note_release(void);
exopiped 0:8ee38453bad9 26 static bool note_release_done(void);
exopiped 0:8ee38453bad9 27 static bool note_released(void);
exopiped 0:8ee38453bad9 28 static void note_end(void);
exopiped 0:8ee38453bad9 29
exopiped 0:8ee38453bad9 30 static unsigned note_freq=0; // frequency in Hz
exopiped 0:8ee38453bad9 31 static NOTE_STATE note_state=NOTE_OFF;
exopiped 0:8ee38453bad9 32 static int note_bufno= NIL; // NIL or index of dma buffer
exopiped 0:8ee38453bad9 33 static int note_attack_bufcount;
exopiped 0:8ee38453bad9 34 static int note_attack_delta;
exopiped 0:8ee38453bad9 35 static int note_attack_bufs;
exopiped 0:8ee38453bad9 36 static int note_decay_bufs;
exopiped 0:8ee38453bad9 37 static int note_decay_bufcount;
exopiped 0:8ee38453bad9 38 static int note_decay_delta;
exopiped 0:8ee38453bad9 39 static int note_release_delta;
exopiped 0:8ee38453bad9 40 static int note_first_bufval;
exopiped 0:8ee38453bad9 41 static int note_last_bufval;
exopiped 0:8ee38453bad9 42 static int note_release_numerator;
exopiped 0:8ee38453bad9 43 static int note_release_denominator;
exopiped 0:8ee38453bad9 44
exopiped 0:8ee38453bad9 45 void note_init(void)
exopiped 0:8ee38453bad9 46 {
exopiped 0:8ee38453bad9 47 note_freq = 0;
exopiped 0:8ee38453bad9 48 note_state = NOTE_OFF;
exopiped 0:8ee38453bad9 49 note_bufno = NIL;
exopiped 0:8ee38453bad9 50 note_attack_bufcount=0;
exopiped 0:8ee38453bad9 51 note_decay_bufcount=0;
exopiped 0:8ee38453bad9 52 dma_init();
exopiped 0:8ee38453bad9 53 }
exopiped 0:8ee38453bad9 54
exopiped 0:8ee38453bad9 55 void note_start(void)
exopiped 0:8ee38453bad9 56 {
exopiped 0:8ee38453bad9 57 if (wave_type_changed()) {
exopiped 0:8ee38453bad9 58 wave_type_incr();
exopiped 0:8ee38453bad9 59 }
exopiped 0:8ee38453bad9 60 wave_reset();
exopiped 0:8ee38453bad9 61 note_freq = touch_frequency();
exopiped 0:8ee38453bad9 62 note_attack_bufs=envlp_get_attack_bufs();
exopiped 0:8ee38453bad9 63 note_decay_bufs=envlp_get_decay_bufs();
exopiped 0:8ee38453bad9 64 note_release_delta = envlp_get_release_delta();
exopiped 0:8ee38453bad9 65 note_release_numerator = ENVLP_MAX - note_release_delta;
exopiped 0:8ee38453bad9 66 note_release_denominator = ENVLP_MAX;
exopiped 0:8ee38453bad9 67 // fill first two buffers
exopiped 0:8ee38453bad9 68 note_attack();
exopiped 0:8ee38453bad9 69 note_set_bufno(0);
exopiped 0:8ee38453bad9 70 note_state_machine();
exopiped 0:8ee38453bad9 71 note_fill_buf();
exopiped 0:8ee38453bad9 72 note_set_bufno(1);
exopiped 0:8ee38453bad9 73 note_state_machine();
exopiped 0:8ee38453bad9 74 note_fill_buf();
exopiped 1:aa184d2eb2e3 75 note_bufno=NIL;
exopiped 0:8ee38453bad9 76 dma_enable();
exopiped 0:8ee38453bad9 77 }
exopiped 0:8ee38453bad9 78
exopiped 0:8ee38453bad9 79 void note_end(void)
exopiped 0:8ee38453bad9 80 {
exopiped 0:8ee38453bad9 81 dma_disable();
exopiped 0:8ee38453bad9 82 note_state=NOTE_OFF;
exopiped 1:aa184d2eb2e3 83 note_bufno=NIL;
exopiped 0:8ee38453bad9 84 }
exopiped 0:8ee38453bad9 85
exopiped 0:8ee38453bad9 86 /*
exopiped 0:8ee38453bad9 87 * note_update
exopiped 0:8ee38453bad9 88 * update the frequency and attenuation factor for the
exopiped 0:8ee38453bad9 89 * current note. If the current envelope first and last
exopiped 0:8ee38453bad9 90 * add up to less than 2, end the note.
exopiped 0:8ee38453bad9 91 * otherwise check to see if it is time to fill a dma buffer.
exopiped 0:8ee38453bad9 92 * if so fill the one specified by note_fillbuf.
exopiped 0:8ee38453bad9 93 */
exopiped 0:8ee38453bad9 94
exopiped 0:8ee38453bad9 95 void note_update(void)
exopiped 0:8ee38453bad9 96 {
exopiped 0:8ee38453bad9 97 // execute note state machine
exopiped 0:8ee38453bad9 98 note_state_machine();
exopiped 0:8ee38453bad9 99 if(note_bufno!=NIL) {
exopiped 1:aa184d2eb2e3 100 note_fill_buf();
exopiped 0:8ee38453bad9 101 }
exopiped 0:8ee38453bad9 102
exopiped 0:8ee38453bad9 103 // handle presence or absence of touch
exopiped 0:8ee38453bad9 104 if (touch_debounce()) {
exopiped 0:8ee38453bad9 105 wait_ms(10); // wait 10 msec if touch present
exopiped 0:8ee38453bad9 106 if (note_released() || !note_active()) {
exopiped 0:8ee38453bad9 107 note_start();
exopiped 0:8ee38453bad9 108 }
exopiped 0:8ee38453bad9 109 } else {
exopiped 0:8ee38453bad9 110 if (note_active()) {
exopiped 0:8ee38453bad9 111 if (!note_released()) {
exopiped 0:8ee38453bad9 112 note_release();
exopiped 0:8ee38453bad9 113 }
exopiped 0:8ee38453bad9 114 }
exopiped 0:8ee38453bad9 115 }
exopiped 0:8ee38453bad9 116 }
exopiped 0:8ee38453bad9 117
exopiped 0:8ee38453bad9 118 void note_state_machine(void)
exopiped 0:8ee38453bad9 119 {
exopiped 0:8ee38453bad9 120 // execute state machine that manages envelope
exopiped 0:8ee38453bad9 121
exopiped 0:8ee38453bad9 122 switch (note_state) {
exopiped 0:8ee38453bad9 123 case NOTE_ATTACK:
exopiped 0:8ee38453bad9 124 if (note_attack_done()) {
exopiped 0:8ee38453bad9 125 note_state = NOTE_DECAY;
exopiped 0:8ee38453bad9 126 }
exopiped 0:8ee38453bad9 127 note_freq = touch_frequency();
exopiped 0:8ee38453bad9 128 break;
exopiped 0:8ee38453bad9 129
exopiped 0:8ee38453bad9 130 case NOTE_DECAY:
exopiped 0:8ee38453bad9 131 if(note_decay_done()) {
exopiped 0:8ee38453bad9 132 note_state = NOTE_SUSTAIN;
exopiped 0:8ee38453bad9 133 }
exopiped 0:8ee38453bad9 134 note_freq = touch_frequency();
exopiped 0:8ee38453bad9 135 break;
exopiped 0:8ee38453bad9 136
exopiped 0:8ee38453bad9 137 case NOTE_SUSTAIN:
exopiped 0:8ee38453bad9 138 note_freq = touch_frequency();
exopiped 0:8ee38453bad9 139 break;
exopiped 0:8ee38453bad9 140
exopiped 0:8ee38453bad9 141 case NOTE_RELEASE:
exopiped 0:8ee38453bad9 142 if (note_release_done()) {
exopiped 0:8ee38453bad9 143 note_end();
exopiped 0:8ee38453bad9 144 break;
exopiped 0:8ee38453bad9 145 }
exopiped 0:8ee38453bad9 146 break;
exopiped 0:8ee38453bad9 147 case NOTE_OFF:
exopiped 0:8ee38453bad9 148 default:
exopiped 0:8ee38453bad9 149 break;
exopiped 0:8ee38453bad9 150 }
exopiped 0:8ee38453bad9 151 }
exopiped 0:8ee38453bad9 152
exopiped 0:8ee38453bad9 153 /*
exopiped 0:8ee38453bad9 154 * note_fill_buf
exopiped 0:8ee38453bad9 155 * Use the first and last buffer envelope values, and the
exopiped 0:8ee38453bad9 156 * wave values returned by wave_nextval() to compute the
exopiped 0:8ee38453bad9 157 * envelop-modified wave values, and then apply the changes
exopiped 0:8ee38453bad9 158 * necessary to output the values to the DAC data register.
exopiped 0:8ee38453bad9 159 */
exopiped 0:8ee38453bad9 160 void note_fill_buf(void)
exopiped 0:8ee38453bad9 161 {
exopiped 0:8ee38453bad9 162 int j,start_env,end_env,env_val,wave_val,buf_val,amplitude;
exopiped 1:aa184d2eb2e3 163 int *bufptr;
exopiped 0:8ee38453bad9 164
exopiped 0:8ee38453bad9 165 bufptr = dma_get_bufptr(note_bufno);
exopiped 0:8ee38453bad9 166 start_env = note_first_bufval;
exopiped 0:8ee38453bad9 167 end_env = note_last_bufval;
exopiped 1:aa184d2eb2e3 168 amplitude = touch_amplitude();
exopiped 0:8ee38453bad9 169
exopiped 0:8ee38453bad9 170 for (j=0;j<DMA_BUFSIZE;j++) {
exopiped 1:aa184d2eb2e3 171 env_val=start_env+(end_env - start_env)*j/DMA_BUFSIZE;
exopiped 1:aa184d2eb2e3 172 wave_val = wave_nextval(note_freq);
exopiped 1:aa184d2eb2e3 173 buf_val = wave_val * env_val / ENVLP_MAX;
exopiped 1:aa184d2eb2e3 174 buf_val=amplitude*buf_val/TOUCH_MAX_AMPLITUDE;
exopiped 1:aa184d2eb2e3 175 bufptr[j]= DAC_POWER_MODE | ((buf_val << 6) & 0xFFC0);
exopiped 0:8ee38453bad9 176 }
exopiped 1:aa184d2eb2e3 177
exopiped 1:aa184d2eb2e3 178 note_bufno = NIL;
exopiped 0:8ee38453bad9 179 switch (note_state) {
exopiped 0:8ee38453bad9 180 case NOTE_ATTACK:
exopiped 0:8ee38453bad9 181 note_attack_bufcount++;
exopiped 0:8ee38453bad9 182 break;
exopiped 0:8ee38453bad9 183 case NOTE_DECAY:
exopiped 0:8ee38453bad9 184 note_decay_bufcount++;
exopiped 0:8ee38453bad9 185 break;
exopiped 1:aa184d2eb2e3 186 case NOTE_SUSTAIN:
exopiped 1:aa184d2eb2e3 187 note_first_bufval = note_last_bufval;
exopiped 1:aa184d2eb2e3 188 break;
exopiped 0:8ee38453bad9 189 case NOTE_RELEASE:
exopiped 0:8ee38453bad9 190 note_first_bufval = note_last_bufval;
exopiped 0:8ee38453bad9 191 note_last_bufval =
exopiped 0:8ee38453bad9 192 note_first_bufval * note_release_numerator
exopiped 0:8ee38453bad9 193 / note_release_denominator;
exopiped 0:8ee38453bad9 194 break;
exopiped 0:8ee38453bad9 195 case NOTE_OFF:
exopiped 0:8ee38453bad9 196 default:
exopiped 0:8ee38453bad9 197 ;
exopiped 0:8ee38453bad9 198 }
exopiped 0:8ee38453bad9 199 }
exopiped 0:8ee38453bad9 200
exopiped 0:8ee38453bad9 201 /*
exopiped 0:8ee38453bad9 202 * note_release
exopiped 0:8ee38453bad9 203 * touch has been lifted, note begins to decay
exopiped 0:8ee38453bad9 204 */
exopiped 0:8ee38453bad9 205 void note_release(void)
exopiped 0:8ee38453bad9 206 {
exopiped 0:8ee38453bad9 207 note_state = NOTE_RELEASE;
exopiped 0:8ee38453bad9 208 }
exopiped 0:8ee38453bad9 209 /*
exopiped 0:8ee38453bad9 210 * note_released
exopiped 0:8ee38453bad9 211 * return true if note has been released
exopiped 0:8ee38453bad9 212 * but not yet ended
exopiped 0:8ee38453bad9 213 */
exopiped 0:8ee38453bad9 214 bool note_released(void)
exopiped 0:8ee38453bad9 215 {
exopiped 0:8ee38453bad9 216 return (note_state == NOTE_RELEASE);
exopiped 0:8ee38453bad9 217 }
exopiped 0:8ee38453bad9 218 bool note_active(void)
exopiped 0:8ee38453bad9 219 {
exopiped 0:8ee38453bad9 220 return (note_state < NOTE_OFF);
exopiped 0:8ee38453bad9 221 }
exopiped 0:8ee38453bad9 222 /*
exopiped 0:8ee38453bad9 223 ** note_set_bufno
exopiped 0:8ee38453bad9 224 * Set the index of the dma buffer to fill.
exopiped 0:8ee38453bad9 225 *
exopiped 0:8ee38453bad9 226 */
exopiped 0:8ee38453bad9 227 void note_set_bufno(int bufno)
exopiped 0:8ee38453bad9 228 {
exopiped 0:8ee38453bad9 229 note_bufno = bufno;
exopiped 0:8ee38453bad9 230 }
exopiped 0:8ee38453bad9 231
exopiped 0:8ee38453bad9 232 void note_attack(void)
exopiped 0:8ee38453bad9 233 {
exopiped 0:8ee38453bad9 234 note_state = NOTE_ATTACK;
exopiped 0:8ee38453bad9 235 note_attack_bufcount = 0;
exopiped 0:8ee38453bad9 236 note_attack_delta = ENVLP_MAX / note_attack_bufs;
exopiped 0:8ee38453bad9 237 note_first_bufval=note_attack_bufcount*note_attack_delta;
exopiped 0:8ee38453bad9 238 note_last_bufval=note_first_bufval + note_attack_delta;
exopiped 0:8ee38453bad9 239 }
exopiped 0:8ee38453bad9 240
exopiped 0:8ee38453bad9 241 bool note_attack_done(void)
exopiped 0:8ee38453bad9 242 {
exopiped 0:8ee38453bad9 243 if (note_attack_bufcount >= note_attack_bufs) {
exopiped 0:8ee38453bad9 244 note_decay_bufcount = 0;
exopiped 0:8ee38453bad9 245 note_decay_delta = (ENVLP_MAX >> 1) / note_decay_bufs;
exopiped 0:8ee38453bad9 246 note_first_bufval = note_last_bufval;
exopiped 0:8ee38453bad9 247 return true;
exopiped 0:8ee38453bad9 248 } else {
exopiped 0:8ee38453bad9 249 note_first_bufval=note_attack_bufcount*note_attack_delta;
exopiped 0:8ee38453bad9 250 note_last_bufval=note_first_bufval+note_attack_delta;
exopiped 0:8ee38453bad9 251 }
exopiped 0:8ee38453bad9 252 return false;
exopiped 0:8ee38453bad9 253 }
exopiped 0:8ee38453bad9 254
exopiped 0:8ee38453bad9 255 bool note_decay_done(void)
exopiped 0:8ee38453bad9 256 {
exopiped 0:8ee38453bad9 257 if (note_decay_bufcount >= note_decay_bufs) {
exopiped 0:8ee38453bad9 258 note_first_bufval = note_last_bufval;
exopiped 0:8ee38453bad9 259 return true;
exopiped 0:8ee38453bad9 260 } else {
exopiped 0:8ee38453bad9 261 note_last_bufval=note_first_bufval - note_decay_delta;
exopiped 0:8ee38453bad9 262 if (note_last_bufval < 0) {
exopiped 0:8ee38453bad9 263 note_last_bufval=0;
exopiped 0:8ee38453bad9 264 }
exopiped 0:8ee38453bad9 265 }
exopiped 0:8ee38453bad9 266 return false;
exopiped 0:8ee38453bad9 267 }
exopiped 0:8ee38453bad9 268
exopiped 0:8ee38453bad9 269 bool note_release_done(void)
exopiped 0:8ee38453bad9 270 {
exopiped 0:8ee38453bad9 271 if (note_first_bufval < 25) return true;
exopiped 0:8ee38453bad9 272 return false;
exopiped 0:8ee38453bad9 273 }
exopiped 0:8ee38453bad9 274