beeps.c 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220
  1. #include "beeps.h"
  2. #include <math.h>
  3. #include <avr/pgmspace.h>
  4. #include <avr/interrupt.h>
  5. #include <avr/io.h>
  6. #define PI 3.14159265
  7. #define CHANNEL OCR1C
  8. void delay_us(int count) {
  9. while(count--) {
  10. _delay_us(1);
  11. }
  12. }
  13. int voices = 0;
  14. double frequency = 0;
  15. int volume = 0;
  16. double frequencies[8] = {0, 0, 0, 0, 0, 0, 0, 0};
  17. int volumes[8] = {0, 0, 0, 0, 0, 0, 0, 0};
  18. void beeps() {
  19. // DDRB |= (1<<7);
  20. // PORTB &= ~(1<<7);
  21. // // Use full 16-bit resolution.
  22. // ICR1 = 0xFFFF;
  23. // // I could write a wall of text here to explain... but TL;DW
  24. // // Go read the ATmega32u4 datasheet.
  25. // // And this: http://blog.saikoled.com/post/43165849837/secret-konami-cheat-code-to-high-resolution-pwm-on
  26. // // Pin PB7 = OCR1C (Timer 1, Channel C)
  27. // // Compare Output Mode = Clear on compare match, Channel C = COM1C1=1 COM1C0=0
  28. // // (i.e. start high, go low when counter matches.)
  29. // // WGM Mode 14 (Fast PWM) = WGM13=1 WGM12=1 WGM11=1 WGM10=0
  30. // // Clock Select = clk/1 (no prescaling) = CS12=0 CS11=0 CS10=1
  31. // TCCR1A = _BV(COM1C1) | _BV(WGM11); // = 0b00001010;
  32. // TCCR1B = _BV(WGM13) | _BV(WGM12) | _BV(CS10); // = 0b00011001;
  33. // // Turn off PWM control on PB7, revert to output low.
  34. // // TCCR1A &= ~(_BV(COM1C1));
  35. // // CHANNEL = ((1 << level) - 1);
  36. // // Turn on PWM control of PB7
  37. // TCCR1A |= _BV(COM1C1);
  38. // // CHANNEL = level << OFFSET | 0x0FFF;
  39. // // CHANNEL = 0b1010101010101010;
  40. // float x = 12;
  41. // float y = 24;
  42. // float length = 50;
  43. // float scale = 1;
  44. // // int f1 = 1000000/440;
  45. // // int f2 = 1000000/880;
  46. // // for (uint32_t i = 0; i < length * 1000; i++) {
  47. // // // int frequency = 1/((sin(PI*2*i*scale*pow(2, x/12.0))*.5+1 + sin(PI*2*i*scale*pow(2, y/12.0))*.5+1) / 2);
  48. // // ICR1 = f1; // Set max to the period
  49. // // OCR1C = f1 >> 1; // Set compare to half the period
  50. // // // _delay_us(10);
  51. // // }
  52. // int frequency = 1000000/440;
  53. // ICR1 = frequency; // Set max to the period
  54. // OCR1C = frequency >> 1; // Set compare to half the period
  55. // _delay_us(500000);
  56. // TCCR1A &= ~(_BV(COM1C1));
  57. // CHANNEL = 0;
  58. play_notes();
  59. // play_note(55*pow(2, 0/12.0), 1);
  60. // play_note(55*pow(2, 12/12.0), 1);
  61. // play_note(55*pow(2, 24/12.0), 1);
  62. // play_note(55*pow(2, 0/12.0), 1);
  63. // play_note(55*pow(2, 12/12.0), 1);
  64. // play_note(55*pow(2, 24/12.0), 1);
  65. // play_note(0, 4);
  66. // play_note(55*pow(2, 0/12.0), 8);
  67. // play_note(55*pow(2, 12/12.0), 4);
  68. // play_note(55*pow(2, 10/12.0), 4);
  69. // play_note(55*pow(2, 12/12.0), 8);
  70. // play_note(55*pow(2, 10/12.0), 4);
  71. // play_note(55*pow(2, 7/12.0), 2);
  72. // play_note(55*pow(2, 8/12.0), 2);
  73. // play_note(55*pow(2, 7/12.0), 16);
  74. // play_note(0, 4);
  75. // play_note(55*pow(2, 3/12.0), 8);
  76. // play_note(55*pow(2, 5/12.0), 4);
  77. // play_note(55*pow(2, 7/12.0), 4);
  78. // play_note(55*pow(2, 7/12.0), 8);
  79. // play_note(55*pow(2, 5/12.0), 4);
  80. // play_note(55*pow(2, 3/12.0), 4);
  81. // play_note(55*pow(2, 2/12.0), 16);
  82. }
  83. void send_freq(double freq, int vol) {
  84. int duty = (((double)F_CPU) / freq);
  85. ICR3 = duty; // Set max to the period
  86. OCR3A = duty >> (0x10 - vol); // Set compare to half the period
  87. }
  88. void stop_all_notes() {
  89. voices = 0;
  90. TCCR3A = 0;
  91. TCCR3B = 0;
  92. frequency = 0;
  93. for (int i = 0; i < 8; i++) {
  94. frequencies[i] = 0;
  95. volumes[i] = 0;
  96. }
  97. }
  98. void stop_note(double freq) {
  99. for (int i = 7; i >= 0; i--) {
  100. if (frequencies[i] == freq) {
  101. frequencies[i] = 0;
  102. volumes[i] = 0;
  103. for (int j = i; (j < 7); j++) {
  104. frequencies[j] = frequencies[j+1];
  105. frequencies[j+1] = 0;
  106. volumes[j] = volumes[j+1];
  107. volumes[j+1] = 0;
  108. }
  109. }
  110. }
  111. voices--;
  112. if (voices == 0) {
  113. TCCR3A = 0;
  114. TCCR3B = 0;
  115. frequency = 0;
  116. } else {
  117. double freq = frequencies[voices - 1];
  118. int vol = volumes[voices - 1];
  119. if (frequency < freq) {
  120. for (double f = frequency; f <= freq; f += ((freq - frequency) / 500.0)) {
  121. send_freq(f, vol);
  122. }
  123. } else if (frequency > freq) {
  124. for (double f = frequency; f >= freq; f -= ((frequency - freq) / 500.0)) {
  125. send_freq(f, vol);
  126. }
  127. }
  128. send_freq(freq, vol);
  129. frequency = freq;
  130. volume = vol;
  131. }
  132. }
  133. void play_note(double freq, int vol) {
  134. if (freq > 0) {
  135. DDRC |= (1<<6);
  136. TCCR3A = (1 << COM3A1) | (0 << COM3A0) | (1 << WGM31) | (0 << WGM30);
  137. TCCR3B = (1 << WGM33) | (1 << WGM32) | (0 << CS32) | (1 << CS31) | (0 << CS30);
  138. if (frequency != 0) {
  139. if (frequency < freq) {
  140. for (double f = frequency; f <= freq; f += ((freq - frequency) / 500.0)) {
  141. send_freq(f, vol);
  142. }
  143. } else if (frequency > freq) {
  144. for (double f = frequency; f >= freq; f -= ((frequency - freq) / 500.0)) {
  145. send_freq(f, vol);
  146. }
  147. }
  148. }
  149. send_freq(freq, vol);
  150. frequency = freq;
  151. volume = vol;
  152. frequencies[voices] = frequency;
  153. volumes[voices] = volume;
  154. voices++;
  155. }
  156. // ICR3 = 0xFFFF;
  157. // for (int i = 0; i < 10000; i++) {
  158. // OCR3A = round((sin(i*freq)*.5)+.5)*0xFFFF;
  159. // // _delay_us(50);
  160. // }
  161. // TCCR3A = 0;
  162. // TCCR3B = 0;
  163. }
  164. void note(int x, float length) {
  165. DDRC |= (1<<6);
  166. int t = (int)(440*pow(2,-x/12.0)); // starting note
  167. for (int y = 0; y < length*1000/t; y++) { // note length
  168. PORTC |= (1<<6);
  169. delay_us(t);
  170. PORTC &= ~(1<<6);
  171. delay_us(t);
  172. }
  173. PORTC &= ~(1<<6);
  174. }
  175. void true_note(float x, float y, float length) {
  176. for (uint32_t i = 0; i < length * 50; i++) {
  177. 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));
  178. for (int u = 0; u < 8; u++) {
  179. if (v & (1 << u) && !(PORTC&(1<<6)))
  180. PORTC |= (1<<6);
  181. else if (PORTC&(1<<6))
  182. PORTC &= ~(1<<6);
  183. }
  184. }
  185. PORTC &= ~(1<<6);
  186. }