player.pde 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109
  1. #include <SPI.h>
  2. #include <GD.h>
  3. #include "mont.h"
  4. // visualize voice (v) at amplitude (a) on an 8x8 grid
  5. void visualize(byte v, byte a)
  6. {
  7. int x = 64 + ((v & 7) * 34);
  8. int y = 14 + ((v >> 3) * 34);
  9. byte sprnum = (v << 2); // draw each voice using four sprites
  10. GD.sprite(sprnum++, x + 16, y + 16, a, 0, 0);
  11. GD.sprite(sprnum++, x + 0, y + 16, a, 0, 2);
  12. GD.sprite(sprnum++, x + 16, y + 0, a, 0, 4);
  13. GD.sprite(sprnum++, x + 0, y + 0, a, 0, 6);
  14. }
  15. void setup()
  16. {
  17. int i;
  18. GD.begin();
  19. GD.wr16(RAM_SPRPAL + 2 * 255, TRANSPARENT);
  20. // draw 32 circles into 32 sprite images
  21. for (i = 0; i < 32; i++) {
  22. GD.wr16(RAM_SPRPAL + 2 * i, RGB(8 * i, 64, 255 - 8 * i));
  23. int dst = RAM_SPRIMG + 256 * i;
  24. GD.__wstart(dst);
  25. byte x, y;
  26. int r2 = min(i * i, 256);
  27. for (y = 0; y < 16; y++) {
  28. for (x = 0; x < 16; x++) {
  29. byte pixel;
  30. if ((x * x + y * y) <= r2)
  31. pixel = i; // use color above
  32. else
  33. pixel = 0xff; // transparent
  34. SPI.transfer(pixel);
  35. }
  36. }
  37. GD.__end();
  38. }
  39. for (i = 0; i < 64; i++)
  40. visualize(i, 0);
  41. }
  42. byte amp[64]; // current voice amplitude
  43. byte target[64]; // target voice amplitude
  44. // Set volume for voice v to a
  45. void setvol(byte v, byte a)
  46. {
  47. GD.__wstart(VOICES + (v << 2) + 2);
  48. SPI.transfer(a);
  49. SPI.transfer(a);
  50. GD.__end();
  51. }
  52. void adsr() // handle ADSR for 64 voices
  53. {
  54. byte v;
  55. for (v = 0; v < 64; v++) {
  56. int d = target[v] - amp[v]; // +ve means need to increase
  57. if (d) {
  58. if (d > 0)
  59. amp[v] += 4; // attack
  60. else
  61. amp[v]--; // decay
  62. setvol(v, amp[v]);
  63. visualize(v, amp[v]);
  64. }
  65. }
  66. }
  67. void loop()
  68. {
  69. prog_uchar *pc;
  70. long started = millis();
  71. int ticks = 0;
  72. for (pc = mont; pc < mont + sizeof(mont);) {
  73. byte cmd = pgm_read_byte_near(pc++); // upper 2 bits are command code
  74. if ((cmd & 0xc0) == 0) {
  75. // Command 0x00: pause N*5 milliseconds
  76. ticks += (cmd & 63);
  77. while (millis() < (started + ticks * 5)) {
  78. adsr();
  79. delay(1);
  80. }
  81. } else {
  82. byte v = (cmd & 63);
  83. byte a;
  84. if ((cmd & 0xc0) == 0x40) {
  85. // Command 0x40: silence voice
  86. target[v] = 0;
  87. } else if ((cmd & 0xc0) == 0x80) {
  88. // Command 0x80: set voice frequency and amplitude
  89. byte flo = pgm_read_byte_near(pc++);
  90. byte fhi = pgm_read_byte_near(pc++);
  91. GD.__wstart(VOICES + 4 * v);
  92. SPI.transfer(flo);
  93. SPI.transfer(fhi);
  94. GD.__end();
  95. target[v] = pgm_read_byte_near(pc++);
  96. }
  97. }
  98. }
  99. }