singingPlant.ino 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241
  1. #include <SPI.h>
  2. #include <GD.h>
  3. #include "mont.h"
  4. long started =0;
  5. int ticks = 0;
  6. const uint8_t *pc;
  7. // visualize voice (v) at amplitude (a) on an 8x8 grid
  8. #define SET(x,y) (x |=(1<<y)) //-Bit set/clear macros
  9. #define CLR(x,y) (x &= (~(1<<y))) // |
  10. #define CHK(x,y) (x & (1<<y)) // |
  11. #define TOG(x,y) (x^=(1<<y)) //-+
  12. #define N 120 // How many frequencies
  13. float results[N]; // Filtered result buffer
  14. int sizeOfArray = N;
  15. int fixedGraph = 0;
  16. int topPoint = 0;
  17. int topPointValue = 0;
  18. int topPointInterPolated = 0;
  19. int baseline = 0;
  20. int baselineMax =0;
  21. int value = 0;
  22. void visualize(byte v, byte a)
  23. {
  24. int x = 64 + ((v & 7) * 34);
  25. int y = 14 + ((v >> 3) * 34);
  26. byte sprnum = (v << 2); // draw each voice using four sprites
  27. GD.sprite(sprnum++, x + 16, y + 16, a, 0, 0);
  28. GD.sprite(sprnum++, x + 0, y + 16, a, 0, 2);
  29. GD.sprite(sprnum++, x + 16, y + 0, a, 0, 4);
  30. GD.sprite(sprnum++, x + 0, y + 0, a, 0, 6);
  31. }
  32. void setup()
  33. {
  34. gBegin(34526);
  35. // max and min buttons
  36. pinMode(A1, INPUT);
  37. pinMode(A2, INPUT);
  38. digitalWrite(A1, HIGH);
  39. digitalWrite(A2, HIGH);
  40. int i;
  41. GD.begin(4);
  42. GD.wr16(RAM_SPRPAL + 2 * 255, TRANSPARENT);
  43. // draw 32 circles into 32 sprite images
  44. for (i = 0; i < 32; i++) {
  45. GD.wr16(RAM_SPRPAL + 2 * i, RGB(8 * i, 64, 255 - 8 * i));
  46. int dst = RAM_SPRIMG + 256 * i;
  47. GD.__wstart(dst);
  48. byte x, y;
  49. int r2 = min(i * i, 256);
  50. for (y = 0; y < 16; y++) {
  51. for (x = 0; x < 16; x++) {
  52. byte pixel;
  53. if ((x * x + y * y) <= r2)
  54. pixel = i; // use color above
  55. else
  56. pixel = 0xff; // transparent
  57. SPI.transfer(pixel);
  58. }
  59. }
  60. GD.__end();
  61. }
  62. for (i = 0; i < 64; i++)
  63. visualize(i, 0);
  64. pc = mont;
  65. TCCR1A=0b10000010; //-Set up frequency generator
  66. TCCR1B=0b00011001; //-+
  67. ICR1=110;
  68. OCR1A=55;
  69. pinMode(9,OUTPUT); //-Signal generator pin
  70. for(int i=0;i<N;i++) //-Preset results
  71. results[i]=0; //-+
  72. }
  73. byte amp[64]; // current voice amplitude
  74. byte target[64]; // target voice amplitude
  75. // Set volume for voice v to a
  76. void setvol(byte v, byte a)
  77. {
  78. GD.__wstart(VOICES + (v << 2) + 2);
  79. SPI.transfer(a);
  80. SPI.transfer(a);
  81. GD.__end();
  82. }
  83. void adsr() // handle ADSR for 64 voices
  84. {
  85. byte v;
  86. for (v = 0; v < 64; v++) {
  87. int d = target[v] - amp[v]; // +ve means need to increase
  88. if (d) {
  89. if (d > 0)
  90. amp[v] += 4; // attack
  91. else
  92. amp[v]--; // decay
  93. if(value < 5)
  94. {
  95. setvol(v, 0);
  96. }
  97. else
  98. {
  99. setvol(v, amp[v]*((float)value/800+0.2));
  100. }
  101. visualize(v, amp[v]);
  102. }
  103. }
  104. }
  105. unsigned int d=0;
  106. boolean btnMax = false;
  107. boolean btnMin = false;
  108. void loop()
  109. {
  110. guino_update();
  111. if (pc >= mont + sizeof(mont) - 4) {
  112. started = millis();
  113. ticks = 0;
  114. pc = mont;
  115. }
  116. if (millis() < (started + ticks * 5)) {
  117. adsr();
  118. } else {
  119. byte cmd = pgm_read_byte_near(pc++); // upper 2 bits are command code
  120. if ((cmd & 0xc0) == 0) {
  121. // Command 0x00: pause N*5 milliseconds
  122. ticks += (cmd & 63);
  123. } else {
  124. byte v = (cmd & 63);
  125. byte a;
  126. if ((cmd & 0xc0) == 0x40) {
  127. // Command 0x40: silence voice
  128. target[v] = 0;
  129. } else if ((cmd & 0xc0) == 0x80) {
  130. // Command 0x80: set voice frequency and amplitude
  131. byte flo = pgm_read_byte_near(pc++);
  132. if (value < 0)
  133. flo = 0;
  134. byte fhi = pgm_read_byte_near(pc++) * ((float) value / 300.0f);
  135. GD.__wstart(VOICES + 4 * v);
  136. SPI.transfer(flo);
  137. SPI.transfer(fhi);
  138. GD.__end();
  139. target[v] = pgm_read_byte_near(pc++);
  140. }
  141. }
  142. }
  143. if (!(d < N)) {
  144. d = 0;
  145. topPoint = 0;
  146. topPointValue = 0;
  147. }
  148. int v = analogRead(0); //-Read response signal
  149. results[d] = results[d] * 0.5 + (float) (v) * 0.5; //Filter results
  150. fixedGraph = round(results[d]);
  151. gUpdateValue(&fixedGraph);
  152. if (topPointValue < results[d]) {
  153. topPointValue = results[d];
  154. topPoint = d;
  155. }
  156. CLR(TCCR1B, 0); //-Stop generator
  157. TCNT1 = 0; //-Reload new frequency
  158. ICR1 = d; // |
  159. OCR1A = d / 2; //-+
  160. SET(TCCR1B, 0); //-Restart generator
  161. d++;
  162. if (d == N) {
  163. topPointInterPolated = topPointInterPolated * 0.5f +
  164. ((topPoint +
  165. results[topPoint] / results[topPoint + 1] * results[topPoint - 1] /
  166. results[topPoint]) * 10.0f) * 0.5f;
  167. value =
  168. max(0, map(topPointInterPolated, baseline, baselineMax, 0, 1000));
  169. gUpdateValue(&topPoint);
  170. gUpdateValue(&value);
  171. gUpdateValue(&topPointInterPolated);
  172. if (!digitalRead(A1) && btnMin) {
  173. baseline = topPointInterPolated;
  174. gUpdateValue(&baseline);
  175. }
  176. btnMin = !digitalRead(A1);
  177. if (!digitalRead(A2) && btnMax) {
  178. baselineMax = topPointInterPolated;
  179. gUpdateValue(&baselineMax);
  180. }
  181. btnMax = !digitalRead(A2);
  182. }
  183. }
  184. // This is where you setup your interface
  185. void gInit()
  186. {
  187. gAddLabel("DisneyTouch", 1);
  188. gAddSpacer(1);
  189. gAddSpacer(1);
  190. gAddFixedGraph("FIXED GRPAPH", -500, 1000, N, &fixedGraph, 40);
  191. gAddSlider(0, N, "TOP", &topPoint);
  192. gAddSlider(0, N * 10, "Interpolated", &topPointInterPolated);
  193. gAddSlider(0, 3000, "Baseline", &baseline);
  194. gAddSlider(0, 3000, "BaselineMax", &baselineMax);
  195. gAddSlider(0, 1000, "Value", &value);
  196. }
  197. // Method called everytime a button has been pressed in the interface.
  198. void gButtonPressed(int id)
  199. {
  200. }
  201. void gItemUpdated(int id)
  202. {
  203. }