SPMA100B ringtone chip

l--putt ichgeh at l--putt.de
Sat May 7 20:34:12 UTC 2011


Hi list!

To get closer to a useful phone, I started a project to create a driver 
for the SPMA100B ringtone chip of the C155. I can replay the commands to 
play the startup and shutdown sounds and have some idea about the 
registers. A problem is the MIDI(?) data send to the chip: It's possible 
to extract the MIDI files from a flash image but the tracks are 
interleaved by the firmware. Some random single track files don't work 
either. Anybody an idea?

I've found other datasheets (in particular for the W56964 of the DPL10) 
and they helped a lot in understanding the SPMA100B due to the 
similarities. Hence, I suggest a common framework for all those chips. 
However, even salsa (embedded version of ALSA) seems excessive since we 
have just a single device. I considered a really simple design with just 
single write-call that blocks until played. Some ioctl solve volume etc. 
But this doesn't communicate the state (playing, fifo empty, finished, 
error) well. Any ideas?

Does anybody know cc-licensed MIDI ringtones? 
http://www.ringtonepirates.de/ seems to have only MP3 sounds. Given its 
name, you also need balls to download there (at least in Germany: 
"offensichtlich illegale Quelle" :-P )

Regards,
Stefan


A hack of hello_world example to play ringtones on SPMA100B chip

---
  src/target/firmware/apps/hello_world/main.c |  330 
++++++++++++++++++++++++++-
  1 files changed, 328 insertions(+), 2 deletions(-)

diff --git a/src/target/firmware/apps/hello_world/main.c 
b/src/target/firmware/apps/hello_world/main.c
index 5e3ed85..f247795 100644
--- a/src/target/firmware/apps/hello_world/main.c
+++ b/src/target/firmware/apps/hello_world/main.c
@@ -68,6 +68,310 @@ static void l1a_l23_rx_cb(uint8_t dlci, struct msgb 
*msg)
      puts("\n");
  }

+/* Define GPIO interface */
+#define ARMIO_LATCH_OUT 0xfffe4802
+#define IO_CNTL_REG    0xfffe4804
+#define ASIC_CONF_REG    0xfffef008
+
+#define IO_CONF_REG    0xfffef00a
+#define CALYPSO_CONF_OFF 4
+
+#define CALYPSO_IO4    (1 << 4)
+#define CALYPSO_IO7    (1 << 7)
+#define CALYPSO_IO8    (1 << 8)
+#define CALYPSO_IO12    (1 << 12)
+
+#define GPIO_ENABLE(pins) { \
+    uint16_t reg = readw(IO_CONF_REG); \
+    reg |= (pins) >> CALYPSO_CONF_OFF; \
+    writew(reg, IO_CONF_REG); }
+
+#define GPIO_OUTPUT(pins) { \
+    uint16_t reg = readw(IO_CNTL_REG); \
+    reg &= ~(pins); \
+    writew(reg, IO_CNTL_REG); }
+
+#define GPIO_SET(pins) { \
+    uint16_t reg = readw(ARMIO_LATCH_OUT); \
+    reg |= (pins); \
+    writew(reg, ARMIO_LATCH_OUT); }
+
+#define GPIO_UNSET(pins) { \
+    uint16_t reg = readw(ARMIO_LATCH_OUT); \
+    reg &= ~(pins); \
+    writew(reg, ARMIO_LATCH_OUT); }
+
+/* Define W569x constants */
+#define MUSIC_REG    0x01800000
+
+#define MUSIC_IRQ    CALYPSO_IO4
+#define MUSIC_A0    CALYPSO_IO8
+#define MUSIC_ON    CALYPSO_IO12
+
+static uint8_t spma100_regread(uint8_t bank)
+{
+    GPIO_UNSET(MUSIC_A0);
+    delay_ms(1);
+    writeb(bank, MUSIC_REG);
+    GPIO_SET(MUSIC_A0);
+
+    delay_ms(1);
+
+    return readb(MUSIC_REG);
+}
+
+static void spma100_dumpregs(void)
+{
+    int i;
+    for(i=0; i<256; i++) {
+        printf("%02x,", spma100_regread(i));
+    }
+    printf("\n\n");
+}
+
+static void spma100_deltaregs(void)
+{
+    int i;
+    static uint8_t state[256];
+    for(i=0; i<256; i++) {
+        char tmp = spma100_regread(i);
+        if(tmp ^ state[i])
+            printf("%02x: %02x, changed by %02x\n", i, tmp, tmp ^ 
state[i]);
+        state[i] = tmp;
+    }
+    printf("\n\n");
+}
+
+static void spma100_regwrite(uint8_t bank, uint8_t data)
+{
+    GPIO_UNSET(MUSIC_A0);
+    delay_ms(1);
+    writeb(bank, MUSIC_REG);
+    GPIO_SET(MUSIC_A0);
+
+    delay_ms(1);
+
+    writeb(data, MUSIC_REG);
+
+    delay_ms(1);
+
+    //spma100_dumpregs();
+    //spma100_deltaregs();
+}
+
+void music_onoff(int on)
+{
+    uint16_t reg = readw(0xfffe4802);
+
+    if(on) {
+        reg |= 0x1000;
+    } else {
+        reg &= 0xefff;
+    }
+
+    writew(reg, 0xfffe4802);
+}
+
+/* HW init */
+void music_init(void)
+{
+    GPIO_ENABLE(MUSIC_ON);
+    GPIO_OUTPUT(MUSIC_ON);
+
+    GPIO_ENABLE(MUSIC_IRQ);
+
+    GPIO_ENABLE(MUSIC_A0);
+    GPIO_OUTPUT(MUSIC_A0);
+
+    writeb(2, 0xfffe4818);
+    printf("GPIO event mode %x\n", readw(0xfffe4814));
+
+    music_onoff(1);
+}
+
+int play_midi = -1;
+static char midi1[] = {0x72, 0xab, 0x62, 0x00, 0xb0, 0xb3, 0x7f, 0xc0, 
0xd2, 0x0b, 0xa7, 0x07, 0xef, 0x3c, 0xce, 0x2f, 0x5e, 0x40, 0x25, 0x3c, 
0xb1, 0x07, 0x18, 0x60, 0x30, 0x7b, 0x57, 0x00, 0x91, 0x7f, 0x3f, 0x92, 
0x63, 0xf3, 0x0b, 0x18, 0x47, 0xf3, 0xc1, 0x10, 0x54, 0x00, 0xb1, 0x4b, 
0x7c, 0x81, 0xe1, 0x00, 0x60, 0x13, 0x50, 0xd6, 0x8a, 0x68, 0x43, 0x90, 
0x43, 0x26, 0x74, 0x81, 0xc1, 0x4c, 0x18, 0x00, 0xd9, 0x2a, 0xe0, 0x63, 
0x5b, 0xb0, 0x0b, 0x5b, 0x6a, 0x11, 0x37, 0x20, 0x13, 0x00, 0xf6, 0x60, 
0x99, 0x70, 0xd6, 0x47, 0x63, 0x5b, 0x7e, 0x31, 0x7b, 0x51, 0x00, 0x90, 
0x0c, 0x0a, 0x92, 0x70, 0xfd, 0x0b, 0x19, 0x47, 0xe1, 0xc1, 0x14, 0x54, 
0x13, 0xb0, 0x43, 0x68, 0x81, 0xe0, 0x0b, 0x66, 0x13, 0x4c, 0xc2, 0x8a, 
0x69, 0x4c, 0x91, 0x43, 0x29, 0x67, 0x92, 0xc0, 0x44, 0x19, 0x00, 0xd8, 
0x32, 0xe6, 0x63, 0x48, 0xb1, 0x0b, 0x55, 0x77, 0x10, 0x37, 0x2b, 0x13, 
0x13, 0xff, 0x73, 0x9b, 0x70, 0xdf, 0x48, 0x69, 0x40, 0x7a, 0x30, 0x7b, 
0x49, 0x00, 0x91, 0x04, 0x12, 0x92, 0x63, 0xfc, 0x0b, 0x1a, 0x4f, 0xed, 
0xc2, 0x1a, 0x5c, 0x00, 0xb1, 0x58, 0x64, 0x81, 0xe1, 0x10, 0x6a, 0x13, 
0x47, 0xcf, 0x8e, 0x4a, 0x54, 0x90, 0x47, 0x94, 0x3c, 0x00, 0xfc, 0x5f, 
0x68, 0x6b, 0x91, 0x47, 0x6b, 0xa7, 0x13, 0x71, 0x5e, 0x1b, 0xb1, 0x97, 
0x10, 0x6d, 0x82, 0x3c, 0xef, 0x8a, 0x6b, 0x3c, 0x91, 0x48, 0x2d, 0x73, 
0x92, 0xc0, 0x4b, 0x1b, 0x00, 0xd3, 0x2d, 0xef, 0x63, 0x43, 0xb1, 0x0b, 
0x5c, 0x63, 0x10, 0x3c, 0x29, 0x13, 0x13, 0xf0, 0x6f, 0x9d, 0x70, 0xd0, 
0x47, 0x70, 0x50, 0x66, 0x30, 0x7b, 0x5f, 0x00, 0x91, 0x00, 0x17, 0x92, 
0x63, 0xf7, 0x0b, 0x1c, 0x48, 0xf9, 0xc9, 0x01, 0x5b, 0x00, 0xb1, 0x48, 
0x76, 0x81, 0xe1, 0x0b, 0x71, 0x13, 0x54, 0xdb, 0x8a, 0x6c, 0x47, 0x90, 
0x4c, 0x3b, 0x7e, 0x81, 0xc1, 0x43, 0x1c, 0x00, 0xdd, 0x22, 0xf2, 0x63, 
0x5f, 0xb0, 0x0b, 0x5a, 0x70, 0x11, 0x3f, 0x33, 0x13, 0x00, 0xf9, 0x7a, 
0x9c, 0x70, 0xd9, 0x4f, 0x74, 0x5f, 0x60, 0x31, 0x7b, 0x51, 0x00, 0x90, 
0x07, 0x01, 0x92, 0x70, 0xfe, 0x0b, 0x1d, 0x48, 0xe4, 0xc9, 0x05, 0x5b, 
0x13, 0xb0, 0x47, 0x6a, 0x81, 0xe0, 0x00, 0x77, 0x13, 0x4f, 0xc9, 0x8a, 
0x6d, 0x4f, 0x91, 0x4c, 0x24, 0x69, 0x92, 0xc0, 0x58, 0x1e, 0x00, 0xdc, 
0x34, 0xf9, 0x63, 0x4c, 0xb1, 0x0b, 0x51, 0x7d, 0x10, 0x3f, 0x37, 0x13, 
0x13, 0xe3, 0x75, 0x9f, 0x70, 0xc3, 0x53, 0x7a, 0x47, 0x7f, 0x34, 0x5b, 
0x4a, 0x00, 0x91, 0xac, 0x55, 0x13, 0x23, 0x80, 0x46, 0x4a, 0x68, 0xf4, 
0x4c, 0x7b, 0x13, 0x06, 0xb1, 0x0a, 0x1e, 0x03, 0x92, 0x8c, 0x36, 0x47, 
0x61, 0xdb, 0x0b, 0x1f, 0x00, 0xcc, 0x4f, 0x82, 0x10, 0x08, 0xc4, 0x65, 
0x6b, 0x69, 0xe5, 0x23, 0x18, 0x77, 0x13, 0x4f, 0x09, 0x3e, 0x43, 0xff, 
0x23, 0x07, 0x61, 0x69, 0xd6, 0x63, 0x6b, 0x20, 0x38, 0x73, 0x4c, 0x23, 
0x23, 0x82, 0x2b, 0x7d, 0x79, 0xb0, 0x10, 0x1e, 0x4e, 0x69, 0xd5, 0x2b, 
0x5d, 0x72, 0xf4, 0x3a, 0x11, 0x5d, 0x4a, 0xff, 0xd0, 0x00, 0x00, 0x00, 
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
+static char midi2[] = {0x00, 0x74, 0x62, 0xc0, 0xd2, 0x07, 0xcf, 0x07, 
0xcf, 0x0b, 0x8e, 0x54, 0xe9, 0xd5, 0x09, 0x47, 0x00, 0xc1, 0x06, 0x7a, 
0x30, 0x77, 0x09, 0x01, 0xb1, 0x44, 0x6f, 0x81, 0xe1, 0x2c, 0x5f, 0x06, 
0x4a, 0xc6, 0x8a, 0x67, 0x4c, 0x91, 0x62, 0x0c, 0x73, 0x87, 0xc1, 0x58, 
0x17, 0x00, 0xde, 0x12, 0xde, 0x76, 0x4a, 0xb0, 0x0b, 0x52, 0x72, 0x11, 
0x23, 0x36, 0x13, 0x01, 0xf9, 0x7b, 0x96, 0x70, 0xd9, 0x60, 0x5f, 0x49, 
0x68, 0x30, 0x7b, 0x58, 0x00, 0x91, 0x13, 0x32, 0x87, 0x76, 0xfd, 0x0b, 
0x17, 0x48, 0xfa, 0xdf, 0x2f, 0x4e, 0x05, 0xb0, 0x4c, 0x77, 0x81, 0xe0, 
0x08, 0x78, 0x13, 0x4d, 0xd9, 0x8a, 0x67, 0x4c, 0x91, 0x5d, 0x17, 0x60, 
0x87, 0xc1, 0x43, 0x17, 0x00, 0xd6, 0x38, 0xde, 0x76, 0x41, 0xb1, 0x0b, 
0x54, 0x63, 0x10, 0x2b, 0x1c, 0x06, 0x05, 0xf8, 0x6a, 0x9c, 0x70, 0xd8, 
0x4c, 0x77, 0x54, 0x5e, 0x30, 0x7b, 0x50, 0x00, 0x91, 0x19, 0x01, 0x87, 
0x76, 0xf2, 0x0b, 0x17, 0x40, 0xcd, 0xd8, 0x2f, 0x46, 0x06, 0xb1, 0x4c, 
0x4d, 0x81, 0xe1, 0x1f, 0x5f, 0x06, 0x46, 0xe9, 0x8a, 0x6d, 0x43, 0x90, 
0x53, 0x35, 0x44, 0x80, 0xc1, 0x4b, 0x17, 0x00, 0xad, 0x02, 0xde, 0x76, 
0x3a, 0xb1, 0x0b, 0xe8, 0x2f, 0x91, 0x1b, 0x0b, 0x74, 0x6d, 0xb1, 0x0b, 
0x16, 0xb6, 0x91, 0x94, 0x0a, 0x06, 0xb4, 0xb7, 0x51, 0x13, 0x91, 0xf3, 
0x10, 0x23, 0x70, 0x02, 0xb1, 0x69, 0x48, 0x50, 0xf3, 0x54, 0x5f, 0x67, 
0x59, 0xe1, 0x6a, 0x17, 0x00, 0xf1, 0x0c, 0x0f, 0x66, 0x06, 0xb1, 0x54, 
0x48, 0x50, 0xce, 0x52, 0x5f, 0x58, 0x5b, 0xe0, 0x55, 0x1c, 0x00, 0xcd, 
0x13, 0x22, 0x4e, 0x02, 0xb1, 0x57, 0x48, 0x50, 0xcd, 0x51, 0x5f, 0x5d, 
0x59, 0xe1, 0x50, 0x17, 0x00, 0xcb, 0x0f, 0x0f, 0x5c, 0x06, 0xb1, 0x52, 
0x48, 0x50, 0xc8, 0x4f, 0x5f, 0x5e, 0x5b, 0xe0, 0x53, 0x1c, 0x00, 0xc7, 
0x17, 0x20, 0x44, 0x02, 0xb1, 0x5d, 0x48, 0x50, 0xc7, 0x4e, 0x5f, 0x53, 
0x59, 0xe1, 0x5e, 0x17, 0x0f, 0xc5, 0x12, 0x0f, 0x52, 0x06, 0xb1, 0x58, 
0x48, 0x50, 0xc2, 0x4c, 0x5f, 0x54, 0x5b, 0xe0, 0x59, 0x1b, 0x00, 0xc1, 
0x10, 0x3e, 0x42, 0x02, 0xb1, 0x5b, 0x48, 0x50, 0xc1, 0x4b, 0x5f, 0x49, 
0x59, 0xe1, 0x44, 0x17, 0x00, 0xdf, 0x15, 0x0f, 0x48, 0x06, 0xb1, 0x46, 
0x48, 0x50, 0xdc, 0x49, 0x5f, 0x4a, 0x5b, 0xe0, 0x47, 0x1b, 0x00, 0xdb, 
0x13, 0x3d, 0x58, 0x02, 0xb1, 0x41, 0x48, 0x50, 0xdb, 0x48, 0x5f, 0x4f, 
0x59, 0xe1, 0x42, 0x17, 0x00, 0xd9, 0x18, 0x0f, 0x4e, 0x06, 0xb1, 0x4c, 
0x48, 0x50, 0xd6, 0x46, 0x5f, 0x40, 0x5b, 0xe0, 0x4d, 0x1a, 0x00, 0xd5, 
0x17, 0x3b, 0x56, 0x02, 0xb1, 0x4f, 0x48, 0x50, 0xd5, 0x45, 0x5f, 0x45, 
0x59, 0xe1, 0x48, 0x17, 0x00, 0xd3, 0x1b, 0x0f, 0x44, 0x06, 0xb1, 0x4a, 
0x48, 0x50, 0xd0, 0x43, 0x5f, 0x46, 0x5b, 0xe0, 0x4b, 0x1a, 0x00, 0xaf, 
0x18, 0x39, 0x2c, 0x02, 0xb1, 0x35, 0x48, 0x50, 0xaf, 0x42, 0x5f, 0x3b, 
0x59, 0xe1, 0x36, 0x17, 0x00, 0xad, 0x1e, 0x0f, 0x3a, 0x06, 0xb1, 0x30, 
0x48, 0x50, 0xaa, 0x40, 0x5f, 0x3c, 0x64, 0xe0, 0x31, 0x1a, 0x00, 0xa9, 
0x2c, 0x38, 0x2a, 0x02, 0xb1, 0x33, 0x77, 0x50, 0xa9, 0x3f, 0x5f, 0x31, 
0x66, 0xe1, 0x3c, 0x17, 0x00, 0xa7, 0x5e, 0x0f, 0x30, 0x06, 0xb1, 0x3e, 
0x77, 0x50, 0xa4, 0x3d, 0x5f, 0x32, 0x64, 0xe0, 0x3f, 0x19, 0x00, 0xa3, 
0x28, 0x36, 0x20, 0x02, 0xb1, 0x39, 0x77, 0x50, 0xa3, 0x3c, 0x5f, 0x37, 
0x66, 0xe1, 0x3a, 0x17, 0x00, 0xa1, 0x5a, 0x1f, 0x29, 0x67, 0xa1};
+
+/* SPMA100B driver */
+/* XXX: WARNING! Just guessed! Don't rely on anything! */
+
+static void spma100_volume(uint8_t vol1, uint8_t vol2, uint8_t vol3, 
uint8_t vol4)
+{
+    /*
+     * Volume registers
+     * VDS also OK for VDD=2.8V and SPVDD=3.3V
+     */
+    spma100_regwrite(0xe3, vol1); // MIDI or Master
+    spma100_regwrite(0xe4, vol2); // PCM???
+    spma100_regwrite(0xe5, vol3); // PCM???
+    spma100_regwrite(0xe6, vol4); // opposite of 0xe3
+}
+
+static void spma100_standby(void)
+{
+    /* Volume: Mute */
+    spma100_volume(0, 0, 0, 0);
+
+    spma100_regwrite(0xe2, 0x00);
+    spma100_regwrite(0xe2, 0x01);
+    spma100_regwrite(0xe1, 0xff);
+    spma100_regwrite(0xe2, 0x00);
+    spma100_regwrite(0xe2, 0x01);
+    spma100_regwrite(0xf2, 0x04);
+}
+
+static void spma100_start(void)
+{
+    /* Toggle something. Power? */
+    spma100_regwrite(0xe2, 0x00);
+    spma100_regwrite(0xe2, 0x01);
+
+    spma100_regwrite(0xff, 0x07);
+    spma100_regwrite(0xe9, 0x00);
+    spma100_regwrite(0xf2, 0x00);
+
+    /* Volume: Mute */
+    spma100_volume(0, 0, 0, 0);
+
+    /* Power-up sequence/disable power-downs. Clicks otherwise */
+    spma100_regwrite(0xe1, 0x7e);
+    spma100_regwrite(0xe1, 0x1e);
+    spma100_regwrite(0xe1, 0x04);
+    spma100_regwrite(0xe1, 0x00);
+
+    /*
+     * PLL settings
+     * With OKI's table 8, this would be 13*34/10 = 44.2MHz
+     * -> 0.2% error for 44.1kHz * 1000 cycles/sample
+     * XXX: why twice!?
+     */
+    spma100_regwrite(0xe7, 0x22);
+    spma100_regwrite(0xe8, 0x09);
+    spma100_regwrite(0xf3, 0x22);
+    spma100_regwrite(0xf4, 0x09);
+
+    /*
+     * Would be transition from MUTE to 0dB for W56964
+     */
+    spma100_volume(0, 0, 0, 0);
+    spma100_volume(0x1f, 0x1f, 0x1f, 0x10);
+
+    spma100_regwrite(0xdb, 0x08);
+    spma100_regwrite(0xdc, 0x00);
+    spma100_regwrite(0xde, 0x08);
+    spma100_regwrite(0xdf, 0x00);
+}
+
+static void spma100_senddata(char *data, int length)
+{
+    int i;
+    for(i=0; i<length; i++)
+        spma100_regwrite(0xc5, data[i]);
+}
+
+static void spma100_play_midi(char *data, int length)
+{
+    spma100_regwrite(0xe0, 0x02);
+    spma100_regwrite(0xc8, 0x02);
+    spma100_regwrite(0xc8, 0x04);
+    spma100_regwrite(0xd6, 0x00);
+    spma100_regwrite(0xc4, 0x02);
+    spma100_regwrite(0xc6, 0xff);
+    spma100_regwrite(0xd6, 0x01);
+    spma100_senddata(data, length);
+    spma100_regwrite(0xd6, 0x00);
+    spma100_regwrite(0xc8, 0x01);
+}
+
+static void spma100_init(void)
+{
+    static const char setup_cmd[] = { /* removed because of unknown 
copyright */ };
+
+    int i;
+    /* XOR with flash for copyright issues */
+    for(i=0; i<449; i++)
+        midi1[i] = *(uint8_t *)(0x6f0694 + i) ^ midi1[i];
+    for(i=0; i<sizeof(midi2); i++)
+        midi2[i] = *(uint8_t *)(0x6f0884 + i) ^ midi2[i];
+
+    music_init();
+
+/* Not required to play music!
+    spma100_regwrite(0xd6, 0x01);
+    spma100_regwrite(0xc8, 0x06);
+    spma100_regwrite(0xd6, 0x00);
+
+    // XXX: timestamp advanced! What happened?
+    spma100_regwrite(0xc8, 0x02);
+    spma100_regwrite(0xc8, 0x04);
+    spma100_regwrite(0xd6, 0x00);
+    spma100_regwrite(0xc0, 0x02);
+    spma100_regwrite(0xc4, 0x00);
+    spma100_senddata(setup_cmd, sizeof(setup_cmd));
+
+    // XXX: timestamp advanced! What happened?
+    spma100_regwrite(0xc6, 0xff);
+    spma100_regwrite(0xc8, 0x01);
+
+    spma100_standby();
+*/
+}
+
+static void spma100_voodoo1(void)
+{
+    spma100_regwrite(0xda, 0x35);
+    spma100_regwrite(0xdb, 0x02);
+    spma100_regwrite(0xdd, 0x59);
+    spma100_regwrite(0xde, 0x02);
+}
+
+static void spma100_voodoo2(void)
+{
+    spma100_regwrite(0xd2, 0x00);
+    spma100_regwrite(0xd3, 0x0f);
+    spma100_regwrite(0xd4, 0x0f);
+    spma100_regwrite(0xd8, 0x00);
+}
+
+static void spma100_voodoo3(void)
+{
+    spma100_regwrite(0xc8, 0x06);
+    spma100_regwrite(0xd6, 0x00);
+    spma100_regwrite(0xc8, 0x06);
+    spma100_regwrite(0xd6, 0x00);
+    spma100_regwrite(0xd6, 0x00);
+    spma100_regwrite(0xd9, 0x0f);
+    spma100_regwrite(0xd9, 0x00);
+    spma100_regwrite(0xd3, 0x0f);
+    spma100_regwrite(0xd4, 0x0f);
+    spma100_regwrite(0xd8, 0x00);
+}
+
+static void spma100_clear_fifo()
+{
+    int i;
+    spma100_regwrite(0xd6, 0x01);
+    for(i=0; i<256; i++)
+        spma100_regwrite(0xc5, 0);
+}
+
+void spma100(const char *midi, int length)
+{
+    spma100_start();
+
+    /* XXX: Volume? */
+    //spma100_regwrite(0xe1, 0x00);
+
+    spma100_voodoo1();
+    spma100_voodoo2();
+    spma100_play_midi(midi, length);
+
+    //spma100_clear_fifo();
+    //spma100_voodoo3();
+    //spma100_standby();
+}
+
  int main(void)
  {
      board_init();
@@ -103,9 +407,30 @@ int main(void)
      sercomm_register_rx_cb(SC_DLCI_CONSOLE, console_rx_cb);
      sercomm_register_rx_cb(SC_DLCI_L1A_L23, l1a_l23_rx_cb);

-    /* beyond this point we only react to interrupts */
-    puts("entering interrupt loop\n");
+    /* MIDI player */
+    int i;
+    spma100_init();
+    puts("Play MIDI on keypress\n");
      while (1) {
+        switch(play_midi) {
+        case 1:
+            spma100(midi1, sizeof(midi1));
+            break;
+        case 2:
+            spma100(midi2, sizeof(midi2));
+            break;
+        case 9:
+            printf("GPIO status %04x\n", readw(0xfffe4800));
+            spma100(midi1, sizeof(midi1));
+            for(i=0; i<20; i++) {
+                spma100_deltaregs();
+                printf("GPIO status %04x\n", readw(0xfffe4800));
+                delay_ms(50);
+            }
+            break;
+        }
+        play_midi = -1;
+
          update_timers();
      }

@@ -132,6 +457,7 @@ void key_handler(enum key_codes code, enum 
key_states state)
      case KEY_7:
      case KEY_8:
      case KEY_9:
+        play_midi = code - KEY_0;
          sprintf(test, "%d", code - KEY_0);
          display_puts(test);
          break;
-- 
1.7.1






More information about the baseband-devel mailing list