/**************************************************************************
 *                                 i2c.c                                  *
 *                                                                        *
 *                   Copyright (c) 1999   Jake Janovetz                   *
 **************************************************************************
 * This source code is property of Jake Janovetz.  No permission is given *
 * to use or reuse this code in any other form.                           *
 * Description:                                                           *
 *                                                                        *
 * The public routines contained in this file are:                        *
 *    configure_ports -- Configures the ports on the CPU.                 *
 *    STA_Reset -- Performs a hard reset of the MP3 decoder.              *
 *    STA_StartDecoder -- Soft resets decoder and unmutes the DAC.        *
 *    STA_StopDecoder -- Stops the decoder and mutes the DAC.             *
 *    STA_PauseDecoder -- Pauses the decoder.                             *
 *    STA_ResumeDecoder -- Unpauses the decoder.                          *
 *    STA_QueryMP3Header                                                  *
 *    STA_QueryFrameCount                                                 *
 *    STA_QueryAverageBitrate                                             *
 *    STA_SetVolumeMatrix                                                 *
 *    STA_SetBassFrequency                                                *
 *    STA_SetBassEnhance                                                  *
 *    STA_SetTrebleFrequency                                              *
 *    STA_SetTrebleEnhance                                                *
 *    STA_GetVolume                                                       *
 *    STA_GetBassEnhance                                                  *
 *    STA_GetTrebleEnhance                                                *
 *    STA_VolumeChange                                                    *
 *    STA_BassChange                                                      *
 *    STA_TrebleChange                                                    *
 *    STA_MuteToggle                                                      *
 *                                                                        *
 *                                                                        *
 * The private routines contained in this file are:                       *
 *    I2C_SendByte                                                        *
 *    I2C_ReadByte                                                        *
 *    I2C_Start                                                           *
 *    I2C_Stop                                                            *
 *    I2C_NoACK                                                           *
 *    DAC_Mute                                                            *
 *    DAC_UnMute                                                          *
 *    STA_ReadRegister                                                    *
 *    STA_WriteRegister                                                   *
 *    STA_DownloadUpdate -- Download firmware updates.                    *
 *    STA_ReadToneControls -- Reads all tone controls from the decoder.   *
 *    STA_WriteToneControls -- Writes all tone controls to the decoder.   *
 *                                                                        *
 *                                                                        *
 **************************************************************************
 * Change History:                                                        *
 *  03/01/1999 - Creation (JWJ)                                           *
 *************************************************************************/


#include <rtems.h>
#include <syslog.h>
#include "m68360.h"
#include "monitor.h"
#include "i2c.h"
#include "mp3.h"


#define I2C_DATA        (1<<0)
#define I2C_CLK         (1<<1)
#define MPEG_RESET      (1<<2)
#define DAC_MUTE_L      (1<<3)
#define DAC_MUTE_R      (1<<4)
#define DAC_AUTOMUTE    (1<<5)
#define VOLUME_SDATAI   (1<<6)
#define VOLUME_SCLK     (1<<7)
#define VOLUME_MUTE     (1<<8)

#define MPEG_DATA       (1<<3)
#define MPEG_CLK        (1<<10)
#define MPEG_ENABLE     (1<<1)
#define MPEG_DEMAND     (1<<6)


#define I2C_DELAY      16


/**************************************************************************
 * STA013
 * Register Defines
 *************************************************************************/
#define STA_REG_VERSION                0x00
#define STA_REG_IDENT                  0x01
#define STA_REG_PLLCTL_1               0x05
#define STA_REG_PLLCTL_2               0x06
#define STA_REG_PLLCTL_3               0x07
#define STA_REG_REQ_POL                0x0c
#define STA_REG_SCLK_POL               0x0d
#define STA_REG_ERROR_CODE             0x0f
#define STA_REG_SOFT_RESET             0x10
#define STA_REG_PLAY                   0x13
#define STA_REG_MUTE                   0x14
#define STA_REG_CMD_INTERRUPT          0x16
#define STA_REG_DATA_REQ_ENABLE        0x18
#define STA_REG_SYNCSTATUS             0x40
#define STA_REG_ANCCOUNT_L             0x41
#define STA_REG_ANCCOUNT_H             0x42
#define STA_REG_HEAD_H                 0x43
#define STA_REG_HEAD_M                 0x44
#define STA_REG_HEAD_L                 0x45
#define STA_REG_DLA                    0x46
#define STA_REG_DLB                    0x47
#define STA_REG_DRA                    0x48
#define STA_REG_DRB                    0x49
#define STA_REG_MFSDF_441              0x50
#define STA_REG_PLLFRAC_441_L          0x51
#define STA_REG_PLLFRAC_441_H          0x52
#define STA_REG_PCMDIVIDER             0x54
#define STA_REG_PCMCONF                0x55
#define STA_REG_PCMCROSS               0x56
#define STA_REG_ANC_DATA_1             0x59
#define STA_REG_ANC_DATA_2             0x5a
#define STA_REG_ANC_DATA_3             0x5b
#define STA_REG_ANC_DATA_4             0x5c
#define STA_REG_ANC_DATA_5             0x5d
#define STA_REG_MFSDF                  0x61
#define STA_REG_DAC_CLK_MODE           0x63
#define STA_REG_PLLFRAC_L              0x64
#define STA_REG_PLLFRAC_H              0x65
#define STA_REG_FRAME_CNT_L            0x67
#define STA_REG_FRAME_CNT_M            0x68
#define STA_REG_FRAME_CNT_H            0x69
#define STA_REG_AVERAGE_BITRATE        0x6a
#define STA_REG_SOFTVERSION            0x71
#define STA_REG_RUN                    0x72
#define STA_REG_TREBLE_FREQUENCY_LOW   0x77
#define STA_REG_TREBLE_FREQUENCY_HIGH  0x78
#define STA_REG_BASS_FREQUENCY_LOW     0x79
#define STA_REG_BASS_FREQUENCY_HIGH    0x7a
#define STA_REG_TREBLE_ENHANCE         0x7b
#define STA_REG_BASS_ENHANCE           0x7c
#define STA_REG_TONE_ATTEN             0x7d



#define MIN(a,b)        ((a<b)?(a):(b))
#define MAX(a,b)        ((a>b)?(a):(b))


#define MIN_VOLUME_ATTENUATION     0
#define MAX_VOLUME_ATTENUATION     96
#define MIN_TONE_ATTENUATION       0
#define MAX_TONE_ATTENUATION       96
#define MIN_BASS_FREQUENCY         100
#define MAX_BASS_FREQUENCY         500
#define MIN_TREBLE_FREQUENCY       1000
#define MAX_TREBLE_FREQUENCY       5000
#define SOFTMUTE_VOLUME_CHANGE     20

/**************************************************************************
 * Prototypes
 *************************************************************************/
static int STA_ReadToneControls();
static int STA_WriteToneControls();

static struct MP3_ToneControls  tone_controls_g;
static rtems_id                 sta_semid_g;

static int MP3_Bitrates[] =
   { 0,  8, 16, 24, 32, 40, 48, 56,  64,  80,  96, 112, 128, 144, 160, 0,
     0, 32, 40, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320, 0};
static int MP3_SamplingFrequencies[] =
   { 11, 12,  8,  0,      /* MPEG 2.5 rates */
      0,  0,  0,  0,      /* reserved rates */
     22, 24, 16,  0,      /* MPEG 2   rates */
     44, 48, 32,  0       /* MPEG 1   rates */
   };
     

void
configure_ports()
{
   rtems_status_code   sc;


   m360.paodr &= ~(MPEG_DATA | MPEG_CLK);  /* active outputs */
   m360.padir |=   MPEG_DATA | MPEG_CLK;     /* outputs */
   m360.papar &= ~(MPEG_DATA | MPEG_CLK);  /* Assign as GPIO */
   m360.padat &= ~(MPEG_DATA | MPEG_CLK);

   m360.pbodr &= ~0x000001ff;   /* Configure Port B open drain register */
   m360.pbdir |=  0x000001ff;   /* Configure Port B as output */
   m360.pbpar &= ~0x000001ff;   /* Configure Port B as GPIO */
   m360.pbdat  =  0x000001ff;   /* Default outputs */

   m360.pcpar &= ~0x42;         /* Pins 1,6 are GPIO */
   m360.pcdir |=  0x02;         /* Pin 1 (MPEG_ENABLE) is an output */
   m360.pcdir &= ~0x40;         /* Pin 6 (MPEG_DEMAND) is an input */
   m360.pcso  &= ~0x42;         /* Pins 1,6 are GPIO */
   m360.pcdat &= ~0x02;         /* Clear MPEG_ENABLE */
   m360.pcint &= ~(MPEG_DEMAND);   /* Interrupt on any change to DEMAND */

   m360.pbdat &= ~DAC_AUTOMUTE;   /* Turn on DAC automute */


   /***********************************************************************
    * Create a port semaphore to regulate usage of the STA013 I2C bus.
    **********************************************************************/
   sc = rtems_semaphore_create(rtems_build_name('P', 'R', 'T', 'S'),
                               1,
                               RTEMS_FIFO | RTEMS_BINARY_SEMAPHORE |
                               RTEMS_NO_INHERIT_PRIORITY | RTEMS_LOCAL |
                               RTEMS_NO_PRIORITY_CEILING, 0,
                               &sta_semid_g);
   if (sc != RTEMS_SUCCESSFUL)
      syslog(LOG_ERR, "mp3d: Could not create port semaphore.");
}


/*
 * I2C bus protocol:
 *
 * Data changes (SDA) occur ONLY when SCL is low.  A transition while
 *    SCL is high is defined as either STOP or START.
 * START is defined as a high-low transition of SDA while SCL is high.
 * STOP is defined as a low-high transition of SDA while SCL is high.
 *
 * Data is shifted out MSB first.
 *
 * Acknowledge: the bus master releases the bus after sending 8-bits
 *   of data.  During the 9th clock pulse, the receiver pulls the
 *   SDA bus low to acknowledge.
 */
static int
I2C_SendByte(unsigned char b)
{
   int i, j;
   unsigned long ack;
   rtems_interrupt_level  isr_level;


   rtems_interrupt_disable(isr_level);
   for (i=0; i<8; i++)
   {
      if (b & 0x80)
         m360.pbdat |= I2C_DATA;
      else
         m360.pbdat &= ~I2C_DATA;

      for (j=0; j<I2C_DELAY; j++);
      m360.pbdat |= I2C_CLK;
      for (j=0; j<I2C_DELAY; j++);
      m360.pbdat &= ~I2C_CLK;
      b <<= 1;
   }

   /* Receive acknowledgement */
   m360.pbdir &= ~I2C_DATA;  /* Set SDA to be input to MCU for ACK. */

   for (j=0; j<I2C_DELAY; j++);
   ack = m360.pbdat & I2C_DATA;
   m360.pbdat |= I2C_CLK;
   for (j=0; j<I2C_DELAY; j++);
   m360.pbdat &= ~I2C_CLK;

   m360.pbdir |= I2C_DATA;   /* Set SDA to be output. */
   rtems_interrupt_enable(isr_level);

   return(ack!=0);
}


static unsigned char
I2C_ReadByte()
{
   int           i, j;
   unsigned char b;
   rtems_interrupt_level  isr_level;


   rtems_interrupt_disable(isr_level);


   b = 0x00;
   m360.pbdir &= ~I2C_DATA;  /* Set SDA to be input. */
   for (j=0; j<I2C_DELAY; j++);
   for (i=0; i<8; i++)
   {
      if (m360.pbdat & I2C_DATA)
         b |= 0x01;

      if (i < 7)
         b <<= 1;

      m360.pbdat |= I2C_CLK;
      for (j=0; j<I2C_DELAY; j++);
      m360.pbdat &= ~I2C_CLK;
      for (j=0; j<I2C_DELAY; j++);
   }

   /* Receive acknowledgement */
   m360.pbdat |= I2C_CLK;
   for (j=0; j<I2C_DELAY; j++);
   m360.pbdat &= ~I2C_CLK;
   for (j=0; j<I2C_DELAY; j++);

   m360.pbdir |= I2C_DATA;   /* Set SDA to be output. */
   rtems_interrupt_enable(isr_level);

   return(b);
}


static void
I2C_Start()
{
   int i;
   rtems_interrupt_level  isr_level;


   rtems_interrupt_disable(isr_level);
   /* Start */
   m360.pbdat |= I2C_DATA;
   m360.pbdat |= I2C_CLK;
   for (i=0; i<I2C_DELAY; i++);
   m360.pbdat &= ~I2C_DATA;
   for (i=0; i<I2C_DELAY; i++);
   m360.pbdat &= ~I2C_CLK;
   for (i=0; i<I2C_DELAY; i++);
   rtems_interrupt_enable(isr_level);
}


static void
I2C_Stop()
{
   int i;
   rtems_interrupt_level  isr_level;


   rtems_interrupt_disable(isr_level);
   /* Stop */
   m360.pbdat &= ~I2C_DATA;
   for (i=0; i<I2C_DELAY; i++);
   m360.pbdat |= I2C_CLK;
   for (i=0; i<I2C_DELAY; i++);
   m360.pbdat |= I2C_DATA;
   for (i=0; i<I2C_DELAY; i++);
   m360.pbdat &= ~I2C_CLK;
   rtems_interrupt_enable(isr_level);
}


static void
I2C_NoACK()
{
   int j;

   m360.pbdat |= I2C_CLK;
   for (j=0; j<I2C_DELAY; j++);
   m360.pbdat &= ~I2C_CLK;
   for (j=0; j<I2C_DELAY; j++);
}



/**************************************************************************
 **************************************************************************
 ** DAC Section
 **************************************************************************
 *************************************************************************/
static void
DAC_Mute()
{
   m360.pbdat &= ~(DAC_MUTE_L | DAC_MUTE_R);
}


static void
DAC_UnMute()
{
   m360.pbdat |= DAC_MUTE_L | DAC_MUTE_R;
}


/**************************************************************************
 **************************************************************************
 ** STA013 Section
 **************************************************************************
 *************************************************************************/
static unsigned char STA013_UpdateData[] = 
   {
0x3a, 0x01, 0x2a, 0x04, 0x28, 0x00, 0x29, 0x00, 0x20, 0x00, 
0x21, 0x00, 0x22, 0x00, 0x23, 0x00, 0x24, 0x00, 0x25, 0x00, 
0x26, 0x00, 0x27, 0x00, 0x28, 0x01, 0x28, 0x02, 0x21, 0x8f, 
0x28, 0x03, 0x21, 0x00, 0x28, 0x04, 0x28, 0x05, 0x28, 0x06, 
0x28, 0x07, 0x28, 0x08, 0x28, 0x09, 0x28, 0x0a, 0x28, 0x0b, 
0x28, 0x0c, 0x20, 0x80, 0x21, 0x90, 0x28, 0x0d, 0x20, 0x00, 
0x21, 0x00, 0x28, 0x0e, 0x20, 0x81, 0x21, 0x91, 0x28, 0x0f, 
0x20, 0x00, 0x21, 0x92, 0x28, 0x10, 0x21, 0x00, 0x28, 0x11, 
0x21, 0x93, 0x28, 0x12, 0x21, 0x00, 0x28, 0x13, 0x28, 0x14, 
0x28, 0x15, 0x20, 0x82, 0x28, 0x16, 0x20, 0x00, 0x28, 0x17, 
0x28, 0x18, 0x28, 0x19, 0x21, 0x94, 0x28, 0x1a, 0x21, 0x95, 
0x28, 0x1b, 0x21, 0x96, 0x28, 0x1c, 0x21, 0x00, 0x28, 0x1d, 
0x20, 0x83, 0x28, 0x1e, 0x20, 0x00, 0x28, 0x1f, 0x21, 0x97, 
0x28, 0x20, 0x21, 0x00, 0x28, 0x21, 0x28, 0x22, 0x28, 0x23, 
0x28, 0x24, 0x28, 0x25, 0x28, 0x26, 0x28, 0x27, 0x28, 0x28, 
0x28, 0x29, 0x28, 0x2a, 0x20, 0x84, 0x28, 0x2b, 0x20, 0x00, 
0x28, 0x2c, 0x28, 0x2d, 0x28, 0x2e, 0x28, 0x2f, 0x28, 0x30, 
0x28, 0x31, 0x28, 0x32, 0x20, 0x85, 0x28, 0x33, 0x20, 0x00, 
0x28, 0x34, 0x28, 0x35, 0x28, 0x36, 0x28, 0x37, 0x21, 0x98, 
0x28, 0x38, 0x21, 0x00, 0x28, 0x39, 0x28, 0x3a, 0x28, 0x3b, 
0x28, 0x3c, 0x28, 0x3d, 0x28, 0x3e, 0x28, 0x3f, 0x28, 0x40, 
0x28, 0x41, 0x28, 0x42, 0x28, 0x43, 0x28, 0x44, 0x28, 0x45, 
0x28, 0x46, 0x28, 0x47, 0x28, 0x48, 0x28, 0x49, 0x28, 0x4a, 
0x28, 0x4b, 0x28, 0x4c, 0x28, 0x4d, 0x28, 0x4e, 0x28, 0x4f, 
0x28, 0x50, 0x28, 0x51, 0x28, 0x52, 0x28, 0x53, 0x28, 0x54, 
0x28, 0x55, 0x28, 0x56, 0x28, 0x57, 0x28, 0x58, 0x28, 0x59, 
0x28, 0x5a, 0x28, 0x5b, 0x28, 0x5c, 0x28, 0x5d, 0x28, 0x5e, 
0x28, 0x5f, 0x28, 0x60, 0x28, 0x61, 0x28, 0x62, 0x21, 0x99, 
0x28, 0x63, 0x21, 0x00, 0x28, 0x64, 0x28, 0x65, 0x28, 0x66, 
0x28, 0x67, 0x28, 0x68, 0x28, 0x69, 0x28, 0x6a, 0x28, 0x6b, 
0x28, 0x6c, 0x28, 0x6d, 0x28, 0x6e, 0x28, 0x6f, 0x28, 0x70, 
0x28, 0x71, 0x28, 0x72, 0x28, 0x73, 0x28, 0x74, 0x28, 0x75, 
0x28, 0x76, 0x28, 0x77, 0x28, 0x78, 0x28, 0x79, 0x28, 0x7a, 
0x28, 0x7b, 0x28, 0x7c, 0x28, 0x7d, 0x28, 0x7e, 0x28, 0x7f, 
0x28, 0x80, 0x28, 0x81, 0x28, 0x82, 0x28, 0x83, 0x28, 0x84, 
0x28, 0x85, 0x28, 0x86, 0x28, 0x87, 0x28, 0x88, 0x28, 0x89, 
0x28, 0x8a, 0x28, 0x8b, 0x28, 0x8c, 0x28, 0x8d, 0x28, 0x8e, 
0x28, 0x8f, 0x28, 0x90, 0x28, 0x91, 0x20, 0x86, 0x28, 0x92, 
0x20, 0x87, 0x28, 0x93, 0x20, 0x00, 0x28, 0x94, 0x28, 0x95, 
0x28, 0x96, 0x28, 0x97, 0x28, 0x98, 0x28, 0x99, 0x28, 0x9a, 
0x28, 0x9b, 0x28, 0x9c, 0x28, 0x9d, 0x28, 0x9e, 0x28, 0x9f, 
0x21, 0x9a, 0x28, 0xa0, 0x21, 0x00, 0x28, 0xa1, 0x28, 0xa2, 
0x28, 0xa3, 0x28, 0xa4, 0x28, 0xa5, 0x28, 0xa6, 0x28, 0xa7, 
0x28, 0xa8, 0x28, 0xa9, 0x28, 0xaa, 0x28, 0xab, 0x28, 0xac, 
0x28, 0xad, 0x28, 0xae, 0x28, 0xaf, 0x28, 0xb0, 0x28, 0xb1, 
0x28, 0xb2, 0x28, 0xb3, 0x28, 0xb4, 0x28, 0xb5, 0x28, 0xb6, 
0x28, 0xb7, 0x28, 0xb8, 0x28, 0xb9, 0x20, 0x88, 0x28, 0xba, 
0x20, 0x00, 0x28, 0xbb, 0x20, 0x89, 0x28, 0xbc, 0x20, 0x00, 
0x28, 0xbd, 0x28, 0xbe, 0x28, 0xbf, 0x28, 0xc0, 0x28, 0xc1, 
0x28, 0xc2, 0x28, 0xc3, 0x21, 0x9b, 0x28, 0xc4, 0x21, 0x00, 
0x28, 0xc5, 0x28, 0xc6, 0x28, 0xc7, 0x28, 0xc8, 0x28, 0xc9, 
0x28, 0xca, 0x28, 0xcb, 0x28, 0xcc, 0x28, 0xcd, 0x28, 0xce, 
0x28, 0xcf, 0x28, 0xd0, 0x28, 0xd1, 0x28, 0xd2, 0x28, 0xd3, 
0x28, 0xd4, 0x28, 0xd5, 0x28, 0xd6, 0x28, 0xd7, 0x28, 0xd8, 
0x28, 0xd9, 0x28, 0xda, 0x28, 0xdb, 0x28, 0xdc, 0x28, 0xdd, 
0x28, 0xde, 0x28, 0xdf, 0x28, 0xe0, 0x28, 0xe1, 0x20, 0x8a, 
0x28, 0xe2, 0x20, 0x8b, 0x28, 0xe3, 0x20, 0x00, 0x28, 0xe4, 
0x28, 0xe5, 0x28, 0xe6, 0x28, 0xe7, 0x28, 0xe8, 0x28, 0xe9, 
0x28, 0xea, 0x28, 0xeb, 0x28, 0xec, 0x28, 0xed, 0x28, 0xee, 
0x28, 0xef, 0x28, 0xf0, 0x28, 0xf1, 0x28, 0xf2, 0x28, 0xf3, 
0x28, 0xf4, 0x28, 0xf5, 0x28, 0xf6, 0x28, 0xf7, 0x28, 0xf8, 
0x20, 0x8c, 0x28, 0xf9, 0x20, 0x00, 0x21, 0x9c, 0x28, 0xfa, 
0x21, 0x9d, 0x28, 0xfb, 0x20, 0x8d, 0x21, 0x9e, 0x28, 0xfc, 
0x20, 0x8e, 0x21, 0x9f, 0x28, 0xfd, 0x20, 0x00, 0x21, 0x00, 
0x28, 0xfe, 0x28, 0xff, 0x2a, 0x01, 0x28, 0x00, 0x22, 0x01, 
0x23, 0x95, 0x24, 0x89, 0x25, 0x07, 0x26, 0xa4, 0x27, 0x07, 
0x28, 0x01, 0x21, 0xc7, 0x22, 0x00, 0x23, 0x80, 0x26, 0xc4, 
0x27, 0x0c, 0x28, 0x02, 0x20, 0x09, 0x21, 0x1c, 0x22, 0x04, 
0x26, 0xaa, 0x27, 0x0a, 0x28, 0x03, 0x20, 0x00, 0x21, 0x00, 
0x22, 0x00, 0x23, 0xa6, 0x26, 0xa0, 0x27, 0x07, 0x28, 0x04, 
0x28, 0x05, 0x20, 0x05, 0x23, 0x84, 0x26, 0xb4, 0x27, 0x09, 
0x28, 0x06, 0x20, 0x00, 0x22, 0x03, 0x23, 0x00, 0x24, 0x81, 
0x25, 0xc0, 0x26, 0xab, 0x27, 0x0a, 0x28, 0x07, 0x21, 0xae, 
0x22, 0x00, 0x23, 0x95, 0x24, 0x89, 0x25, 0x07, 0x26, 0xa4, 
0x27, 0x00, 0x28, 0x08, 0x21, 0x48, 0x22, 0x01, 0x23, 0x80, 
0x26, 0xc4, 0x27, 0x0c, 0x28, 0x09, 0x20, 0x09, 0x21, 0x04, 
0x22, 0x04, 0x26, 0xaa, 0x27, 0x0a, 0x28, 0x0a, 0x20, 0x00, 
0x21, 0x00, 0x22, 0x00, 0x23, 0xa8, 0x26, 0xa4, 0x27, 0x07, 
0x28, 0x0b, 0x28, 0x0c, 0x21, 0x40, 0x22, 0x20, 0x23, 0x80, 
0x26, 0xc4, 0x27, 0x0c, 0x28, 0x0d, 0x22, 0x24, 0x26, 0xc6, 
0x28, 0x0e, 0x21, 0x9e, 0x22, 0x00, 0x26, 0xc8, 0x28, 0x0f, 
0x20, 0x09, 0x21, 0x02, 0x22, 0x14, 0x26, 0xaa, 0x27, 0x0a, 
0x28, 0x10, 0x20, 0x05, 0x21, 0x00, 0x22, 0x00, 0x23, 0x84, 
0x26, 0xb4, 0x27, 0x09, 0x28, 0x11, 0x20, 0x00, 0x21, 0x01, 
0x23, 0x00, 0x24, 0x01, 0x25, 0xc0, 0x26, 0xab, 0x27, 0x0a, 
0x28, 0x12, 0x21, 0xc3, 0x23, 0x95, 0x24, 0x89, 0x25, 0x07, 
0x26, 0x20, 0x27, 0x00, 0x28, 0x13, 0x20, 0x03, 0x21, 0xc2, 
0x23, 0x83, 0x26, 0x26, 0x27, 0x0d, 0x28, 0x14, 0x21, 0xb3, 
0x22, 0x08, 0x28, 0x15, 0x20, 0x00, 0x21, 0xc6, 0x22, 0x00, 
0x23, 0x95, 0x26, 0x00, 0x27, 0x08, 0x28, 0x16, 0x21, 0x00, 
0x23, 0x00, 0x24, 0x96, 0x25, 0x03, 0x26, 0xaa, 0x27, 0x0a, 
0x28, 0x17, 0x20, 0x42, 0x21, 0xb6, 0x23, 0x80, 0x24, 0x89, 
0x25, 0x07, 0x28, 0x18, 0x20, 0x00, 0x21, 0x00, 0x23, 0x94, 
0x26, 0x0e, 0x28, 0x19, 0x20, 0x0f, 0x23, 0x84, 0x26, 0xb4, 
0x27, 0x09, 0x28, 0x1a, 0x20, 0x00, 0x23, 0x93, 0x26, 0xa8, 
0x27, 0x03, 0x28, 0x1b, 0x26, 0x28, 0x27, 0x00, 0x28, 0x1c, 
0x21, 0x01, 0x23, 0x00, 0x24, 0x01, 0x25, 0xc0, 0x26, 0xab, 
0x27, 0x0a, 0x28, 0x1d, 0x21, 0xc5, 0x23, 0x95, 0x24, 0x89, 
0x25, 0x07, 0x26, 0x20, 0x27, 0x00, 0x28, 0x1e, 0x21, 0x00, 
0x23, 0x94, 0x26, 0x00, 0x27, 0x0a, 0x28, 0x1f, 0x26, 0x0e, 
0x28, 0x20, 0x20, 0x03, 0x21, 0x79, 0x22, 0x01, 0x23, 0x83, 
0x26, 0x26, 0x27, 0x0d, 0x28, 0x21, 0x21, 0x32, 0x28, 0x22, 
0x20, 0x00, 0x21, 0x04, 0x22, 0x00, 0x23, 0x80, 0x24, 0x00, 
0x25, 0xfc, 0x26, 0xaa, 0x27, 0x0a, 0x28, 0x23, 0x21, 0x00, 
0x23, 0x00, 0x25, 0x00, 0x28, 0x24, 0x21, 0xa3, 0x22, 0x0d, 
0x23, 0x80, 0x24, 0x9e, 0x25, 0x3b, 0x28, 0x25, 0x20, 0x42, 
0x21, 0x57, 0x22, 0x01, 0x24, 0x89, 0x25, 0x07, 0x28, 0x26, 
0x20, 0x00, 0x21, 0x43, 0x22, 0x0d, 0x24, 0x00, 0x25, 0x38, 
0x28, 0x27, 0x21, 0x08, 0x22, 0x98, 0x23, 0x95, 0x24, 0x89, 
0x25, 0x07, 0x26, 0x24, 0x27, 0x00, 0x28, 0x28, 0x20, 0x42, 
0x21, 0x93, 0x22, 0x01, 0x23, 0x80, 0x26, 0xaa, 0x27, 0x0a, 
0x28, 0x29, 0x20, 0x03, 0x21, 0x7e, 0x22, 0x04, 0x23, 0x83, 
0x26, 0x26, 0x27, 0x0d, 0x28, 0x2a, 0x20, 0x00, 0x21, 0xb0, 
0x22, 0x00, 0x23, 0x95, 0x26, 0xa0, 0x27, 0x07, 0x28, 0x2b, 
0x21, 0x00, 0x23, 0x00, 0x24, 0x0c, 0x25, 0x04, 0x26, 0xaa, 
0x27, 0x0a, 0x28, 0x2c, 0x21, 0x02, 0x23, 0x80, 0x24, 0x86, 
0x25, 0xc3, 0x26, 0xab, 0x28, 0x2d, 0x20, 0x42, 0x21, 0x97, 
0x22, 0x01, 0x24, 0x89, 0x25, 0x07, 0x26, 0xaa, 0x28, 0x2e, 
0x20, 0x00, 0x21, 0x00, 0x22, 0x00, 0x24, 0x1f, 0x25, 0x04, 
0x28, 0x2f, 0x21, 0xb2, 0x23, 0x95, 0x24, 0x89, 0x25, 0x07, 
0x26, 0x20, 0x27, 0x04, 0x28, 0x30, 0x20, 0x42, 0x21, 0x8b, 
0x22, 0x04, 0x23, 0x80, 0x26, 0xaa, 0x27, 0x0a, 0x28, 0x31, 
0x20, 0x00, 0x21, 0xb1, 0x22, 0x00, 0x23, 0x95, 0x26, 0xa0, 
0x27, 0x07, 0x28, 0x32, 0x20, 0x03, 0x21, 0x75, 0x22, 0x04, 
0x23, 0x83, 0x26, 0x26, 0x27, 0x0d, 0x28, 0x33, 0x20, 0x05, 
0x21, 0x00, 0x22, 0x00, 0x23, 0x84, 0x26, 0xb4, 0x27, 0x09, 
0x28, 0x34, 0x20, 0x00, 0x21, 0x60, 0x23, 0x00, 0x24, 0x01, 
0x25, 0xc0, 0x26, 0xab, 0x27, 0x0a, 0x28, 0x35, 0x21, 0x08, 
0x22, 0x98, 0x23, 0x95, 0x24, 0x89, 0x25, 0x07, 0x26, 0x24, 
0x27, 0x00, 0x28, 0x36, 0x21, 0xbc, 0x22, 0x00, 0x28, 0x37, 
0x21, 0xa3, 0x22, 0x0d, 0x23, 0x00, 0x24, 0x01, 0x25, 0xc0, 
0x26, 0xab, 0x27, 0x0a, 0x28, 0x38, 0x21, 0x60, 0x22, 0x00, 
0x23, 0x80, 0x24, 0x00, 0x25, 0x38, 0x26, 0xaa, 0x28, 0x39, 
0x21, 0x06, 0x22, 0x98, 0x23, 0x95, 0x24, 0x89, 0x25, 0x07, 
0x26, 0x24, 0x27, 0x00, 0x28, 0x3a, 0x21, 0xbe, 0x22, 0x00, 
0x28, 0x3b, 0x20, 0x05, 0x21, 0x00, 0x23, 0x84, 0x26, 0xb4, 
0x27, 0x09, 0x28, 0x3c, 0x20, 0x00, 0x21, 0x60, 0x23, 0x00, 
0x24, 0x01, 0x25, 0xc0, 0x26, 0xab, 0x27, 0x0a, 0x28, 0x3d, 
0x21, 0x42, 0x22, 0x01, 0x23, 0x95, 0x24, 0x89, 0x25, 0x07, 
0x26, 0x24, 0x27, 0x00, 0x28, 0x3e, 0x21, 0x0c, 0x22, 0x98, 
0x26, 0xa4, 0x27, 0x07, 0x28, 0x3f, 0x21, 0x08, 0x28, 0x40, 
0x21, 0x60, 0x22, 0x00, 0x23, 0x00, 0x24, 0x01, 0x25, 0xc0, 
0x26, 0xab, 0x27, 0x0a, 0x28, 0x41, 0x21, 0x0c, 0x22, 0x98, 
0x23, 0x95, 0x24, 0x89, 0x25, 0x07, 0x26, 0x24, 0x27, 0x00, 
0x28, 0x42, 0x20, 0x05, 0x21, 0x00, 0x22, 0x00, 0x23, 0x84, 
0x26, 0xb4, 0x27, 0x09, 0x28, 0x43, 0x20, 0x00, 0x23, 0x80, 
0x24, 0x00, 0x25, 0x10, 0x26, 0xab, 0x27, 0x0a, 0x28, 0x44, 
0x21, 0x22, 0x22, 0x01, 0x23, 0x95, 0x24, 0x89, 0x25, 0x07, 
0x26, 0x24, 0x27, 0x00, 0x28, 0x45, 0x21, 0x00, 0x22, 0x00, 
0x23, 0x00, 0x24, 0x04, 0x25, 0x12, 0x26, 0xaa, 0x27, 0x0a, 
0x28, 0x46, 0x20, 0x03, 0x21, 0xd4, 0x22, 0x05, 0x23, 0x83, 
0x24, 0x89, 0x25, 0x07, 0x26, 0x26, 0x27, 0x0d, 0x28, 0x47, 
0x20, 0x00, 0x21, 0x60, 0x22, 0x00, 0x23, 0x00, 0x24, 0x01, 
0x25, 0xc0, 0x26, 0xab, 0x27, 0x0a, 0x28, 0x48, 0x21, 0xb3, 
0x23, 0x95, 0x24, 0x89, 0x25, 0x07, 0x26, 0x00, 0x27, 0x08, 
0x28, 0x49, 0x21, 0x00, 0x23, 0x00, 0x24, 0x09, 0x25, 0x00, 
0x26, 0xaa, 0x27, 0x0a, 0x28, 0x4a, 0x21, 0x02, 0x23, 0x80, 
0x24, 0x86, 0x25, 0x3b, 0x28, 0x4b, 0x20, 0x42, 0x21, 0xdd, 
0x22, 0x05, 0x24, 0x89, 0x25, 0x07, 0x28, 0x4c, 0x20, 0x00, 
0x21, 0x00, 0x22, 0x00, 0x24, 0x1f, 0x25, 0x00, 0x28, 0x4d, 
0x21, 0xb3, 0x23, 0x95, 0x24, 0x89, 0x25, 0x07, 0x26, 0x20, 
0x27, 0x00, 0x28, 0x4e, 0x21, 0x00, 0x23, 0x00, 0x24, 0x97, 
0x25, 0x03, 0x26, 0xaa, 0x27, 0x0a, 0x28, 0x4f, 0x20, 0x42, 
0x21, 0xe2, 0x22, 0x05, 0x23, 0x80, 0x24, 0x89, 0x25, 0x07, 
0x28, 0x50, 0x20, 0x00, 0x21, 0x10, 0x22, 0x00, 0x23, 0x00, 
0x24, 0x80, 0x25, 0xcc, 0x26, 0xab, 0x28, 0x51, 0x21, 0x00, 
0x22, 0x40, 0x23, 0xb4, 0x24, 0x89, 0x25, 0x07, 0x26, 0xaa, 
0x27, 0x04, 0x28, 0x52, 0x22, 0x00, 0x23, 0xb0, 0x26, 0x92, 
0x27, 0x09, 0x28, 0x53, 0x21, 0x14, 0x22, 0x01, 0x23, 0x95, 
0x26, 0x00, 0x27, 0x08, 0x28, 0x54, 0x21, 0x48, 0x23, 0xa4, 
0x26, 0x2a, 0x27, 0x00, 0x28, 0x55, 0x21, 0x00, 0x22, 0x00, 
0x23, 0x00, 0x24, 0x09, 0x25, 0x00, 0x26, 0xaa, 0x27, 0x0a, 
0x28, 0x56, 0x21, 0x08, 0x23, 0x80, 0x24, 0x86, 0x25, 0x3b, 
0x28, 0x57, 0x20, 0x42, 0x21, 0x11, 0x22, 0x07, 0x24, 0x89, 
0x25, 0x07, 0x28, 0x58, 0x20, 0x00, 0x21, 0x00, 0x22, 0x00, 
0x24, 0x1f, 0x25, 0x00, 0x28, 0x59, 0x21, 0x14, 0x22, 0x01, 
0x23, 0x95, 0x24, 0x89, 0x25, 0x07, 0x26, 0x20, 0x27, 0x00, 
0x28, 0x5a, 0x21, 0x16, 0x26, 0x02, 0x27, 0x09, 0x28, 0x5b, 
0x21, 0x00, 0x22, 0x00, 0x23, 0x00, 0x24, 0x80, 0x25, 0x48, 
0x26, 0xaa, 0x27, 0x0a, 0x28, 0x5c, 0x23, 0xa0, 0x24, 0x89, 
0x25, 0x07, 0x26, 0x14, 0x27, 0x09, 0x28, 0x5d, 0x24, 0x80, 
0x25, 0x50, 0x26, 0xa4, 0x27, 0x04, 0x28, 0x5e, 0x21, 0x16, 
0x22, 0x01, 0x23, 0x95, 0x24, 0x89, 0x25, 0x07, 0x27, 0x00, 
0x28, 0x5f, 0x21, 0x04, 0x22, 0x00, 0x23, 0x00, 0x24, 0x9c, 
0x25, 0x78, 0x26, 0xaa, 0x27, 0x0a, 0x28, 0x60, 0x21, 0x43, 
0x22, 0x0d, 0x24, 0x01, 0x25, 0xc4, 0x26, 0xab, 0x28, 0x61, 
0x21, 0x03, 0x22, 0x00, 0x24, 0x15, 0x28, 0x62, 0x21, 0x00, 
0x24, 0x00, 0x25, 0x00, 0x26, 0xaa, 0x28, 0x63, 0x21, 0x5e, 
0x23, 0x95, 0x24, 0x89, 0x25, 0x07, 0x26, 0x10, 0x27, 0x09, 
0x28, 0x64, 0x21, 0x03, 0x23, 0x00, 0x24, 0x15, 0x25, 0xc4, 
0x26, 0xab, 0x27, 0x0a, 0x28, 0x65, 0x21, 0x00, 0x23, 0x80, 
0x24, 0x00, 0x25, 0x06, 0x26, 0xaa, 0x28, 0x66, 0x24, 0x8f, 
0x25, 0xe3, 0x26, 0xab, 0x28, 0x67, 0x20, 0x42, 0x21, 0xcd, 
0x22, 0x07, 0x24, 0x89, 0x25, 0x07, 0x26, 0xaa, 0x28, 0x68, 
0x20, 0x00, 0x21, 0x60, 0x22, 0x00, 0x23, 0x00, 0x24, 0x01, 
0x25, 0xc0, 0x26, 0xab, 0x28, 0x69, 0x21, 0x00, 0x23, 0x80, 
0x24, 0x8f, 0x25, 0x03, 0x26, 0xaa, 0x28, 0x6a, 0x20, 0x42, 
0x21, 0xdd, 0x22, 0x07, 0x24, 0x89, 0x25, 0x07, 0x28, 0x6b, 
0x20, 0x00, 0x21, 0x43, 0x22, 0x0d, 0x23, 0x00, 0x24, 0x01, 
0x25, 0xc0, 0x26, 0xab, 0x28, 0x6c, 0x21, 0x00, 0x22, 0x00, 
0x24, 0x00, 0x25, 0x04, 0x26, 0xaa, 0x28, 0x6d, 0x20, 0x03, 
0x21, 0x7f, 0x22, 0x01, 0x23, 0x83, 0x24, 0x89, 0x25, 0x07, 
0x26, 0x26, 0x27, 0x0d, 0x28, 0x6e, 0x21, 0x62, 0x28, 0x6f, 
0x20, 0x05, 0x21, 0x00, 0x22, 0x00, 0x23, 0x84, 0x26, 0xb4, 
0x27, 0x09, 0x28, 0x70, 0x20, 0x00, 0x21, 0x06, 0x23, 0x95, 
0x26, 0x00, 0x27, 0x08, 0x28, 0x71, 0x21, 0x01, 0x23, 0x00, 
0x24, 0x97, 0x25, 0x3b, 0x26, 0xaa, 0x27, 0x0a, 0x28, 0x72, 
0x20, 0x42, 0x21, 0x0e, 0x22, 0x08, 0x23, 0x80, 0x24, 0x89, 
0x25, 0x07, 0x28, 0x73, 0x20, 0x03, 0x21, 0x3c, 0x22, 0x0b, 
0x23, 0x83, 0x26, 0x26, 0x27, 0x0d, 0x28, 0x74, 0x20, 0x00, 
0x21, 0x03, 0x22, 0x00, 0x23, 0x95, 0x26, 0x02, 0x27, 0x08, 
0x28, 0x75, 0x21, 0x27, 0x23, 0x00, 0x24, 0x81, 0x25, 0xc4, 
0x26, 0xab, 0x27, 0x0a, 0x28, 0x76, 0x21, 0x00, 0x23, 0x80, 
0x24, 0x09, 0x25, 0x48, 0x26, 0xaa, 0x28, 0x77, 0x21, 0x58, 
0x22, 0x34, 0x23, 0xa3, 0x24, 0x89, 0x25, 0x07, 0x26, 0x2a, 
0x27, 0x00, 0x28, 0x78, 0x21, 0x00, 0x22, 0x00, 0x23, 0xa0, 
0x26, 0x00, 0x27, 0x09, 0x28, 0x79, 0x21, 0x07, 0x23, 0x80, 
0x24, 0x03, 0x25, 0x39, 0x26, 0xaa, 0x27, 0x0a, 0x28, 0x7a, 
0x21, 0x04, 0x23, 0x00, 0x24, 0x1c, 0x25, 0x38, 0x28, 0x7b, 
0x21, 0x07, 0x23, 0x80, 0x24, 0x83, 0x25, 0x39, 0x28, 0x7c, 
0x21, 0x03, 0x23, 0x95, 0x24, 0x89, 0x25, 0x07, 0x26, 0x02, 
0x27, 0x08, 0x28, 0x7d, 0x21, 0x27, 0x23, 0x00, 0x24, 0x81, 
0x25, 0xc4, 0x26, 0xab, 0x27, 0x0a, 0x28, 0x7e, 0x21, 0x00, 
0x23, 0x80, 0x24, 0x09, 0x25, 0x48, 0x26, 0xaa, 0x28, 0x7f, 
0x21, 0x58, 0x22, 0x34, 0x23, 0xa3, 0x24, 0x89, 0x25, 0x07, 
0x26, 0x2a, 0x27, 0x00, 0x28, 0x80, 0x21, 0x06, 0x22, 0x00, 
0x23, 0x00, 0x24, 0x81, 0x25, 0xc0, 0x26, 0x93, 0x27, 0x01, 
0x28, 0x81, 0x21, 0x00, 0x23, 0x80, 0x24, 0x89, 0x25, 0x48, 
0x26, 0xaa, 0x27, 0x0a, 0x28, 0x82, 0x20, 0x02, 0x21, 0x66, 
0x22, 0x08, 0x23, 0x00, 0x24, 0x00, 0x25, 0x66, 0x28, 0x83, 
0x20, 0x00, 0x21, 0x00, 0x22, 0x00, 0x23, 0x80, 0x24, 0x1f, 
0x25, 0x02, 0x28, 0x84, 0x21, 0x06, 0x24, 0x89, 0x25, 0x07, 
0x26, 0xdc, 0x27, 0x0c, 0x28, 0x85, 0x21, 0x00, 0x23, 0xaa, 
0x26, 0xaa, 0x27, 0x0a, 0x28, 0x86, 0x23, 0xb6, 0x26, 0x00, 
0x27, 0x08, 0x28, 0x87, 0x23, 0x80, 0x24, 0x86, 0x25, 0x3b, 
0x26, 0xaa, 0x27, 0x0a, 0x28, 0x88, 0x21, 0x05, 0x24, 0x89, 
0x25, 0x07, 0x26, 0xdc, 0x27, 0x0c, 0x28, 0x89, 0x21, 0x00, 
0x23, 0xaa, 0x26, 0xaa, 0x27, 0x0a, 0x28, 0x8a, 0x23, 0xb6, 
0x26, 0x00, 0x27, 0x08, 0x28, 0x8b, 0x23, 0x80, 0x24, 0x86, 
0x25, 0x3b, 0x26, 0xaa, 0x27, 0x0a, 0x28, 0x8c, 0x20, 0x42, 
0x21, 0x7b, 0x22, 0x08, 0x24, 0x89, 0x25, 0x07, 0x28, 0x8d, 
0x20, 0x00, 0x21, 0x00, 0x22, 0x00, 0x23, 0x00, 0x24, 0x01, 
0x25, 0x82, 0x28, 0x8e, 0x21, 0x05, 0x24, 0x81, 0x25, 0xc2, 
0x26, 0xab, 0x28, 0x8f, 0x20, 0x03, 0x21, 0x93, 0x22, 0x08, 
0x23, 0x83, 0x24, 0x89, 0x25, 0x07, 0x26, 0x26, 0x27, 0x0d, 
0x28, 0x90, 0x20, 0x00, 0x21, 0x05, 0x22, 0x00, 0x23, 0x00, 
0x24, 0x81, 0x25, 0xc0, 0x26, 0x13, 0x27, 0x01, 0x28, 0x91, 
0x21, 0x00, 0x23, 0x80, 0x24, 0x89, 0x25, 0x48, 0x26, 0xaa, 
0x27, 0x0a, 0x28, 0x92, 0x20, 0x02, 0x21, 0x7e, 0x22, 0x08, 
0x23, 0x00, 0x24, 0x00, 0x25, 0x66, 0x28, 0x93, 0x20, 0x00, 
0x21, 0x00, 0x22, 0x00, 0x23, 0x80, 0x24, 0x1f, 0x25, 0x02, 
0x28, 0x94, 0x21, 0x05, 0x24, 0x89, 0x25, 0x07, 0x26, 0xdc, 
0x27, 0x0c, 0x28, 0x95, 0x21, 0x00, 0x23, 0xaa, 0x26, 0xaa, 
0x27, 0x0a, 0x28, 0x96, 0x23, 0xb6, 0x26, 0x00, 0x27, 0x08, 
0x28, 0x97, 0x23, 0x80, 0x24, 0x86, 0x25, 0x3b, 0x26, 0xaa, 
0x27, 0x0a, 0x28, 0x98, 0x21, 0x05, 0x24, 0x89, 0x25, 0x07, 
0x26, 0xdc, 0x27, 0x0c, 0x28, 0x99, 0x21, 0x00, 0x23, 0xaa, 
0x26, 0xaa, 0x27, 0x0a, 0x28, 0x9a, 0x23, 0x80, 0x24, 0x1f, 
0x25, 0x02, 0x28, 0x9b, 0x21, 0x01, 0x23, 0x00, 0x24, 0x81, 
0x25, 0xc2, 0x26, 0xab, 0x28, 0x9c, 0x20, 0x03, 0x21, 0x93, 
0x22, 0x08, 0x23, 0x83, 0x24, 0x89, 0x25, 0x07, 0x26, 0x26, 
0x27, 0x0d, 0x28, 0x9d, 0x20, 0x00, 0x21, 0x04, 0x22, 0x00, 
0x23, 0x95, 0x26, 0x12, 0x27, 0x08, 0x28, 0x9e, 0x21, 0x60, 
0x23, 0xc4, 0x26, 0xaa, 0x27, 0x04, 0x28, 0x9f, 0x21, 0x00, 
0x23, 0xc0, 0x26, 0x00, 0x27, 0x09, 0x28, 0xa0, 0x20, 0x42, 
0x21, 0xcb, 0x22, 0x08, 0x23, 0x80, 0x26, 0xaa, 0x27, 0x0a, 
0x28, 0xa1, 0x20, 0x70, 0x21, 0x54, 0x22, 0xb8, 0x23, 0x95, 
0x26, 0x12, 0x27, 0x08, 0x28, 0xa2, 0x20, 0x02, 0x21, 0xcc, 
0x22, 0x08, 0x23, 0x80, 0x26, 0xaa, 0x27, 0x0a, 0x28, 0xa3, 
0x20, 0x03, 0x21, 0xca, 0x22, 0x0f, 0x23, 0x83, 0x26, 0x26, 
0x27, 0x0d, 0x28, 0xa4, 0x20, 0x00, 0x21, 0x00, 0x22, 0x00, 
0x23, 0x00, 0x24, 0x8c, 0x25, 0x0c, 0x26, 0xaa, 0x27, 0x0a, 
0x28, 0xa5, 0x21, 0x04, 0x24, 0x82, 0x25, 0x78, 0x28, 0xa6, 
0x21, 0x00, 0x23, 0x80, 0x24, 0x89, 0x25, 0x48, 0x26, 0x12, 
0x27, 0x04, 0x28, 0xa7, 0x20, 0x03, 0x21, 0xde, 0x22, 0x0f, 
0x23, 0x83, 0x25, 0x07, 0x26, 0x26, 0x27, 0x0d, 0x28, 0xa8, 
0x20, 0x00, 0x21, 0x01, 0x22, 0x00, 0x23, 0x00, 0x24, 0x9c, 
0x25, 0x78, 0x26, 0xaa, 0x27, 0x0a, 0x28, 0xa9, 0x21, 0x00, 
0x23, 0x80, 0x24, 0x81, 0x25, 0x40, 0x28, 0xaa, 0x20, 0x03, 
0x21, 0xcf, 0x22, 0x0f, 0x23, 0x83, 0x24, 0x89, 0x25, 0x07, 
0x26, 0x26, 0x27, 0x0d, 0x28, 0xab, 0x20, 0x70, 0x21, 0x08, 
0x22, 0xb8, 0x23, 0x95, 0x26, 0xa0, 0x27, 0x04, 0x28, 0xac, 
0x20, 0x03, 0x21, 0xd4, 0x22, 0x0f, 0x23, 0x83, 0x26, 0x26, 
0x27, 0x0d, 0x28, 0xad, 0x21, 0x27, 0x22, 0x0b, 0x28, 0xae, 
0x20, 0x70, 0x21, 0x63, 0x22, 0xb8, 0x23, 0x95, 0x26, 0x12, 
0x27, 0x08, 0x28, 0xaf, 0x20, 0x00, 0x21, 0x01, 0x22, 0x00, 
0x23, 0x80, 0x24, 0x86, 0x25, 0xcb, 0x26, 0xab, 0x27, 0x0a, 
0x28, 0xb0, 0x20, 0x42, 0x21, 0xdd, 0x22, 0x08, 0x24, 0x89, 
0x25, 0x07, 0x26, 0xaa, 0x28, 0xb1, 0x20, 0x00, 0x21, 0x18, 
0x22, 0x80, 0x23, 0x95, 0x26, 0xa4, 0x27, 0x00, 0x28, 0xb2, 
0x20, 0x03, 0x21, 0xd9, 0x22, 0x0f, 0x23, 0x83, 0x26, 0x26, 
0x27, 0x0d, 0x28, 0xb3, 0x20, 0x70, 0x21, 0x0a, 0x22, 0xb8, 
0x23, 0x95, 0x26, 0xa0, 0x27, 0x00, 0x28, 0xb4, 0x20, 0x02, 
0x21, 0xe0, 0x22, 0x08, 0x23, 0x80, 0x26, 0xaa, 0x27, 0x0a, 
0x28, 0xb5, 0x20, 0x70, 0x21, 0x0a, 0x22, 0xb8, 0x23, 0x95, 
0x26, 0xa0, 0x27, 0x00, 0x28, 0xb6, 0x21, 0x54, 0x26, 0x02, 
0x27, 0x08, 0x28, 0xb7, 0x20, 0x00, 0x21, 0x18, 0x22, 0x80, 
0x26, 0xa4, 0x27, 0x00, 0x28, 0xb8, 0x21, 0x00, 0x22, 0x00, 
0x23, 0x80, 0x24, 0x80, 0x25, 0x48, 0x26, 0xaa, 0x27, 0x0a, 
0x28, 0xb9, 0x20, 0x70, 0x21, 0x5e, 0x22, 0xb8, 0x23, 0x95, 
0x24, 0x89, 0x25, 0x07, 0x26, 0x12, 0x27, 0x08, 0x28, 0xba, 
0x20, 0x00, 0x21, 0x00, 0x22, 0x00, 0x23, 0x80, 0x24, 0x09, 
0x25, 0x4b, 0x26, 0xaa, 0x27, 0x0a, 0x28, 0xbb, 0x20, 0x70, 
0x21, 0x5f, 0x22, 0xb8, 0x23, 0x95, 0x24, 0x89, 0x25, 0x07, 
0x26, 0x10, 0x27, 0x08, 0x28, 0xbc, 0x20, 0x00, 0x21, 0x00, 
0x22, 0x00, 0x23, 0x00, 0x24, 0x1c, 0x25, 0x83, 0x26, 0xab, 
0x27, 0x0a, 0x28, 0xbd, 0x20, 0x03, 0x21, 0x32, 0x22, 0x09, 
0x23, 0x83, 0x24, 0x89, 0x25, 0x07, 0x26, 0x26, 0x27, 0x0d, 
0x28, 0xbe, 0x20, 0x00, 0x21, 0x00, 0x22, 0x00, 0x23, 0x00, 
0x24, 0x82, 0x25, 0x8c, 0x26, 0xab, 0x27, 0x0a, 0x28, 0xbf, 
0x20, 0x03, 0x21, 0x25, 0x22, 0x09, 0x23, 0x83, 0x24, 0x89, 
0x25, 0x07, 0x26, 0x26, 0x27, 0x0d, 0x28, 0xc0, 0x20, 0x42, 
0x21, 0xbc, 0x23, 0x80, 0x26, 0xaa, 0x27, 0x0a, 0x28, 0xc1, 
0x20, 0x00, 0x21, 0x01, 0x22, 0x00, 0x23, 0x00, 0x24, 0x01, 
0x25, 0xc0, 0x26, 0xab, 0x28, 0xc2, 0x20, 0x70, 0x21, 0x0f, 
0x22, 0xb8, 0x23, 0x95, 0x24, 0x89, 0x25, 0x07, 0x26, 0x20, 
0x27, 0x00, 0x28, 0xc3, 0x20, 0x03, 0x21, 0xe3, 0x22, 0x0f, 
0x23, 0x83, 0x26, 0x26, 0x27, 0x0d, 0x28, 0xc4, 0x20, 0x05, 
0x21, 0x00, 0x22, 0x00, 0x23, 0x84, 0x26, 0xb4, 0x27, 0x09, 
0x28, 0xc5, 0x20, 0x00, 0x21, 0x03, 0x23, 0x95, 0x26, 0x14, 
0x27, 0x08, 0x28, 0xc6, 0x21, 0xa6, 0x23, 0xa4, 0x26, 0x2a, 
0x27, 0x05, 0x28, 0xc7, 0x21, 0x00, 0x23, 0xa0, 0x26, 0x44, 
0x27, 0x09, 0x28, 0xc8, 0x21, 0x18, 0x22, 0x6d, 0x23, 0x80, 
0x24, 0x9e, 0x25, 0x7b, 0x26, 0xaa, 0x27, 0x0a, 0x28, 0xc9, 
0x20, 0x42, 0x21, 0x13, 0x22, 0x0b, 0x24, 0x89, 0x25, 0x07, 
0x28, 0xca, 0x20, 0x00, 0x21, 0xae, 0x22, 0x00, 0x23, 0x95, 
0x26, 0x24, 0x27, 0x00, 0x28, 0xcb, 0x21, 0x00, 0x22, 0x03, 
0x23, 0x80, 0x24, 0x87, 0x25, 0x7b, 0x26, 0xaa, 0x27, 0x0a, 
0x28, 0xcc, 0x20, 0x42, 0x21, 0x16, 0x22, 0x0b, 0x24, 0x89, 
0x25, 0x07, 0x28, 0xcd, 0x20, 0x00, 0x21, 0xae, 0x22, 0x00, 
0x23, 0x95, 0x26, 0x24, 0x27, 0x00, 0x28, 0xce, 0x20, 0x05, 
0x21, 0x00, 0x23, 0x84, 0x26, 0xb4, 0x27, 0x09, 0x28, 0xcf, 
0x20, 0x03, 0x21, 0x0d, 0x22, 0x0b, 0x23, 0x83, 0x26, 0x26, 
0x27, 0x0d, 0x28, 0xd0, 0x20, 0x00, 0x21, 0x00, 0x22, 0x00, 
0x23, 0x00, 0x24, 0x80, 0x26, 0x02, 0x27, 0x00, 0x28, 0xd1, 
0x23, 0x80, 0x24, 0x09, 0x25, 0x48, 0x26, 0x1e, 0x28, 0xd2, 
0x21, 0x58, 0x22, 0x34, 0x23, 0x33, 0x24, 0x80, 0x25, 0x07, 
0x26, 0x2a, 0x28, 0xd3, 0x21, 0x00, 0x22, 0x00, 0x23, 0x00, 
0x26, 0x80, 0x27, 0x10, 0x28, 0xd4, 0x21, 0x10, 0x23, 0x63, 
0x26, 0x2a, 0x27, 0x00, 0x28, 0xd5, 0x21, 0x00, 0x23, 0x60, 
0x26, 0xa8, 0x27, 0x12, 0x28, 0xd6, 0x21, 0xaf, 0x22, 0x4c, 
0x23, 0x00, 0x26, 0xc8, 0x27, 0x0c, 0x28, 0xd7, 0x21, 0x00, 
0x22, 0x00, 0x26, 0x80, 0x27, 0x05, 0x28, 0xd8, 0x23, 0x80, 
0x24, 0x86, 0x25, 0x3b, 0x26, 0x1e, 0x27, 0x00, 0x28, 0xd9, 
0x20, 0x42, 0x21, 0x1c, 0x22, 0x0e, 0x23, 0x00, 0x24, 0x80, 
0x25, 0x07, 0x28, 0xda, 0x20, 0x00, 0x21, 0x35, 0x22, 0x29, 
0x26, 0xc4, 0x27, 0x0c, 0x28, 0xdb, 0x20, 0x02, 0x21, 0x1d, 
0x22, 0x0e, 0x26, 0x1e, 0x27, 0x00, 0x28, 0xdc, 0x20, 0x00, 
0x21, 0x7f, 0x22, 0x34, 0x26, 0xc4, 0x27, 0x0c, 0x28, 0xdd, 
0x21, 0x00, 0x22, 0x00, 0x23, 0x90, 0x24, 0x9f, 0x25, 0x04, 
0x26, 0x10, 0x27, 0x0a, 0x28, 0xde, 0x23, 0x00, 0x24, 0x84, 
0x25, 0x00, 0x26, 0x80, 0x27, 0x10, 0x28, 0xdf, 0x21, 0x06, 
0x23, 0x63, 0x24, 0x80, 0x25, 0x07, 0x26, 0x2a, 0x27, 0x00, 
0x28, 0xe0, 0x21, 0x00, 0x23, 0x80, 0x24, 0x89, 0x26, 0xaa, 
0x27, 0x0a, 0x28, 0xe1, 0x20, 0x05, 0x23, 0x84, 0x26, 0xb4, 
0x27, 0x09, 0x28, 0xe2, 0x20, 0x70, 0x21, 0x61, 0x22, 0xb8, 
0x23, 0x95, 0x26, 0x12, 0x27, 0x08, 0x28, 0xe3, 0x20, 0x00, 
0x21, 0x01, 0x22, 0x00, 0x23, 0x80, 0x24, 0x86, 0x25, 0xc3, 
0x26, 0xab, 0x27, 0x0a, 0x28, 0xe4, 0x20, 0x42, 0x21, 0xce, 
0x22, 0x0f, 0x24, 0x89, 0x25, 0x07, 0x26, 0xaa, 0x28, 0xe5, 
0x20, 0x70, 0x21, 0x50, 0x22, 0xb8, 0x23, 0x95, 0x26, 0x12, 
0x27, 0x08, 0x28, 0xe6, 0x20, 0x05, 0x21, 0x00, 0x22, 0x00, 
0x23, 0x84, 0x26, 0xb4, 0x27, 0x09, 0x28, 0xe7, 0x20, 0x70, 
0x21, 0x64, 0x22, 0xb8, 0x23, 0x95, 0x26, 0x12, 0x27, 0x08, 
0x28, 0xe8, 0x20, 0x00, 0x21, 0x01, 0x22, 0x00, 0x23, 0x80, 
0x24, 0x86, 0x25, 0xc3, 0x26, 0xab, 0x27, 0x0a, 0x28, 0xe9, 
0x20, 0x42, 0x21, 0xd3, 0x22, 0x0f, 0x24, 0x89, 0x25, 0x07, 
0x26, 0xaa, 0x28, 0xea, 0x20, 0x70, 0x21, 0x51, 0x22, 0xb8, 
0x23, 0x95, 0x26, 0x12, 0x27, 0x08, 0x28, 0xeb, 0x20, 0x05, 
0x21, 0x00, 0x22, 0x00, 0x23, 0x84, 0x26, 0xb4, 0x27, 0x09, 
0x28, 0xec, 0x20, 0x70, 0x21, 0x65, 0x22, 0xb8, 0x23, 0x95, 
0x26, 0x12, 0x27, 0x08, 0x28, 0xed, 0x20, 0x00, 0x21, 0x01, 
0x22, 0x00, 0x23, 0x80, 0x24, 0x86, 0x25, 0xc3, 0x26, 0xab, 
0x27, 0x0a, 0x28, 0xee, 0x20, 0x42, 0x21, 0xd8, 0x22, 0x0f, 
0x24, 0x89, 0x25, 0x07, 0x26, 0xaa, 0x28, 0xef, 0x20, 0x70, 
0x21, 0x52, 0x22, 0xb8, 0x23, 0x95, 0x26, 0x12, 0x27, 0x08, 
0x28, 0xf0, 0x20, 0x05, 0x21, 0x00, 0x22, 0x00, 0x23, 0x84, 
0x26, 0xb4, 0x27, 0x09, 0x28, 0xf1, 0x20, 0x70, 0x21, 0x61, 
0x22, 0xb8, 0x23, 0x95, 0x26, 0x02, 0x27, 0x08, 0x28, 0xf2, 
0x20, 0x00, 0x21, 0x01, 0x22, 0x00, 0x23, 0x80, 0x24, 0x86, 
0x25, 0xc3, 0x26, 0xab, 0x27, 0x0a, 0x28, 0xf3, 0x20, 0x42, 
0x21, 0xdd, 0x22, 0x0f, 0x24, 0x89, 0x25, 0x07, 0x26, 0xaa, 
0x28, 0xf4, 0x20, 0x70, 0x21, 0x50, 0x22, 0xb8, 0x23, 0x95, 
0x26, 0x02, 0x27, 0x08, 0x28, 0xf5, 0x20, 0x05, 0x21, 0x00, 
0x22, 0x00, 0x23, 0x84, 0x26, 0xb4, 0x27, 0x09, 0x28, 0xf6, 
0x20, 0x00, 0x21, 0x01, 0x23, 0x80, 0x24, 0x86, 0x25, 0xcb, 
0x26, 0xab, 0x27, 0x0a, 0x28, 0xf7, 0x20, 0x42, 0x21, 0xe1, 
0x22, 0x0f, 0x24, 0x89, 0x25, 0x07, 0x26, 0xaa, 0x28, 0xf8, 
0x20, 0x00, 0x21, 0x02, 0x22, 0x00, 0x23, 0x00, 0x24, 0x81, 
0x25, 0xc4, 0x26, 0xab, 0x28, 0xf9, 0x21, 0x00, 0x23, 0x80, 
0x24, 0x89, 0x25, 0x48, 0x26, 0xaa, 0x28, 0xfa, 0x20, 0x05, 
0x23, 0x84, 0x25, 0x07, 0x26, 0xb4, 0x27, 0x09, 0x28, 0xfb, 
0x20, 0x70, 0x21, 0x4e, 0x22, 0xb8, 0x23, 0x95, 0x26, 0x10, 
0x27, 0x08, 0x28, 0xfc, 0x20, 0x00, 0x21, 0x00, 0x22, 0x00, 
0x23, 0x80, 0x24, 0x86, 0x25, 0xc3, 0x26, 0xab, 0x27, 0x0a, 
0x28, 0xfd, 0x20, 0x42, 0x21, 0xe7, 0x22, 0x0f, 0x24, 0x89, 
0x25, 0x07, 0x26, 0xaa, 0x28, 0xfe, 0x20, 0x00, 0x21, 0xbb, 
0x22, 0x00, 0x23, 0x95, 0x26, 0x20, 0x27, 0x00, 0x28, 0xff, 
0x20, 0x05, 0x21, 0x00, 0x23, 0x84, 0x26, 0xb4, 0x27, 0x09, 
0x2a, 0x08, 0x10, 0x01, 0x3a, 0x00, 0x64, 0x3a, 0x65, 0xbb, 
0x08, 0x3a, 0x09, 0xbb, 0x50, 0x10, 0x52, 0x67, 0x51, 0x77, 
0x05, 0xa1, 0x18, 0x04, 0xff, 0xff
   };


static void
STA_WriteRegister(unsigned char reg, unsigned char data)
{
   I2C_Start();
   I2C_SendByte(0x86);
   I2C_SendByte(reg);
   I2C_SendByte(data);
   I2C_Stop();
}


/*
 * Performs a "Random Address Read" to read the contents of a single
 * register.
 */
static unsigned char
STA_ReadRegister(unsigned char reg)
{
   unsigned char data;


   /* Random address read */
   I2C_Start();
   I2C_SendByte(0x86);
   I2C_SendByte(reg);
   I2C_Start();
   I2C_SendByte(0x87);
   data = I2C_ReadByte();
   I2C_Stop();

   return(data);
}


static int
STA_DownloadUpdate()
{
   int           i;
   unsigned char a;
   unsigned char d;


   i=0;
   a = STA013_UpdateData[i];
   d = STA013_UpdateData[i+1];
   i+=2;
   while ((a != 0xff) || (d != 0xff))
   {
      STA_WriteRegister(a, d);
      a = STA013_UpdateData[i];
      d = STA013_UpdateData[i+1];
      i+=2;
   }
   return(0);
}


int
STA_Reset()
{
   struct CantanteSettings settings;


   m360.pbdat &= ~MPEG_RESET;
   rtems_task_wake_after(1);
   m360.pbdat |= MPEG_RESET;
   rtems_task_wake_after(1);

   /***********************************************************************
    * Make sure the STA identifies itself correctly.
    **********************************************************************/
   if (STA_ReadRegister(STA_REG_IDENT) != 0xac)
      return(1);

   /***********************************************************************
    * Download any ST Microelectronics updates.
    **********************************************************************/
   STA_DownloadUpdate();

   /***********************************************************************
    * Initialize tone controls based on device configuration.
    **********************************************************************/
   STA_ReadToneControls();
   tone_controls_g.bass_freq = 200;
   tone_controls_g.treble_freq = 3000;
   Monitor_ReadCantanteSettings(&settings);
   if (settings.volume_fixed == 1)
   {
      tone_controls_g.volume_dla = 3;
      tone_controls_g.volume_dra = 3;
      tone_controls_g.volume_dlb = 96;
      tone_controls_g.volume_drb = 96;
   }
   else
   {
      tone_controls_g.volume_dla = 18;
      tone_controls_g.volume_dra = 18;
      tone_controls_g.volume_dlb = 96;
      tone_controls_g.volume_drb = 96;
   }
   STA_WriteToneControls();
   return(0);
}


/**************************************************************************
 * Tone control ranges are dictated by STA013 documentation:
 *       volume_dla: 0 to 96 representing dB attenuation
 *       volume_dlb: 0 to 96 representing dB attenuation
 *       volume_dra: 0 to 96 representing dB attenuation
 *       volume_drb: 0 to 96 representing dB attenuation
 *       tone_atten: 0 to 12 representing 1.5dB attenuation
 *     bass_enhance: -12 to 12 representing 1.5dB steps
 *   treble_enhance: -12 to 12 representing 1.5dB steps
 *************************************************************************/
static int
STA_ReadToneControls()
{
   unsigned char t;

   tone_controls_g.volume_dla     = STA_ReadRegister(STA_REG_DLA);
   tone_controls_g.volume_dlb     = STA_ReadRegister(STA_REG_DLB);
   tone_controls_g.volume_dra     = STA_ReadRegister(STA_REG_DRA);
   tone_controls_g.volume_drb     = STA_ReadRegister(STA_REG_DRB);
   tone_controls_g.bass_freq =
               (int)STA_ReadRegister(STA_REG_BASS_FREQUENCY_HIGH) * 256 +
               (int)STA_ReadRegister(STA_REG_BASS_FREQUENCY_LOW);
   tone_controls_g.treble_freq    =
               (int)STA_ReadRegister(STA_REG_TREBLE_FREQUENCY_HIGH) * 256 + 
               (int)STA_ReadRegister(STA_REG_TREBLE_FREQUENCY_LOW);

   t = STA_ReadRegister(STA_REG_BASS_ENHANCE);
   if (t < 128)
      tone_controls_g.bass_enhance = (int)t;
   else
      tone_controls_g.bass_enhance = (int)t - 256;

   t = STA_ReadRegister(STA_REG_TREBLE_ENHANCE);
   if (t < 128)
      tone_controls_g.treble_enhance = (int)t;
   else
      tone_controls_g.treble_enhance = (int)t - 256;

   return(0);
}


static int
STA_WriteToneControls()
{
   unsigned char t;
   int           tone;


   STA_WriteRegister(STA_REG_DLA, tone_controls_g.volume_dla);
   STA_WriteRegister(STA_REG_DLB, tone_controls_g.volume_dlb);
   STA_WriteRegister(STA_REG_DRA, tone_controls_g.volume_dra);
   STA_WriteRegister(STA_REG_DRB, tone_controls_g.volume_drb);
   STA_WriteRegister(STA_REG_BASS_FREQUENCY_HIGH, 
                     tone_controls_g.bass_freq / 256);
   STA_WriteRegister(STA_REG_BASS_FREQUENCY_LOW, 
                     tone_controls_g.bass_freq % 256);
   STA_WriteRegister(STA_REG_TREBLE_FREQUENCY_HIGH,
                     tone_controls_g.treble_freq / 256);
   STA_WriteRegister(STA_REG_TREBLE_FREQUENCY_LOW,
                     tone_controls_g.treble_freq % 256);

   /***********************************************************************
    * Set the tone attenuation to be max(0, bass, treble)
    **********************************************************************/
   tone = MAX(0, MAX(tone_controls_g.bass_enhance,
                     tone_controls_g.treble_enhance));
   STA_WriteRegister(STA_REG_TONE_ATTEN, tone);

   if (tone_controls_g.bass_enhance > 0)
      t = (unsigned char)tone_controls_g.bass_enhance;
   else
      t = (unsigned char)(tone_controls_g.bass_enhance + 256);
   STA_WriteRegister(STA_REG_BASS_ENHANCE, t);

   if (tone_controls_g.treble_enhance > 0)
      t = (unsigned char)tone_controls_g.treble_enhance;
   else
      t = (unsigned char)(tone_controls_g.treble_enhance + 256);
   STA_WriteRegister(STA_REG_TREBLE_ENHANCE, t);

   /***********************************************************************
    * Tone controls have changed, so notify everyone listening.
    **********************************************************************/
   Status_Command(STATUS_COMMAND_TONECHANGE);
   return(0);
}


int
STA_StartDecoder()
{
   DAC_Mute();
   rtems_semaphore_obtain(sta_semid_g, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
   STA_WriteRegister(STA_REG_SOFT_RESET, 0x01);

   /*
    * Mute and configure DAC output.
    */
   STA_WriteRegister(STA_REG_MUTE,       0x01);
   STA_WriteRegister(STA_REG_PCMDIVIDER, 0x03);
   STA_WriteRegister(STA_REG_PCMCONF,    0x2b);

   /*
    * Configure PLL for MP3 rates.
    */
   STA_WriteRegister(STA_REG_PLLFRAC_441_H, 0xff);
   STA_WriteRegister(STA_REG_PLLFRAC_441_L, 0xff);
   STA_WriteRegister(STA_REG_PLLFRAC_H,     0xbb);
   STA_WriteRegister(STA_REG_PLLFRAC_L,     0x3a);
   STA_WriteRegister(STA_REG_MFSDF_441,     0x08);
   STA_WriteRegister(STA_REG_MFSDF,         0x07);

   /*
    * Configure interface polarities, etc.
    */
   STA_WriteRegister(STA_REG_PLLCTL_2,        0x0c);
   STA_WriteRegister(STA_REG_PLLCTL_3,        0x00);
   STA_WriteRegister(STA_REG_PLLCTL_1,        0x01);
   STA_WriteRegister(STA_REG_SCLK_POL,        0x00);
   STA_WriteRegister(STA_REG_REQ_POL,         0x05);
   STA_WriteRegister(STA_REG_DATA_REQ_ENABLE, 0x04);
   STA_WriteRegister(STA_REG_PLLCTL_1,        0xa1);

   STA_WriteToneControls();

   /*
    * Unmute and start running.
    */
   STA_WriteRegister(STA_REG_RUN,  0x01);
   STA_WriteRegister(STA_REG_PLAY, 0x01);
   STA_WriteRegister(STA_REG_MUTE, 0x00);

   rtems_task_wake_after(1);
   DAC_UnMute();
   rtems_semaphore_release(sta_semid_g);

   return(0);
}


int
STA_StopDecoder()
{
   DAC_Mute();
   rtems_semaphore_obtain(sta_semid_g, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
   STA_ReadToneControls();
   STA_WriteRegister(STA_REG_MUTE, 0x01);
   STA_WriteRegister(STA_REG_SOFT_RESET, 0x01);
   STA_WriteRegister(STA_REG_SOFT_RESET, 0x00);
   rtems_semaphore_release(sta_semid_g);
   return(0);
}


int
STA_PauseDecoder()
{
   rtems_semaphore_obtain(sta_semid_g, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
   STA_WriteRegister(STA_REG_PLAY, 0x00);
   rtems_semaphore_release(sta_semid_g);
   return(0);
}


int
STA_ResumeDecoder()
{
   rtems_semaphore_obtain(sta_semid_g, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
   STA_WriteRegister(STA_REG_PLAY, 0x01);
   rtems_semaphore_release(sta_semid_g);
   return(0);
}


int
STA_QueryMP3Header(struct MP3_Header *hdr)
{
   unsigned long l;


   rtems_semaphore_obtain(sta_semid_g, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
   l = (unsigned long)STA_ReadRegister(STA_REG_HEAD_H) << 16 |
       (unsigned long)STA_ReadRegister(STA_REG_HEAD_M) << 8  |
       (unsigned long)STA_ReadRegister(STA_REG_HEAD_L);
   rtems_semaphore_release(sta_semid_g);

   hdr->word           = l;
   hdr->emphasis       = l & 0x03;
   hdr->isOriginal     = (l >> 2) & 0x01;
   hdr->isCopyrighted  = (l >> 3) & 0x01;
   hdr->modeExtension  = (l >> 4) & 0x03;
   hdr->mode           = (l >> 6) & 0x03;
   hdr->private        = (l >> 8) & 0x01;
   hdr->padding        = (l >> 9) & 0x01;
   hdr->frequencyIndex = (l >> 10) & 0x03;
   hdr->bitrateIndex   = (l >> 12) & 0x0f;
   hdr->protection     = (l >> 16) & 0x01;
   hdr->layer          = (l >> 17) & 0x03;
   hdr->ID             = (l >> 19) & 0x01;
   hdr->ID_ex          = (l >> 20) & 0x01;

   hdr->bitrate   = MP3_Bitrates[hdr->bitrateIndex + 16*hdr->ID];
   hdr->frequency = MP3_SamplingFrequencies[hdr->frequencyIndex + 
                                            4*hdr->ID + 8*hdr->ID_ex];
   return(0);
}


unsigned long
STA_QueryFrameCount()
{
   unsigned long l;

   rtems_semaphore_obtain(sta_semid_g, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
   l = (unsigned long)STA_ReadRegister(STA_REG_FRAME_CNT_H) << 16 |
       (unsigned long)STA_ReadRegister(STA_REG_FRAME_CNT_M) << 8  |
       (unsigned long)STA_ReadRegister(STA_REG_FRAME_CNT_L);
   rtems_semaphore_release(sta_semid_g);
   return(l);
}


int
STA_QueryAverageBitrate()
{
   int c;

   rtems_semaphore_obtain(sta_semid_g, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
   c = 2 * (int)STA_ReadRegister(STA_REG_AVERAGE_BITRATE);
   rtems_semaphore_release(sta_semid_g);
   return(c);
}


int
STA_SetVolumeMatrix(unsigned char dla, unsigned char dlb,
                    unsigned char dra, unsigned char drb)
{
   if ((dla > 96) || (dlb > 96) || (dra > 96) || (drb > 96))
      return(-1);

   tone_controls_g.volume_dla = dla;
   tone_controls_g.volume_dlb = dlb;
   tone_controls_g.volume_dra = dra;
   tone_controls_g.volume_drb = drb;
   rtems_semaphore_obtain(sta_semid_g, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
   STA_WriteToneControls();
   rtems_semaphore_release(sta_semid_g);
   return(0);
}


int
STA_SetBassFrequency(unsigned short freq)
{
   rtems_semaphore_obtain(sta_semid_g, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
   STA_WriteRegister(STA_REG_BASS_FREQUENCY_HIGH, (freq&0xff00) >> 8);
   STA_WriteRegister(STA_REG_BASS_FREQUENCY_LOW, freq&0x00ff);
   rtems_semaphore_release(sta_semid_g);
   tone_controls_g.bass_freq = freq;
   return(0);
}


int
STA_SetBassEnhance(int v)
{
   if ((v > 12) || (v < -12))
      return(-1);

   tone_controls_g.bass_enhance = v;
   rtems_semaphore_obtain(sta_semid_g, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
   STA_WriteToneControls();
   rtems_semaphore_release(sta_semid_g);
   return(0);
}


int
STA_SetTrebleFrequency(unsigned short freq)
{
   rtems_semaphore_obtain(sta_semid_g, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
   STA_WriteRegister(STA_REG_TREBLE_FREQUENCY_HIGH, (freq&0xff00) >> 8);
   STA_WriteRegister(STA_REG_TREBLE_FREQUENCY_LOW, freq&0x00ff);
   rtems_semaphore_release(sta_semid_g);
   tone_controls_g.treble_freq = freq;
   return(0);
}


int
STA_SetTrebleEnhance(int v)
{
   if ((v > 12) || (v < -12))
      return(-1);

   tone_controls_g.treble_enhance = v;
   rtems_semaphore_obtain(sta_semid_g, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
   STA_WriteToneControls();
   rtems_semaphore_release(sta_semid_g);
   return(0);
}


int
STA_GetVolume()
{
   int v;

   rtems_semaphore_obtain(sta_semid_g, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
   STA_ReadToneControls();
   v = (int)tone_controls_g.volume_dla;
   rtems_semaphore_release(sta_semid_g);
   return(v);
}


int
STA_GetBassEnhance()
{
   int v;

   rtems_semaphore_obtain(sta_semid_g, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
   STA_ReadToneControls();
   rtems_semaphore_release(sta_semid_g);
   v = (int)tone_controls_g.bass_enhance;
   return(v);
}


int
STA_GetTrebleEnhance()
{
   int v;

   rtems_semaphore_obtain(sta_semid_g, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
   STA_ReadToneControls();
   rtems_semaphore_release(sta_semid_g);
   v = (int)tone_controls_g.treble_enhance;
   return(v);
}


int
STA_VolumeChange(int v)
{
   tone_controls_g.volume_dla = STA_ReadRegister(STA_REG_DLA);
   tone_controls_g.volume_dra = STA_ReadRegister(STA_REG_DRA);
   tone_controls_g.volume_dla = MIN(MAX(tone_controls_g.volume_dla - v,
                                        0), 96);
   tone_controls_g.volume_dra = MIN(MAX(tone_controls_g.volume_dra - v,
                                        0), 96);
   rtems_semaphore_obtain(sta_semid_g, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
   STA_WriteToneControls();
   rtems_semaphore_release(sta_semid_g);
   return(0);
}


int
STA_BassChange(int b)
{
   tone_controls_g.bass_enhance =
                   (int)((char)STA_ReadRegister(STA_REG_BASS_ENHANCE));
   tone_controls_g.bass_enhance = MIN(MAX(tone_controls_g.bass_enhance + b,
                                          -12), 12);
   rtems_semaphore_obtain(sta_semid_g, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
   STA_WriteToneControls();
   rtems_semaphore_release(sta_semid_g);
   return(0);
}


int
STA_TrebleChange(int t)
{
   tone_controls_g.treble_enhance =
                   (int)((char)STA_ReadRegister(STA_REG_TREBLE_ENHANCE));
   tone_controls_g.treble_enhance = MIN(MAX(tone_controls_g.treble_enhance + t,
                                          -12), 12);
   rtems_semaphore_obtain(sta_semid_g, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
   STA_WriteToneControls();
   rtems_semaphore_release(sta_semid_g);
   return(0);
}


int
STA_MuteToggle()
{
   int mute;

   rtems_semaphore_obtain(sta_semid_g, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
   mute = (int)STA_ReadRegister(STA_REG_MUTE);
   if (mute == 0)
      mute = 1;
   else
      mute = 0;
   STA_WriteRegister(STA_REG_MUTE, mute);
   rtems_semaphore_release(sta_semid_g);
   return(mute);
}


int
STA_SoftMuteToggle()
{
   rtems_semaphore_obtain(sta_semid_g, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
   rtems_semaphore_release(sta_semid_g);
   return(0);
}

