diff options
Diffstat (limited to 'quantum/beeps.c')
| -rw-r--r-- | quantum/beeps.c | 246 |
1 files changed, 246 insertions, 0 deletions
diff --git a/quantum/beeps.c b/quantum/beeps.c new file mode 100644 index 000000000..8d1f81f21 --- /dev/null +++ b/quantum/beeps.c | |||
| @@ -0,0 +1,246 @@ | |||
| 1 | #include "beeps.h" | ||
| 2 | #include <math.h> | ||
| 3 | #include <avr/pgmspace.h> | ||
| 4 | #include <avr/interrupt.h> | ||
| 5 | #include <avr/io.h> | ||
| 6 | |||
| 7 | #define PI 3.14159265 | ||
| 8 | |||
| 9 | void delay_us(int count) { | ||
| 10 | while(count--) { | ||
| 11 | _delay_us(1); | ||
| 12 | } | ||
| 13 | } | ||
| 14 | |||
| 15 | int voices = 0; | ||
| 16 | double frequency = 0; | ||
| 17 | int volume = 0; | ||
| 18 | int position = 0; | ||
| 19 | |||
| 20 | double frequencies[8] = {0, 0, 0, 0, 0, 0, 0, 0}; | ||
| 21 | int volumes[8] = {0, 0, 0, 0, 0, 0, 0, 0}; | ||
| 22 | bool sliding = false; | ||
| 23 | #define RANGE 1000 | ||
| 24 | volatile int i=0; //elements of the wave | ||
| 25 | |||
| 26 | |||
| 27 | void beeps() { | ||
| 28 | play_notes(); | ||
| 29 | } | ||
| 30 | |||
| 31 | void send_freq(double freq, int vol) { | ||
| 32 | int duty = (((double)F_CPU) / freq); | ||
| 33 | ICR3 = duty; // Set max to the period | ||
| 34 | OCR3A = duty >> (0x10 - vol); // Set compare to half the period | ||
| 35 | } | ||
| 36 | |||
| 37 | void stop_all_notes() { | ||
| 38 | voices = 0; | ||
| 39 | TCCR3A = 0; | ||
| 40 | TCCR3B = 0; | ||
| 41 | frequency = 0; | ||
| 42 | volume = 0; | ||
| 43 | |||
| 44 | for (int i = 0; i < 8; i++) { | ||
| 45 | frequencies[i] = 0; | ||
| 46 | volumes[i] = 0; | ||
| 47 | } | ||
| 48 | } | ||
| 49 | |||
| 50 | void stop_note(double freq) { | ||
| 51 | for (int i = 7; i >= 0; i--) { | ||
| 52 | if (frequencies[i] == freq) { | ||
| 53 | frequencies[i] = 0; | ||
| 54 | volumes[i] = 0; | ||
| 55 | for (int j = i; (j < 7); j++) { | ||
| 56 | frequencies[j] = frequencies[j+1]; | ||
| 57 | frequencies[j+1] = 0; | ||
| 58 | volumes[j] = volumes[j+1]; | ||
| 59 | volumes[j+1] = 0; | ||
| 60 | } | ||
| 61 | } | ||
| 62 | } | ||
| 63 | voices--; | ||
| 64 | if (voices < 0) | ||
| 65 | voices = 0; | ||
| 66 | if (voices == 0) { | ||
| 67 | TCCR3A = 0; | ||
| 68 | TCCR3B = 0; | ||
| 69 | frequency = 0; | ||
| 70 | volume = 0; | ||
| 71 | } else { | ||
| 72 | double freq = frequencies[voices - 1]; | ||
| 73 | int vol = volumes[voices - 1]; | ||
| 74 | if (frequency < freq) { | ||
| 75 | sliding = true; | ||
| 76 | for (double f = frequency; f <= freq; f += ((freq - frequency) / 500.0)) { | ||
| 77 | send_freq(f, vol); | ||
| 78 | } | ||
| 79 | sliding = false; | ||
| 80 | } else if (frequency > freq) { | ||
| 81 | sliding = true; | ||
| 82 | for (double f = frequency; f >= freq; f -= ((frequency - freq) / 500.0)) { | ||
| 83 | send_freq(f, vol); | ||
| 84 | } | ||
| 85 | sliding = false; | ||
| 86 | } | ||
| 87 | send_freq(freq, vol); | ||
| 88 | frequency = freq; | ||
| 89 | volume = vol; | ||
| 90 | } | ||
| 91 | } | ||
| 92 | |||
| 93 | void init_notes() { | ||
| 94 | // TCCR1A = (1 << COM1A1) | (0 << COM1A0) | (1 << WGM11) | (1 << WGM10); | ||
| 95 | // TCCR1B = (1 << COM1B1) | (0 << COM1A0) | (1 << WGM13) | (1 << WGM12) | (0 << CS12) | (0 << CS11) | (1 << CS10); | ||
| 96 | |||
| 97 | // DDRC |= (1<<6); | ||
| 98 | |||
| 99 | // TCCR3A = (1 << COM3A1) | (0 << COM3A0) | (1 << WGM31) | (0 << WGM30); | ||
| 100 | // TCCR3B = (1 << WGM33) | (1 << WGM32) | (0 << CS32) | (0 << CS31) | (1 << CS30); | ||
| 101 | |||
| 102 | // ICR3 = 0xFFFF; | ||
| 103 | // OCR3A = (int)((float)wave[i]*ICR3/RANGE); //go to next array element | ||
| 104 | |||
| 105 | |||
| 106 | // cli(); | ||
| 107 | |||
| 108 | // /* Enable interrupt on timer2 == 127, with clk/8 prescaler. At 16MHz, | ||
| 109 | // this gives a timer interrupt at 15625Hz. */ | ||
| 110 | // TIMSK3 = (1 << OCIE3A); | ||
| 111 | |||
| 112 | // /* clear/reset timer on match */ | ||
| 113 | // // TCCR3A = 1<<WGM31 | 0<<WGM30; CTC mode, reset on match | ||
| 114 | // // TCCR3B = 0<<CS32 | 1<<CS31 | 0<<CS30; /* clk, /8 prescaler */ | ||
| 115 | |||
| 116 | // TCCR3A = (1 << COM3A1) | (0 << COM3A0) | (1 << WGM31) | (0 << WGM30); | ||
| 117 | // TCCR3B = (0 << WGM33) | (0 << WGM32) | (0 << CS32) | (0 << CS31) | (1 << CS30); | ||
| 118 | |||
| 119 | |||
| 120 | // TCCR1A = (1 << COM1A1) | (0 << COM1A0) | (1 << WGM11) | (0 << WGM10); | ||
| 121 | // TCCR1B = (1 << WGM12) | (0 << CS12) | (0 << CS11) | (1 << CS10); | ||
| 122 | // // SPCR = 0x50; | ||
| 123 | // // SPSR = 0x01; | ||
| 124 | // DDRC |= (1<<6); | ||
| 125 | // // ICR3 = 0xFFFF; | ||
| 126 | // // OCR3A=80; | ||
| 127 | // PORTC |= (1<<6); | ||
| 128 | |||
| 129 | // sei(); | ||
| 130 | } | ||
| 131 | |||
| 132 | // #define highByte(c) ((c >> 8) & 0x00FF) | ||
| 133 | // #define lowByte(c) (c & 0x00FF) | ||
| 134 | |||
| 135 | ISR(TIMER3_COMPA_vect) { | ||
| 136 | |||
| 137 | if (ICR3 > 0 && !sliding) { | ||
| 138 | switch (position) { | ||
| 139 | case 0: { | ||
| 140 | int duty = (((double)F_CPU) / (frequency)); | ||
| 141 | ICR3 = duty; // Set max to the period | ||
| 142 | OCR3A = duty >> 1; // Set compare to half the period | ||
| 143 | break; | ||
| 144 | } | ||
| 145 | case 1: { | ||
| 146 | int duty = (((double)F_CPU) / (frequency*2)); | ||
| 147 | ICR3 = duty; // Set max to the period | ||
| 148 | OCR3A = duty >> 1; // Set compare to half the period | ||
| 149 | break; | ||
| 150 | } | ||
| 151 | case 2: { | ||
| 152 | int duty = (((double)F_CPU) / (frequency*3)); | ||
| 153 | ICR3 = duty; // Set max to the period | ||
| 154 | OCR3A = duty >> 1; // Set compare to half the period | ||
| 155 | break; | ||
| 156 | } | ||
| 157 | } | ||
| 158 | position = (position + 1) % 3; | ||
| 159 | } | ||
| 160 | // /* OCR2A has been cleared, per TCCR2A above */ | ||
| 161 | // // OCR3A = 127; | ||
| 162 | |||
| 163 | // // pos1 += incr1; | ||
| 164 | // // pos2 += incr2; | ||
| 165 | // // pos3 += incr3; | ||
| 166 | |||
| 167 | // // sample = sinewave[highByte(pos1)] + sinewave[highByte(pos2)] + sinewave[highByte(pos3)]; | ||
| 168 | |||
| 169 | // // OCR3A = sample; | ||
| 170 | |||
| 171 | |||
| 172 | // OCR3A=pgm_read_byte(&sinewave[pos1]); | ||
| 173 | // pos1++; | ||
| 174 | // // PORTC &= ~(1<<6); | ||
| 175 | |||
| 176 | // /* buffered, 1x gain, active mode */ | ||
| 177 | // // SPDR = highByte(sample) | 0x70; | ||
| 178 | // // while (!(SPSR & (1<<SPIF))); | ||
| 179 | |||
| 180 | // // SPDR = lowByte(sample); | ||
| 181 | // // while (!(SPSR & (1<<SPIF))); | ||
| 182 | |||
| 183 | // // PORTC |= (1<<6); | ||
| 184 | } | ||
| 185 | |||
| 186 | void play_note(double freq, int vol) { | ||
| 187 | |||
| 188 | if (freq > 0) { | ||
| 189 | DDRC |= (1<<6); | ||
| 190 | |||
| 191 | TCCR3A = (1 << COM3A1) | (0 << COM3A0) | (1 << WGM31) | (0 << WGM30); | ||
| 192 | TCCR3B = (1 << WGM33) | (1 << WGM32) | (0 << CS32) | (1 << CS31) | (0 << CS30); | ||
| 193 | |||
| 194 | if (frequency != 0) { | ||
| 195 | if (frequency < freq) { | ||
| 196 | for (double f = frequency; f <= freq; f += ((freq - frequency) / 500.0)) { | ||
| 197 | send_freq(f, vol); | ||
| 198 | } | ||
| 199 | } else if (frequency > freq) { | ||
| 200 | for (double f = frequency; f >= freq; f -= ((frequency - freq) / 500.0)) { | ||
| 201 | send_freq(f, vol); | ||
| 202 | } | ||
| 203 | } | ||
| 204 | } | ||
| 205 | send_freq(freq, vol); | ||
| 206 | frequency = freq; | ||
| 207 | volume = vol; | ||
| 208 | |||
| 209 | frequencies[voices] = frequency; | ||
| 210 | volumes[voices] = volume; | ||
| 211 | voices++; | ||
| 212 | } | ||
| 213 | // ICR3 = 0xFFFF; | ||
| 214 | // for (int i = 0; i < 10000; i++) { | ||
| 215 | // OCR3A = round((sin(i*freq)*.5)+.5)*0xFFFF; | ||
| 216 | // // _delay_us(50); | ||
| 217 | // } | ||
| 218 | |||
| 219 | // TCCR3A = 0; | ||
| 220 | // TCCR3B = 0; | ||
| 221 | } | ||
| 222 | |||
| 223 | // void note(int x, float length) { | ||
| 224 | // DDRC |= (1<<6); | ||
| 225 | // int t = (int)(440*pow(2,-x/12.0)); // starting note | ||
| 226 | // for (int y = 0; y < length*1000/t; y++) { // note length | ||
| 227 | // PORTC |= (1<<6); | ||
| 228 | // delay_us(t); | ||
| 229 | // PORTC &= ~(1<<6); | ||
| 230 | // delay_us(t); | ||
| 231 | // } | ||
| 232 | // PORTC &= ~(1<<6); | ||
| 233 | // } | ||
| 234 | |||
| 235 | // void true_note(float x, float y, float length) { | ||
| 236 | // for (uint32_t i = 0; i < length * 50; i++) { | ||
| 237 | // uint32_t v = (uint32_t) (round(sin(PI*2*i*640000*pow(2, x/12.0))*.5+1 + sin(PI*2*i*640000*pow(2, y/12.0))*.5+1) / 2 * pow(2, 8)); | ||
| 238 | // for (int u = 0; u < 8; u++) { | ||
| 239 | // if (v & (1 << u) && !(PORTC&(1<<6))) | ||
| 240 | // PORTC |= (1<<6); | ||
| 241 | // else if (PORTC&(1<<6)) | ||
| 242 | // PORTC &= ~(1<<6); | ||
| 243 | // } | ||
| 244 | // } | ||
| 245 | // PORTC &= ~(1<<6); | ||
| 246 | // } \ No newline at end of file | ||
