Main Page Data Structures File List Data Fields Globals Related Pages

# vs1001.cpp

Go to the documentation of this file.

    00001 /*  VLSI Logic VS1001 MPEG Decoder
    00002
    00003     14.09.2001: tk, the DMA is now disabled during SCI accesses.
    00004                     (see datasheet: After using the Serial Command
    00005                      Interface, it is not allowed to send SCI or SDI
    00006                      data for 5 microseconds)
    00007     30.08.2001: tk, small changes for final VS1001k revision.
    00008                     - GetBitrate() removed.
    00009                     - GetSamplerate() removed.
    00010                     These functions can be simulated by parsing
    00011                     the mp3 header anyways.
    00012     15.06.2001: tk, initial implementation.
    00013
    00014     Copyright (c)2000 by Thomas Kindler, thomas.kindler@gmx.de
    00015
    00016     This program is free software; you can redistribute it and/or
    00017     modify it under the terms of the GNU General Public License as
    00018     published by the Free Software Foundation; either version 2 of
    00019     the License, or (at your option) any later version. Read the
    00020     full License at http://www.gnu.org/copyleft for more details.
    00021 */
    00022
    00023 // include files -----
    00024 //
    00025 #include <stdlib.h>
    00026 #include <stdio.h>
    00027 #include "amd186.h"
    00028 #include "clib/hwapi.h"
    00029 #include "clib/rtos.h"
    00030 #include "misc.h"
    00031 #include "vs1001.h"
    00032
    00033 // Some VS1001 settings, so we can restore
    00034 // them after a reset.
    00035 //
    00036 static int  lastVolLeft, lastVolRight;
    00037 static long lastFrequency;
    00038 static bool lastBassBoost;
    00039
    00040 // old DMA terminal count handler
    00041 //
    00042 static void interrupt (*oldDmaHandler)(...);
    00043
    00044 // user defined callback function
    00045 //
    00046 static void (*callbackFunction)(void *);
    00047 static void  *callbackParam;
    00048
    00049
    00050 static void SCI_Write(unsigned data)
    00051 {
    00052   for (int i=15; i>=0; i--) {
    00053     if (data & 1<<i)
    00054       AMD_PioHigh(AMD_PIOPIN[SCI_SIPIO]);
    00055     else
    00056       AMD_PioLow(AMD_PIOPIN[SCI_SIPIO]);
    00057     AMD_PioHigh(AMD_PIOPIN[SCI_SCLKPIO]);
    00058     AMD_PioLow(AMD_PIOPIN[SCI_SCLKPIO]);
    00059   }
    00060 }
    00061
    00062
    00063 static unsigned SCI_Read()
    00064 {
    00065   unsigned data = 0;
    00066   for (int i=15; i>=0; i--) {
    00067     AMD_PioHigh(AMD_PIOPIN[SCI_SCLKPIO]);
    00068     if (AMD_GetPio(AMD_PIOPIN[SCI_SOPIO]))
    00069       data |= 1<<i;
    00070     AMD_PioLow(AMD_PIOPIN[SCI_SCLKPIO]);
    00071   }
    00072   return data;
    00073 }
    00074
    00075
    00076 static unsigned SCI_ReadReg(int address)
    00077 {
    00078   AMD_EnableDrq(SDI_DMACHANNEL, 0);
    00079   AMD_PioLow(AMD_PIOPIN[SCI_SCLKPIO]);
    00080   AMD_PioLow(AMD_PIOPIN[SCI_XCSPIO]);
    00081   SCI_Write( 0x0300 | address );
    00082   unsigned data = SCI_Read();
    00083   AMD_PioHigh(AMD_PIOPIN[SCI_XCSPIO]);
    00084   usleep(5);
    00085   AMD_EnableDrq(SDI_DMACHANNEL, 1);
    00086   return data;
    00087 }
    00088
    00089
    00090 static void SCI_WriteReg(int address, unsigned data)
    00091 {
    00092   AMD_EnableDrq(SDI_DMACHANNEL, 0);
    00093   AMD_PioLow(AMD_PIOPIN[SCI_SCLKPIO]);
    00094   AMD_PioLow(AMD_PIOPIN[SCI_XCSPIO]);
    00095   SCI_Write( 0x0200 | address );
    00096   SCI_Write( data );
    00097   AMD_PioHigh(AMD_PIOPIN[SCI_XCSPIO]);
    00098   usleep(5);
    00099   AMD_EnableDrq(SDI_DMACHANNEL, 1);
    00100 }
    00101
    00102
    00109 static void interrupt DmaHandler(...)
    00110 {
    00111   if (callbackFunction)
    00112     callbackFunction(callbackParam);
    00113   oldDmaHandler();
    00114 }
    00115
    00116
    00122 bool VS_IsPlaying()
    00123 {
    00124   DmaInfo  dma;
    00125
    00126   // check DMA status
    00127   //
    00128   AMD_GetDmaInfo(SDI_DMACHANNEL, &dma);
    00129   return dma.control & DCON_ST ? true : false;
    00130 }
    00131
    00132
    00149 void VS_PlayMpegAsync( char *data, unsigned len,
    00150                        void (*function)(void *),
    00151                        void  *param )
    00152 {
    00153   // set up DMA channel
    00154   //
    00155   DmaInfo  dma;
    00156   dma.control = DCON_DSYNC | DCON_SMIO | DCON_SINC | DCON_TC | DCON_INT;
    00157   dma.length  = len;
    00158   dma.srcMem  = data;
    00159   dma.dstPort = SDI_DATAREG;
    00160
    00161   callbackFunction = function;
    00162   callbackParam    = param;
    00163
    00164   // enable DMA request pin
    00165   //
    00166   AMD_StartDma(SDI_DMACHANNEL, &dma);
    00167   AMD_EnableDrq(SDI_DMACHANNEL, true);
    00168 }
    00169
    00170
    00184 int VS_PlayMpegSync(char *data, unsigned len)
    00185 {
    00186   VS_PlayMpegAsync(data, len, NULL, 0);
    00187   while (VS_IsPlaying());
    00188
    00189   return VS_OK;
    00190 }
    00191
    00192
    00200 void SDI_WriteZeros(unsigned length)
    00201 {
    00202   char zeros[256] = {0};
    00203   int  block;
    00204
    00205   while (length > 0) {
    00206     block = min(length, sizeof(zeros));
    00207     VS_PlayMpegSync(zeros, block);
    00208     length -= block;;
    00209   }
    00210 }
    00211
    00212
    00217 void VS_Stop()
    00218 {
    00219   // stop DMA channel
    00220   AMD_StopDma(SDI_DMACHANNEL);
    00221 }
    00222
    00223
    00234 void VS_SetVolume(int left, int right)
    00235 {
    00236   lastVolLeft = left;
    00237   lastVolRight = right;
    00238   SCI_WriteReg(SCI_VOL, ((255-left)<<8) | (255-right));
    00239 }
    00240
    00241
    00250 void VS_GetMPEGHeader(unsigned long *header)
    00251 {
    00252   ((unsigned *)header)[0] = SCI_ReadReg(SCI_HDAT0);
    00253   ((unsigned *)header)[1] = SCI_ReadReg(SCI_HDAT1);
    00254 }
    00255
    00256
    00269 void VS_SetClockFreq(long frequency)
    00270 {
    00271   lastFrequency = frequency;
    00272   if (frequency < 18432000)
    00273     SCI_WriteReg(SCI_CLOCKF, (frequency/2000) | 0x8000);
    00274   else
    00275     SCI_WriteReg(SCI_CLOCKF, (frequency/2000));
    00276 }
    00277
    00278
    00284 void VS_SetBassBoost(bool onoff)
    00285 {
    00286   lastBassBoost = onoff;
    00287   if (onoff)
    00288     SCI_WriteReg(SCI_MODE, SCI_ReadReg(SCI_MODE) | SM_BASS);
    00289   else
    00290     SCI_WriteReg(SCI_MODE, SCI_ReadReg(SCI_MODE) & ~SM_BASS);
    00291 }
    00292
    00293
    00299 void VS_SDITest()
    00300 {
    00301   char beepOn[] = { 0x53, 0xef, 0x6e, 0x3e, 0, 0, 0, 0 };
    00302   char beepOff[]= { 0x45, 0x78, 0x69, 0x74, 0, 0, 0, 0 };
    00303
    00304   printf("Testing SDI interface");
    00305   for (int i=0; i<25; i++) {
    00306     VS_PlayMpegSync(beepOn, sizeof(beepOn));
    00307     RTX_Sleep_Time(100);
    00308     VS_PlayMpegSync(beepOff, sizeof(beepOff));
    00309     RTX_Sleep_Time(100);
    00310     printf(".");
    00311   }
    00312   printf(" ok.\n");
    00313 }
    00314
    00315
    00320 void VS_SCITest()
    00321 {
    00322   printf("Testing SCI interface");
    00323   for (int i=0; i<25; i++) {
    00324     VS_SetVolume(0, 0);
    00325     RTX_Sleep_Time(100);
    00326     VS_SetVolume(255,255);
    00327     RTX_Sleep_Time(100);
    00328     printf(".");
    00329   }
    00330   printf(" ok.\n");
    00331 }
    00332
    00333
    00338 void VS_Dump()
    00339 {
    00340   printf("VS1001 SCI registers ---\n");
    00341   printf("  MODE    = %04x\n", SCI_ReadReg(SCI_MODE));
    00342   printf("  STATUS  = %04x\n", SCI_ReadReg(SCI_STATUS));
    00343   printf("  CLOCKF  = %04x\n", SCI_ReadReg(SCI_CLOCKF));
    00344   printf("  DECTIME = %04x\n", SCI_ReadReg(SCI_DECTIME));
    00345   printf("  AUDATA  = %04x\n", SCI_ReadReg(SCI_AUDATA));
    00346   printf("  HDAT0   = %04x\n", SCI_ReadReg(SCI_HDAT0));
    00347   printf("  HDAT1   = %04x\n", SCI_ReadReg(SCI_HDAT1));
    00348   printf("  A1ADDR  = %04x\n", SCI_ReadReg(SCI_A1ADDR));
    00349   printf("  VOL     = %04x\n", SCI_ReadReg(SCI_VOL));
    00350   printf("  A1CTRL0 = %04x\n", SCI_ReadReg(SCI_A1CTRL0));
    00351   printf("  A1CTRL1 = %04x\n", SCI_ReadReg(SCI_A1CTRL1));
    00352   printf("  A1CTRL2 = %04x\n", SCI_ReadReg(SCI_A1CTRL2));
    00353 }
    00354
    00355
    00362 void VS_Reset()
    00363 {
    00364   AMD_EnableDrq(SDI_DMACHANNEL, 0);
    00365   SCI_WriteReg(SCI_MODE, SM_RESET);
    00366   usleep(500);
    00367   if (SCI_ReadReg(SCI_MODE) == SM_RESET)
    00368     printf( "OMFG: VS1001 Software reset failed.\n"
    00369             "  Why don't they implement a watchdog timer,\n"
    00370             "  or a reset bit that *works*?! Go and write\n"
    00371             "  some mail to info@vlsi.fi :)\n"
    00372           );
    00373   VS_SetClockFreq(lastFrequency);
    00374   VS_SetVolume(lastVolLeft, lastVolRight);
    00375   VS_SetBassBoost(lastBassBoost);
    00376   SDI_WriteZeros(2);
    00377 }
    00378
    00379
    00384 void VS_Init()
    00385 {
    00386   printf("SCI_Init(): initializing VS1001..\n");
    00387
    00388   // enable SCI PIOs
    00389   //
    00390   pfe_enable_bus(0xff, true);
    00391   pfe_enable_pcs(SDI_DATAREG >> 8);
    00392
    00393   pfe_enable_pio(SCI_XCSPIO,  PIO_O1  );
    00394   pfe_enable_pio(SCI_SCLKPIO, PIO_O0  );
    00395   pfe_enable_pio(SCI_SIPIO,   PIO_O0  );
    00396   pfe_enable_pio(SCI_SOPIO,   PIO_IPU );
    00397
    00398   // install DMA terminal count interrupt
    00399   //
    00400   oldDmaHandler = getvect(10);
    00401   setvect(10, DmaHandler);
    00402
    00403   // initialize settings, and reset the VS1001
    00404   //
    00405   lastVolLeft   = 255;
    00406   lastVolRight  = 255;
    00407   lastFrequency = VS_CLOCK;
    00408   lastBassBoost = true;
    00409   VS_Reset();
    00410 }
    00411
    00412
    00417 void VS_Done()
    00418 {
    00419   // disable DMA channel
    00420   //
    00421   VS_Stop();
    00422
    00423   if (oldDmaHandler)
    00424     setvect(10, oldDmaHandler);
    00425 }