singingPlant.ino 5.6 KB

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