2013-10-28 13:19:25 +00:00

230 lines
4.7 KiB
Plaintext

#include <SPI.h>
#include <GD.h>
// ----------------------------------------------------------------------
// controller: buttons on Arduino pins 3,4,5,6 with 7 grounded
// ----------------------------------------------------------------------
static void controller_init()
{
// Configure input pins with internal pullups
byte i;
for (i = 3; i < 7; i++) {
pinMode(i, INPUT);
digitalWrite(i, HIGH);
}
// drive pin 7 low
pinMode(7, OUTPUT);
digitalWrite(7, 0);
}
#define CONTROL_LEFT 1
#define CONTROL_RIGHT 2
#define CONTROL_UP 4
#define CONTROL_DOWN 8
static byte controller_sense()
{
byte r = 0;
if (!digitalRead(5))
r |= CONTROL_DOWN;
if (!digitalRead(4))
r |= CONTROL_UP;
if (!digitalRead(6))
r |= CONTROL_LEFT;
if (!digitalRead(3))
r |= CONTROL_RIGHT;
return r;
}
#define FLOCAL 2
#define SEL_local() digitalWrite(FLOCAL, LOW)
#define UNSEL_local() digitalWrite(FLOCAL, HIGH)
struct dirent {
char name[12];
uint16_t length;
uint32_t addr;
};
static uint32_t flash_readn(byte *dst, uint32_t src, size_t n)
{
SEL_local();
SPI.transfer(0x03);
SPI.transfer((byte)(src >> 16));
SPI.transfer((byte)(src >> 8));
SPI.transfer((byte)(src >> 0));
while (n--) {
*dst++ = SPI.transfer(0);
src++;
if ((511 & (uint16_t)src) == 264)
src = src - 264 + 512;
}
UNSEL_local();
return src;
}
uint16_t samp_len;
uint32_t samp_ptr;
static dirent de;
static byte find_name(uint32_t &ptr, uint16_t &len, uint32_t dirptr, char *name)
{
while (true) {
dirptr = flash_readn((byte*)&de, dirptr, sizeof(de));
if (de.name[0] == 0)
return 0; // end of dir, no match found
if (strcmp(de.name, name) == 0) {
len = de.length;
ptr = de.addr;
return 1;
}
}
}
static byte ninstruments;
static dirent instruments[32];
struct active {
byte instrument;
uint32_t addr;
uint16_t pos, length;
uint16_t x, y;
};
#define NACTIVE 3
static active playing[NACTIVE];
struct active *findidle()
{
byte i;
for (i = 0; i < NACTIVE; i++)
if (playing[i].addr == 0)
return &playing[i];
return NULL;
}
static void kickoff(byte i)
{
active *p = findidle();
if (p) {
p->addr = instruments[i].addr;
p->pos = 0;
p->length = instruments[i].length;
p->x = 0;
p->y = 16 + 16 * i;
}
}
static void fromflash(uint16_t dst, uint32_t src, uint16_t len)
{
while (len--) {
byte v;
src = flash_readn(&v, src, 1);
GD.wr(dst++, v);
}
}
static byte sprstr(int x, int y, byte spr, const char *txt)
{
char c;
while ((c = *txt++) != 0) {
GD.sprite(spr++, x, y, (c - ' ') >> 2, 8 + ((c & 3) << 1), 0);
x += 11;
}
return spr;
}
// add all samples from dir
void add_samples(uint32_t dir)
{
dirent *pi = &instruments[ninstruments];
while (dir = flash_readn((byte*)pi, dir, sizeof(*pi)), pi->name[0]) {
pi++, ninstruments++;
}
}
void setup()
{
controller_init();
GD.begin();
GD.ascii();
pinMode(FLOCAL, OUTPUT);
UNSEL_local();
GD.wr(IOMODE, 'F');
uint32_t assetroot = 512L * 640;
uint32_t dk;
uint16_t dkl;
find_name(dk, dkl, assetroot, "voice");
add_samples(dk);
find_name(dk, dkl, assetroot, "drumkit");
add_samples(dk);
byte i;
for (i = 0; i < ninstruments; i++) {
byte x = (50 - strlen(instruments[i].name)) >> 1;
GD.putstr(x, 2 + i, instruments[i].name);
}
uint32_t sd;
uint16_t sdl;
if (1) {
find_name(dk, dkl, assetroot, "pickups");
find_name(sd, sdl, dk, "pal");
fromflash(RAM_SPRPAL, sd, sdl);
find_name(sd, sdl, dk, "img");
fromflash(RAM_SPRIMG, sd, sdl);
}
}
#include "soundbuffer.h"
#define SOUNDBUFFER 0x3f00
int cursor;
void loop()
{
GD.microcode(soundbuffer_code, sizeof(soundbuffer_code));
byte writepointer = 0;
for (;;) {
active *p;
byte i;
byte readpointer = GD.rd(COMM+0);
byte fullness = writepointer - readpointer;
while (fullness < 254) {
char total = 0;
for (p = playing, i = 0; i < NACTIVE; p++, i++) {
if (p->addr) {
char v;
p->addr = flash_readn((byte*)&v, p->addr, 1);
total += (v >> 1);
if (++p->pos >= p->length)
p->addr = 0;
}
}
GD.wr(SOUNDBUFFER + writepointer++, total);
fullness++;
}
GD.waitvblank();
GD.sprite(0, 142, 11 + 8 * cursor, 47, 0, 0);
GD.sprite(1, 238, 11 + 8 * cursor, 47, 0, 2);
static byte prev;
byte press;
press = controller_sense();
press = random(16);
if (prev == 0) {
if (press & CONTROL_DOWN)
cursor = min(ninstruments - 1, cursor + 1);
if (press & CONTROL_UP)
cursor = max(0, cursor - 1);
if (press & (CONTROL_RIGHT | CONTROL_LEFT))
kickoff(cursor);
}
prev = press;
}
}