OSDN Git Service

Updated board test codes on KOZOS.
authorShinichiro Nakamura <shinta.main.jp@gmail.com>
Wed, 6 Jun 2012 10:45:36 +0000 (19:45 +0900)
committerShinichiro Nakamura <shinta.main.jp@gmail.com>
Wed, 6 Jun 2012 10:45:36 +0000 (19:45 +0900)
17 files changed:
firm/09/os/Makefile
firm/09/os/audiodrv.c [new file with mode: 0644]
firm/09/os/audiodrv.h [new file with mode: 0644]
firm/09/os/clock.c
firm/09/os/command.c
firm/09/os/defines.h
firm/09/os/kozos.c
firm/09/os/kozos.h
firm/09/os/lcd.c
firm/09/os/lcddrv.c
firm/09/os/lcddrv.h
firm/09/os/leddrv.c
firm/09/os/main.c
firm/09/os/remocon.c
firm/09/os/rotenc.o [deleted file]
firm/09/os/vs1011e.c [new file with mode: 0644]
firm/09/os/vs1011e.h [new file with mode: 0644]

index 0e2afcf..c8780aa 100644 (file)
@@ -25,6 +25,8 @@ OBJS += lcd.o
 OBJS += remocon.o
 OBJS += mmc.o pff.o
 OBJS += lcddrv.o
+OBJS += vs1011e.o
+OBJS += audiodrv.o
 
 # sources of kozos
 OBJS += kozos.o syscall.o memory.o consdrv.o timerdrv.o command.o clock.o
diff --git a/firm/09/os/audiodrv.c b/firm/09/os/audiodrv.c
new file mode 100644 (file)
index 0000000..900d0e9
--- /dev/null
@@ -0,0 +1,47 @@
+#include "audiodrv.h"
+#include "vs1011e.h"
+#include "kozos.h"
+#include "consdrv.h"
+
+#define AUDIODRV_CMD_PULSE  'p'
+
+void audiodrv_pulse(void)
+{
+  char *p;
+  p = kz_kmalloc(1);
+  p[0] = AUDIODRV_CMD_PULSE;
+  kz_send(MSGBOX_ID_AUDIODRIVE, 1, p);
+}
+
+static int audiodrv_command(char *p)
+{
+  int cmd = p[0];
+  volatile int i;
+  switch (cmd) {
+  case AUDIODRV_CMD_PULSE:
+    vs1011e_sinetest_init();
+    for (i = 0; i < 2000; i++) { }
+    vs1011e_sinetest_fini();
+    break;
+  default:
+    break;
+  }
+  kz_kmfree(p);
+
+  return 0;
+}
+
+int audiodrv_main(int argc, char *argv[])
+{
+  int size;
+  char *p;
+
+  vs1011e_init();
+
+  while (1) {
+    kz_recv(MSGBOX_ID_AUDIODRIVE, &size, &p);
+    audiodrv_command(p);
+  }
+
+  return 0;
+}
diff --git a/firm/09/os/audiodrv.h b/firm/09/os/audiodrv.h
new file mode 100644 (file)
index 0000000..f637124
--- /dev/null
@@ -0,0 +1,7 @@
+#ifndef _AUDIODRV_H_INCLUDED_
+#define _AUDIODRV_H_INCLUDED_
+
+void audiodrv_pulse(void);
+
+#endif
+
index 19cf2df..1194970 100644 (file)
@@ -1,13 +1,11 @@
 #include "defines.h"
 #include "kozos.h"
-#include "consdrv.h"
 #include "timerdrv.h"
 #include "leddrv.h"
 #include "lcddrv.h"
 #include "lib.h"
 #include "sw.h"
 #include "re.h"
-#include "pff.h"
 
 int clock_main(int argc, char *argv[])
 {
@@ -16,9 +14,8 @@ int clock_main(int argc, char *argv[])
 
   lcddrv_clear();
   lcddrv_draw_logo(  0, 0, 2);
-  lcddrv_draw_logo( 50, 0, 1);
-  lcddrv_draw_logo(100, 0, 0);
   lcddrv_draw_box(0, 0, 121, 31, 1);
+  lcddrv_draw_text(40, 4, "KOZOS EXPBRD #00");
 
   uint16 prev = 0, curr = 0;
   while (1) {
@@ -38,6 +35,9 @@ int clock_main(int argc, char *argv[])
       }
       prev = curr;
     }
+
+    timerdrv_start(1);
+    timerdrv_wait();
   }
 
   return 0;
index 26cf876..05c3dfd 100644 (file)
@@ -1,7 +1,6 @@
 #include "defines.h"
 #include "kozos.h"
 #include "consdrv.h"
-#include "timerdrv.h"
 #include "leddrv.h"
 #include "lib.h"
 
index ec0255f..62cd20e 100644 (file)
@@ -23,6 +23,7 @@ typedef enum {
   MSGBOX_ID_TIMEXPIRE,
   MSGBOX_ID_LEDDRIVE,
   MSGBOX_ID_LCDDRIVE,
+  MSGBOX_ID_AUDIODRIVE,
   MSGBOX_ID_NUM
 } kz_msgbox_id_t;
 
index 8a25eba..901896b 100644 (file)
@@ -6,7 +6,7 @@
 #include "memory.h"
 #include "lib.h"
 
-#define THREAD_NUM 8
+#define THREAD_NUM 12
 #define PRIORITY_NUM 16
 #define THREAD_NAME_SIZE 15
 
index c8107b3..8c91939 100644 (file)
@@ -38,6 +38,7 @@ int consdrv_main(int argc, char *argv[]);
 int timerdrv_main(int argc, char *argv[]);
 int leddrv_main(int argc, char *argv[]);
 int lcddrv_main(int argc, char *argv[]);
+int audiodrv_main(int argc, char *argv[]);
 
 /* ¥æ¡¼¥¶¡¦¥¿¥¹¥¯ */
 int command_main(int argc, char *argv[]);
index 1023edc..1e597bc 100644 (file)
@@ -20,6 +20,9 @@ static const uint16 FONT_MAX_CODE = 0x7F;
 
 #define BIT_LCD_RES     (1 << 7)
 #define BIT_SDC_CS      (1 << 0)
+#define BIT_VSCCS       (1 << 2)
+#define BIT_VSDCS       (1 << 3)
+#define BIT_VSRST       (1 << 5)
 
 #define LCD1_CMD(VAL) \
   do { \
@@ -146,7 +149,7 @@ static const uint8 font5x7_data[] = {
 
 void lcd_init(void)
 {
-  *H8_3069F_P4DDR = BIT_LCD_RES | BIT_SDC_CS;
+  *H8_3069F_P4DDR = BIT_LCD_RES | BIT_SDC_CS | BIT_VSCCS | BIT_VSDCS | BIT_VSRST;
 
   /*
    * L->H : 68K mode.
index 2a4c76d..b629b70 100644 (file)
@@ -1,10 +1,12 @@
 #include "lcddrv.h"
 #include "lcd.h"
 #include "kozos.h"
+#include "lib.h"
 
 #define LCDDRV_CMD_LCD_CLEAR        'c' /* LCD\e$B$N>C5n\e(B */
 #define LCDDRV_CMD_LCD_DRAW_BOX     'b' /* BOX\e$BIA2h%3%^%s%I\e(B */
 #define LCDDRV_CMD_LCD_DRAW_LOGO    'l' /* LOGO\e$BIA2h%3%^%s%I\e(B */
+#define LCDDRV_CMD_LCD_DRAW_TEXT    't' /* TEXT\e$BIA2h%3%^%s%I\e(B */
 
 void lcddrv_clear(void)
 {
@@ -38,6 +40,20 @@ void lcddrv_draw_logo(int x, int y, int size)
   kz_send(MSGBOX_ID_LCDDRIVE, 4, p);
 }
 
+void lcddrv_draw_text(int x, int y, char *str)
+{
+  char *p;
+  int len;
+  len = strlen(str);
+  p = kz_kmalloc(3 + len + 1);
+  p[0] = LCDDRV_CMD_LCD_DRAW_TEXT;
+  p[1] = x;
+  p[2] = y;
+  memcpy(&p[3], str, len);
+  p[3 + len] = '\0';
+  kz_send(MSGBOX_ID_LCDDRIVE, 3 + len + 1, p);
+}
+
 static void draw_logo(const int ofsx, const int ofsy, const int size)
 {
   static const uint8 logo_40x32[] = {
@@ -171,6 +187,9 @@ static int lcddrv_command(char *p)
   case LCDDRV_CMD_LCD_DRAW_LOGO:
     draw_logo(p[1], p[2], p[3]);
     break;
+  case LCDDRV_CMD_LCD_DRAW_TEXT:
+    lcd_draw_string(p[1], p[2], &p[3], 0);
+    break;
   default:
     break;
   }
@@ -185,6 +204,7 @@ int lcddrv_main(int argc, char *argv[])
   char *p;
 
   lcd_init();
+
   while (1) {
     kz_recv(MSGBOX_ID_LCDDRIVE, &size, &p);
     lcddrv_command(p);
index 0fe8406..0a82feb 100644 (file)
@@ -4,5 +4,6 @@
 void lcddrv_clear(void);
 void lcddrv_draw_box(int x1, int y1, int x2, int y2, int on);
 void lcddrv_draw_logo(int x, int y, int size);
+void lcddrv_draw_text(int x, int y, char *str);
 
 #endif
index be3568e..de64f98 100644 (file)
@@ -53,6 +53,7 @@ int leddrv_main(int argc, char *argv[])
   char *p;
 
   led_init();
+
   while (1) {
     kz_recv(MSGBOX_ID_LEDDRIVE, &size, &p);
     leddrv_command(p);
index 395357e..b2096ac 100644 (file)
@@ -6,13 +6,14 @@
 /* ¥·¥¹¥Æ¥à¡¦¥¿¥¹¥¯¤È¥æ¡¼¥¶¡¦¥¿¥¹¥¯¤Îµ¯Æ° */
 static int start_threads(int argc, char *argv[])
 {
-  kz_run(consdrv_main,  "consdrv",  1, 0x200, 0, NULL);
-  kz_run(timerdrv_main, "timerdrv", 2, 0x100, 0, NULL);
-  kz_run(command_main,  "command",  5, 0x200, 0, NULL);
-  kz_run(leddrv_main,   "leddrv",   6, 0x100, 0, NULL);
-  kz_run(lcddrv_main,   "lcddrv",   7, 0x100, 0, NULL);
-  kz_run(clock_main,    "clock",    8, 0x100, 0, NULL);
-  kz_run(remocon_main,  "remocon",  9, 0x100, 0, NULL);
+  kz_run(consdrv_main,  "consdrv",   1, 0x200, 0, NULL);
+  kz_run(timerdrv_main, "timerdrv",  2, 0x200, 0, NULL);
+  kz_run(leddrv_main,   "leddrv",    7, 0x200, 0, NULL);
+  kz_run(command_main,  "command",   8, 0x200, 0, NULL);
+  kz_run(lcddrv_main,   "lcddrv",    9, 0x200, 0, NULL);
+  kz_run(audiodrv_main, "audiodrv", 10, 0x200, 0, NULL);
+  kz_run(clock_main,    "clock",    11, 0x200, 0, NULL);
+  kz_run(remocon_main,  "remocon",  12, 0x200, 0, NULL);
 
   kz_chpri(15); /* Í¥Àè½ç°Ì¤ò²¼¤²¤Æ¡¤¥¢¥¤¥É¥ë¥¹¥ì¥Ã¥É¤Ë°Ü¹Ô¤¹¤ë */
   INTR_ENABLE; /* ³ä¹þ¤ßÍ­¸ú¤Ë¤¹¤ë */
index 27b133d..c28dfe5 100644 (file)
@@ -5,6 +5,7 @@
 #include "led.h"
 #include "lib.h"
 #include "consdrv.h"
+#include "audiodrv.h"
 
 #define H8_3069F_ISCR       ((volatile uint8 *)0xFEE014)
 #define H8_3069F_IER        ((volatile uint8 *)0xFEE015)
@@ -93,20 +94,19 @@ int remocon_main(int argc, char *argv[])
 
   while (1) {
     if (tmrovf) {
-      if (bitcnt > 0) {
-        if (bitcnt == 32) {
-          int i;
-          for (i = 0; i < bitcnt; i++) {
-            if (data[i / 8] & (1 << (i % 8))) {
-              consdrv_write("1");
-            } else {
-              consdrv_write("0");
-            }
+      if (bitcnt == 32) {
+        int i;
+        for (i = 0; i < bitcnt; i++) {
+          if (data[i / 8] & (1 << (i % 8))) {
+            consdrv_write("1");
+          } else {
+            consdrv_write("0");
           }
-          consdrv_write("\n");
         }
-        bitcnt = 0;
+        consdrv_write("\n");
+        audiodrv_pulse();
       }
+      bitcnt = 0;
       tmrovf = 0;
       irs = WaitLeader;
     }
diff --git a/firm/09/os/rotenc.o b/firm/09/os/rotenc.o
deleted file mode 100644 (file)
index e5c833e..0000000
Binary files a/firm/09/os/rotenc.o and /dev/null differ
diff --git a/firm/09/os/vs1011e.c b/firm/09/os/vs1011e.c
new file mode 100644 (file)
index 0000000..ce1375c
--- /dev/null
@@ -0,0 +1,372 @@
+
+#include "vs1011e.h"
+
+#define VS1011E_OPCODE_READ    0x03
+#define VS1011E_OPCODE_WRITE   0x02
+
+#define REGADDR_MODE           0x00
+#define REGADDR_STATUS         0x01
+#define REGADDR_BASS           0x02
+#define REGADDR_CLOCKF         0x03
+#define REGADDR_DECODE_TIME    0x04
+#define REGADDR_AUDATA         0x05
+#define REGADDR_WRAM           0x06
+#define REGADDR_WRAMADDR       0x07
+#define REGADDR_HDAT0          0x08
+#define REGADDR_HDAT1          0x09
+#define REGADDR_AIADDR         0x0A
+#define REGADDR_VOL            0x0B
+#define REGADDR_AICTRL0                0x0C
+#define REGADDR_AICTRL1                0x0D
+#define REGADDR_AICTRL2                0x0E
+#define REGADDR_AICTRL3                0x0F
+
+#define SM_DIFF                (1 <<  0)
+#define SM_LAYER12     (1 <<  1)
+#define SM_RESET       (1 <<  2)
+#define SM_OUTOFWAV    (1 <<  3)
+#define SM_SETTOZERO1  (1 <<  4)
+#define SM_TESTS       (1 <<  5)
+#define SM_STREAM      (1 <<  6)
+#define SM_SETTOZERO2  (1 <<  7)
+#define SM_DACT                (1 <<  8)
+#define SM_SDIORD      (1 <<  9)
+#define SM_SDISHARE    (1 << 10)
+#define SM_SDINEW      (1 << 11)
+#define SM_SETTOZERO3  (1 << 12)
+#define SM_SETTOZERO4  (1 << 13)
+
+#define SCI_BASS_BITBASS_ST_AMP                12
+#define SCI_BASS_BITBASS_ST_FREQ       8
+#define SCI_BASS_BITBASS_SB_AMP                4
+#define SCI_BASS_BITBASS_SB_FREQ       0
+
+#define VS1011E_VSCTL1()    do { *H8_3069F_P4DR |=  P4DR_BIT_VSCCS; } while (0)
+#define VS1011E_VSCTL0()    do { *H8_3069F_P4DR &= ~P4DR_BIT_VSCCS; } while (0)
+
+#define VS1011E_VSDAT1()    do { *H8_3069F_P4DR |=  P4DR_BIT_VSDCS; } while (0)
+#define VS1011E_VSDAT0()    do { *H8_3069F_P4DR &= ~P4DR_BIT_VSDCS; } while (0)
+
+#define VS1011E_RESET1()    do { *H8_3069F_P4DR |=  P4DR_BIT_VSRST; } while (0)
+#define VS1011E_RESET0()    do { *H8_3069F_P4DR &= ~P4DR_BIT_VSRST; } while (0)
+
+#define VS1011E_CHK_DREQ()  (((*H8_3069F_P4DR) & P4DR_BIT_VSDREQ) ? 0 : 1)
+
+#define H8_3069F_P4DR   ((volatile uint8 *)0xFFFFD3)
+#define P4DR_BIT_VSCCS  (1 << 2)
+#define P4DR_BIT_VSDCS  (1 << 3)
+#define P4DR_BIT_VSDREQ (1 << 4)
+#define P4DR_BIT_VSRST  (1 << 5)
+
+#define H8_3069F_PBDR   ((volatile uint8 *)0xFFFFDA)
+#define PBDR_BIT_SCLK   (1 << 5)
+#define PBDR_BIT_MOSI   (1 << 6)
+#define PBDR_BIT_MISO   (1 << 7)
+
+#define CS_H()         do { *H8_3069F_P4DR |=  P4DR_BIT_CS; } while (0)      /* Set MMC CS "high" */
+#define CS_L()         do { *H8_3069F_P4DR &= ~P4DR_BIT_CS; } while (0)      /* Set MMC CS "low" */
+#define CK_H()         do { *H8_3069F_PBDR |=  PBDR_BIT_SCLK; } while (0)    /* Set MMC SCLK "high" */
+#define CK_L()         do { *H8_3069F_PBDR &= ~PBDR_BIT_SCLK; } while (0)    /* Set MMC SCLK "low" */
+#define DI_H()         do { *H8_3069F_PBDR |=  PBDR_BIT_MOSI; } while (0)    /* Set MMC DI "high" */
+#define DI_L()         do { *H8_3069F_PBDR &= ~PBDR_BIT_MOSI; } while (0)    /* Set MMC DI "low" */
+#define DO             ((*H8_3069F_PBDR & PBDR_BIT_MISO) ? 1 : 0)            /* Get MMC DO value (high:true, low:false) */
+
+static void _delay_ms(int ms)
+{
+    int i;
+    for (i = 0; i < ms * 10000; i++) {
+    }
+}
+
+static void _delay_us(int us)
+{
+    int i;
+    for (i = 0; i < us * 10; i++) {
+    }
+}
+
+static void SPI_TX(uint8 d)
+{
+    if (d & 0x80) DI_H(); else DI_L(); /* bit7 */
+    CK_H(); CK_L();
+    if (d & 0x40) DI_H(); else DI_L(); /* bit6 */
+    CK_H(); CK_L();
+    if (d & 0x20) DI_H(); else DI_L(); /* bit5 */
+    CK_H(); CK_L();
+    if (d & 0x10) DI_H(); else DI_L(); /* bit4 */
+    CK_H(); CK_L();
+    if (d & 0x08) DI_H(); else DI_L(); /* bit3 */
+    CK_H(); CK_L();
+    if (d & 0x04) DI_H(); else DI_L(); /* bit2 */
+    CK_H(); CK_L();
+    if (d & 0x02) DI_H(); else DI_L(); /* bit1 */
+    CK_H(); CK_L();
+    if (d & 0x01) DI_H(); else DI_L(); /* bit0 */
+    CK_H(); CK_L();
+}
+static uint8 SPI_RX()
+{
+    uint8 r;
+
+    DI_H();    /* Send 0xFF */
+
+    r = 0;   if (DO) r++;      /* bit7 */
+    CK_H(); CK_L();
+    r <<= 1; if (DO) r++;      /* bit6 */
+    CK_H(); CK_L();
+    r <<= 1; if (DO) r++;      /* bit5 */
+    CK_H(); CK_L();
+    r <<= 1; if (DO) r++;      /* bit4 */
+    CK_H(); CK_L();
+    r <<= 1; if (DO) r++;      /* bit3 */
+    CK_H(); CK_L();
+    r <<= 1; if (DO) r++;      /* bit2 */
+    CK_H(); CK_L();
+    r <<= 1; if (DO) r++;      /* bit1 */
+    CK_H(); CK_L();
+    r <<= 1; if (DO) r++;      /* bit0 */
+    CK_H(); CK_L();
+
+    return r;
+}
+
+static void vs1011e_read(uint8 addr, uint16 * stat);
+static void vs1011e_write(uint8 addr, uint16 stat);
+
+void vs1011e_init()
+{
+    vs1011e_reset_by_hardware();
+    vs1011e_reset_by_software();
+}
+
+void vs1011e_reset_by_hardware()
+{
+    // Assert vs1011 reset
+    VS1011E_RESET0();
+    // Delay 30ms
+    _delay_ms(30);
+    // Deassert CS by setting to high level
+    VS1011E_VSCTL1();
+    // Deassert DCS
+    VS1011E_VSDAT1();
+    // Release vs1011 reset
+    VS1011E_RESET1();
+    // Delay 10ms (2.5ms accordig to datasheet)
+    _delay_ms(10);
+    // Set volume to minimum
+    vs1011e_write(REGADDR_VOL, 0xFFFF);
+    // Set CLOCKF
+    vs1011e_write(REGADDR_CLOCKF, 0x9800);
+    // Delay 1ms
+    _delay_ms(1);
+    // Set slow sample rate for slow analog part startup
+    vs1011e_write(REGADDR_AUDATA, 10);
+    // Delay 100ms
+    _delay_ms(100);
+    // Switch on the analog parts
+    vs1011e_write(REGADDR_VOL, 0xFEFE);
+    vs1011e_write(REGADDR_AUDATA, 44101);
+    vs1011e_write(REGADDR_VOL, 0x0202);
+}
+
+void vs1011e_reset_by_software()
+{
+    uint16 i;
+
+    // Delay 200ms
+    _delay_ms(200);
+    // Set SW reset bit, set VS1011 native mode on SPI
+    vs1011e_write(REGADDR_MODE,
+            SM_LAYER12 | SM_RESET | SM_SDINEW | SM_TESTS);
+    // Delay 2us
+    _delay_us(2);
+    // Rewrite SCI_CLOCKF after soft reset
+    vs1011e_write(REGADDR_CLOCKF, 0x9800);
+    // Assert DCS
+    VS1011E_VSDAT0();
+    // Check the DREQ.
+    while (VS1011E_CHK_DREQ()) {
+    }
+    // Send 0x53 to SPI
+    SPI_TX(0x53);
+    // Send 1024 nulls
+    for (i = 0; i < 1024; i++) {
+        // Check the DREQ.
+        while (VS1011E_CHK_DREQ()) {
+        }
+        SPI_TX(0x00);
+    }
+    // Deassert DCS
+    VS1011E_VSDAT1();
+}
+
+void vs1011e_cancel_data()
+{
+    uint16 i;
+    while (VS1011E_CHK_DREQ()) {
+    }
+
+    VS1011E_VSDAT0();
+    for (i = 0; i < 2048; i++) {
+        while (VS1011E_CHK_DREQ()) {
+        }
+        SPI_TX(0x00);
+    }
+    VS1011E_VSDAT1();
+}
+
+void vs1011e_set_enhancer(uint8 st_amp, uint8 st_freq, uint8 sb_amp,
+        uint8 sb_freq)
+{
+    uint16 val =
+        (st_amp << SCI_BASS_BITBASS_ST_AMP) |
+        (st_freq << SCI_BASS_BITBASS_ST_FREQ) |
+        (sb_amp << SCI_BASS_BITBASS_SB_AMP) |
+        (sb_freq << SCI_BASS_BITBASS_SB_FREQ);
+    vs1011e_write(REGADDR_BASS, val);
+}
+
+void vs1011e_get_enhancer(uint8 * st_amp, uint8 * st_freq,
+        uint8 * sb_amp, uint8 * sb_freq)
+{
+    uint16 val;
+    vs1011e_read(REGADDR_BASS, &val);
+    *st_amp = (val >> SCI_BASS_BITBASS_ST_AMP) & 0x0F;
+    *st_freq = (val >> SCI_BASS_BITBASS_ST_FREQ) & 0x0F;
+    *sb_amp = (val >> SCI_BASS_BITBASS_SB_AMP) & 0x0F;
+    *sb_freq = (val >> SCI_BASS_BITBASS_SB_FREQ) & 0x0F;
+}
+
+void vs1011e_volume_read(uint8 * left, uint8 * right)
+{
+    uint16 val;
+    vs1011e_read(REGADDR_VOL, &val);
+    *left = val >> 8;
+    *right = val >> 0;
+}
+
+void vs1011e_volume_write(const uint8 left, const uint8 right)
+{
+    uint16 val =
+        (((uint16) left << 8) & 0xFF00) | (((uint16) right << 0) &
+            0x00FF);
+    vs1011e_write(REGADDR_VOL, val);
+}
+
+void vs1011e_play(int8(*func) (uint8 * buf, const uint16 len))
+{
+#define UNITBYTE    (128)
+    uint8 i;
+    uint8 buf[UNITBYTE];
+    while (1) {
+        /*
+         * Read the song data.
+         */
+        int8 len = func(buf, UNITBYTE);
+        if (len <= 0) {
+            return;
+        }
+        /*
+         * Send the data.
+         */
+        for (i = 0; i < UNITBYTE; i++) {
+            while (VS1011E_CHK_DREQ()) { }
+            VS1011E_VSDAT0();
+            SPI_TX(*(buf + i));
+            VS1011E_VSDAT1();
+        }
+    }
+}
+
+void vs1011e_decodetime_read(uint16 * sec)
+{
+    vs1011e_read(REGADDR_DECODE_TIME, sec);
+}
+
+void vs1011e_decodetime_write(const uint16 sec)
+{
+    vs1011e_write(REGADDR_DECODE_TIME, sec);
+}
+
+void vs1011e_sinetest_init()
+{
+    while (VS1011E_CHK_DREQ()) {
+    }
+
+    VS1011E_VSDAT0();
+    SPI_TX(0x53);
+    SPI_TX(0xEF);
+    SPI_TX(0x6E);
+    SPI_TX(0xF0);
+    SPI_TX(0x00);
+    SPI_TX(0x00);
+    SPI_TX(0x00);
+    SPI_TX(0x00);
+    VS1011E_VSDAT1();
+}
+
+void vs1011e_sinetest_fini()
+{
+    while (VS1011E_CHK_DREQ()) {
+    }
+
+    VS1011E_VSDAT0();
+    SPI_TX(0x45);
+    SPI_TX(0x78);
+    SPI_TX(0x69);
+    SPI_TX(0x74);
+    SPI_TX(0x00);
+    SPI_TX(0x00);
+    SPI_TX(0x00);
+    SPI_TX(0x00);
+    VS1011E_VSDAT1();
+
+    vs1011e_cancel_data();
+}
+
+void vs1011e_register_print()
+{
+#if 0
+    uint8 i;
+    uint16 val;
+    xprintf(PSTR("===================\r\n"));
+    for (i = 0; i <= 0x0F; i++) {
+        vs1011e_read(i, &val);
+        xprintf(PSTR("0x%02X: 0x%04X\r\n"), i, val);
+    }
+    xprintf(PSTR("===================\r\n"));
+#endif
+}
+
+static void vs1011e_read(uint8 addr, uint16 * stat)
+{
+    while (VS1011E_CHK_DREQ()) {
+    }
+
+    VS1011E_VSCTL0();
+
+    SPI_TX(VS1011E_OPCODE_READ);
+    SPI_TX(addr);
+
+    *stat = 0;
+    *stat |= SPI_RX() << 8;
+    *stat |= SPI_RX();
+
+    VS1011E_VSCTL1();
+}
+
+static void vs1011e_write(uint8 addr, uint16 stat)
+{
+    while (VS1011E_CHK_DREQ()) {
+    }
+
+    VS1011E_VSCTL0();
+
+    SPI_TX(VS1011E_OPCODE_WRITE);
+    SPI_TX(addr);
+
+    SPI_TX(stat >> 8);
+    SPI_TX(stat >> 0);
+
+    VS1011E_VSCTL1();
+}
diff --git a/firm/09/os/vs1011e.h b/firm/09/os/vs1011e.h
new file mode 100644 (file)
index 0000000..17138d9
--- /dev/null
@@ -0,0 +1,23 @@
+#ifndef VS1011_H
+#define VS1011_H
+
+#include "defines.h"
+
+void vs1011e_init(void);
+void vs1011e_reset_by_hardware(void);
+void vs1011e_reset_by_software(void);
+void vs1011e_cancel_data(void);
+void vs1011e_set_enhancer(uint8 st_amp, uint8 st_freq, uint8 sb_amp, uint8 sb_freq);
+void vs1011e_get_enhancer(uint8 * st_amp, uint8 * st_freq, uint8 * sb_amp, uint8 * sb_freq);
+void vs1011e_volume_read(uint8 * left, uint8 * right);
+void vs1011e_volume_write(const uint8 left, const uint8 right);
+void vs1011e_play(int8(*func) (uint8 * buf, const uint16 len));
+void vs1011e_decodetime_read(uint16 * sec);
+void vs1011e_decodetime_write(const uint16 sec);
+void vs1011e_register_print(void);
+
+void vs1011e_sinetest_init(void);
+void vs1011e_sinetest_fini(void);
+
+#endif
+