#include #include #include "mont.h" // visualize voice (v) at amplitude (a) on an 8x8 grid void visualize(byte v, byte a) { int x = 64 + ((v & 7) * 34); int y = 14 + ((v >> 3) * 34); byte sprnum = (v << 2); // draw each voice using four sprites GD.sprite(sprnum++, x + 16, y + 16, a, 0, 0); GD.sprite(sprnum++, x + 0, y + 16, a, 0, 2); GD.sprite(sprnum++, x + 16, y + 0, a, 0, 4); GD.sprite(sprnum++, x + 0, y + 0, a, 0, 6); } void setup() { int i; GD.begin(); GD.wr16(RAM_SPRPAL + 2 * 255, TRANSPARENT); // draw 32 circles into 32 sprite images for (i = 0; i < 32; i++) { GD.wr16(RAM_SPRPAL + 2 * i, RGB(8 * i, 64, 255 - 8 * i)); int dst = RAM_SPRIMG + 256 * i; GD.__wstart(dst); byte x, y; int r2 = min(i * i, 256); for (y = 0; y < 16; y++) { for (x = 0; x < 16; x++) { byte pixel; if ((x * x + y * y) <= r2) pixel = i; // use color above else pixel = 0xff; // transparent SPI.transfer(pixel); } } GD.__end(); } Serial.begin(1000000); // JCB for (i = 0; i < 64; i++) visualize(i, 0); } byte amp[64]; // current voice amplitude byte target[64]; // target voice amplitude int shot; // JCB // Set volume for voice v to a void setvol(byte v, byte a) { GD.__wstart(VOICES + (v << 2) + 2); SPI.transfer(a); SPI.transfer(a); GD.__end(); } void adsr() // handle ADSR for 64 voices { byte v; for (v = 0; v < 64; v++) { int d = target[v] - amp[v]; // +ve means need to increase if (d) { if (d > 0) amp[v] += 4; // attack else amp[v]--; // decay setvol(v, amp[v]); visualize(v, amp[v]); } } } void loop() { flash_uint8_t *pc; long started = millis(); int ticks = 0; for (pc = mont; pc < mont + sizeof(mont);) { byte cmd = pgm_read_byte_near(pc++); // upper 2 bits are command code if ((cmd & 0xc0) == 0) { // Command 0x00: pause N*5 milliseconds ticks += (cmd & 63); while (millis() < (started + ticks * 5)) { adsr(); delay(1); } // while ((shot*4) < ticks) GD.screenshot(shot++); // JCB } else { byte v = (cmd & 63); byte a; if ((cmd & 0xc0) == 0x40) { // Command 0x40: silence voice target[v] = 0; } else if ((cmd & 0xc0) == 0x80) { // Command 0x80: set voice frequency and amplitude byte flo = pgm_read_byte_near(pc++); byte fhi = pgm_read_byte_near(pc++); GD.__wstart(VOICES + 4 * v); SPI.transfer(flo); SPI.transfer(fhi); GD.__end(); target[v] = pgm_read_byte_near(pc++); } } } }