voicecontwrite20.c 2.57 KB
/*---------------------------------------------------------------------
 	Copyright (C) 1998, Nintendo.
 	
 	File		miccontwrite20.c
 	Coded    by	Koji Mitsunari.	Apr 25, 1998.
 	Modified by	Koji Mitsunari.	Jun 22, 1998.
 	Comments	Voice Recognition Board
   
 	$Id: voicecontwrite20.c,v 1.1.1.1 2002/05/02 03:28:44 blythe Exp $
   ---------------------------------------------------------------------*/

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

#define	VOICE_DATA_SIZE	20

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

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

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

    if (__osContLastCmd != CONT_VOICE_WRITE20 || __osPfsLastChannel != channel) {
      __osContLastCmd = CONT_VOICE_WRITE20;
      __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 */
      ((__OSVoiceWrite20Format *)ptr)->dummy = 0xff;
      ((__OSVoiceWrite20Format *)ptr)->txsize = VOICE_DATA_SIZE+3;
      ((__OSVoiceWrite20Format *)ptr)->rxsize = 1;
      ((__OSVoiceWrite20Format *)ptr)->cmd = CONT_VOICE_WRITE20;
      ((__OSVoiceWrite20Format *)ptr)->datacrc = 0xff;

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

    bcopy(buffer, ((__OSVoiceWrite20Format *)ptr)->data, VOICE_DATA_SIZE);
        
    ret = __osSiRawStartDma(OS_WRITE, &__osPfsPifRam);
    crc = __osVoiceContDataCrc(buffer, VOICE_DATA_SIZE);
    (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)((((__OSVoiceWrite20Format *)ptr)->rxsize & CON_ERR_MASK) >> 4);
    if (ret == 0) {
      /* check data CRC */
      if (crc != ((__OSVoiceWrite20Format *)ptr)->datacrc) {
	/* reset status */
	if ((ret = __osVoiceGetStatus(mq, channel, &status)) != 0){
	  break;
	} else {
	  ret = CONT_ERR_CONTRFAIL;
	}
      }
    } else {
      ret = CONT_ERR_NO_CONTROLLER;
    }
  } while ((ret == CONT_ERR_CONTRFAIL) && (retry-- >= 0));

  __osSiRelAccess();
  return(ret);
}