voicecontread2.c 2.8 KB
/*---------------------------------------------------------------------
 	Copyright (C) 1997,1998 Nintendo.
 	
 	File		miccontread2.c
 	Coded    by	Koji Mitsunari.	Apr 22, 1998.
 	Modified by	Koji Mitsunari.	Jun 22, 1998.
 	Comments	Voice Recognition Board
   
 	$Id: voicecontread2.c,v 1.1.1.1 2002/05/02 03:28:44 blythe Exp $
   ---------------------------------------------------------------------*/
/**************************************************************************
 *
 *  $Revision: 1.1.1.1 $
 *  $Date: 2002/05/02 03:28:44 $
 *  $Source: 
 *
 **************************************************************************/

#include "osint.h"
#include "controller.h"
#include "siint.h"

#define	VOICE_DATA_SIZE	2

s32
__osVoiceContRead2(OSMesgQueue *mq, int channel, u16 address, u8 *buffer)
{
  s32	ret = 0;
  u8	status;
  int	i;
  u8	*ptr;
  int	retry = 2;

  /* Block to get resource token */
  __osSiGetAccess();

  do { 	/* Retry if ADRS/DATA CRC error */
    ptr = (u8 *)(&__osPfsPifRam);

    if (__osContLastCmd != CONT_VOICE_READ2
	|| __osPfsLastChannel != channel) {
      __osContLastCmd = CONT_VOICE_READ2;
      __osPfsLastChannel = channel;
      
      /* Set up request command format for all channels */
      for (i = 0; i < channel; i++) *ptr++ = 0;

      /* set format flag */
      __osPfsPifRam.pifstatus = CONT_FORMAT;

      /* Setup ram read format */
      ((__OSVoiceRead2Format *)ptr)->dummy = 0xff;
      ((__OSVoiceRead2Format *)ptr)->txsize = 3;
      ((__OSVoiceRead2Format *)ptr)->rxsize = VOICE_DATA_SIZE+1;
      ((__OSVoiceRead2Format *)ptr)->cmd = CONT_VOICE_READ2;
      ((__OSVoiceRead2Format *)ptr)->datacrc = 0xff;

      /* setup ram read format */
      ptr[sizeof(__OSVoiceRead2Format)] = FORMAT_END;
    } else {
      ptr += channel;
    }
    ((__OSVoiceRead2Format *)ptr)->addrh = (u8)(address >>3);
    ((__OSVoiceRead2Format *)ptr)->addrl =
      (u8)( (address << 5) | __osContAddressCrc(address)) ;

    ret = __osSiRawStartDma(OS_WRITE, &__osPfsPifRam);
    (void)osRecvMesg(mq, (OSMesg *)NULL, OS_MESG_BLOCK);

    /* trigger pifmacro */
    ret = __osSiRawStartDma(OS_READ, &__osPfsPifRam);
    (void)osRecvMesg(mq, (OSMesg *)NULL, OS_MESG_BLOCK);

    ret = (s32)((((__OSVoiceRead2Format *)ptr)->rxsize & CON_ERR_MASK) >> 4);
    if (ret == 0) {
      /* check data CRC */
      if (__osVoiceContDataCrc(((__OSVoiceRead2Format *)ptr)->data,
			     VOICE_DATA_SIZE) !=
	  ((__OSVoiceRead2Format *)ptr)->datacrc) {
	      
	/* reset status */
	if ((ret = __osVoiceGetStatus(mq, channel, &status)) != 0){
	  break;
	} else {
	  ret = CONT_ERR_CONTRFAIL;
	}
      } else {
	bcopy(((__OSVoiceRead2Format *)ptr)->data, buffer, VOICE_DATA_SIZE);
      }
    } else {
      ret = CONT_ERR_NO_CONTROLLER;
    }
  } while ((ret == CONT_ERR_CONTRFAIL) && (retry-- >= 0));

  __osSiRelAccess();
  return(ret);
}