+
+/*==============================================================================
+ * NXT Sound API
+ *=============================================================================*/
+
+/**
+ * play a tone(wrapper of leJOS sound tone api)
+ *
+ * @param freq: soundfrequency in Hz (31 to 2100)
+ * @param ms: sound duration in centisecond (10 - 256)
+ * @vol: sound volume (0 to 100)
+ * @return 1 (always)
+ */
+SINT ecrobot_sound_tone(U32 freq, U32 ms, U32 vol)
+{
+ sound_freq_vol(freq, ms, vol);
+ return 1;
+}
+
+/**
+ * play a WAV file (support for only 8bit monoral PCM)
+ *
+ * @param file: WAV file data
+ * NOTE that supports only 8bit monoral PCM
+ * @param length: length of WAV file
+ * @param freq: sampling frequency -1(inherit the WAV file original)/2000 to 22050Hz
+ * @param vol: sound volume(0 to 100)
+ * @return: 1(success)/0(sound resource is busy)/-1(failure)
+ */
+SINT ecrobot_sound_wav(const CHAR *file, U32 length, S32 freq, U32 vol)
+{
+ WAV *wav = (WAV *)file;
+
+ /* check sound resource is free */
+ if (sound_get_time() > 0)
+ return 0;
+
+ /* check length of a file */
+ if (length < WAV_HDR_SIZE)
+ return -1;
+
+ /* check a WAV file header information */
+ if (wav->riff.chunkID != RIFF_CHUNK_ID)
+ return -1;
+ if (wav->riff.format != RIFF_FORMAT)
+ return -1;
+ if (wav->fmt.chunkID != FMT_CHUNK_ID)
+ return -1;
+ if (wav->fmt.audioFormat != 0x0001) /* PCM */
+ return -1;
+ if (wav->fmt.numChannels != 0x0001) /* mono channel */
+ return -1;
+ if (wav->fmt.bitsPerSample != 0x0008) /* 8bit */
+ return -1;
+
+ /* in case of freq < 0, freq(sample rate) is inherited from a WAV file */
+ if (freq < 0)
+ {
+ freq = wav->fmt.sampleRate;
+ }
+
+ /* read wav data. Currently, supported PCM file types are
+ * linear PCM(data chunkID is "data" and "fact") and non-linear PCM.
+ */
+ if (wav->data.chunkID == DATA_CHUNK_ID)
+ {
+ /* linear PCM */
+ sound_play_sample(wav->data.data, wav->data.chunkSize, (U32)freq, vol);
+ }
+ else
+ {
+ WAV_FACT *wav_fact = (WAV_FACT *)file;
+ if (wav_fact->data.chunkID == FACT_CHUNK_ID && wav_fact->data.data_chunkID == DATA_CHUNK_ID)
+ {
+ /* linear PCM with "fact" chunk ID */
+ sound_play_sample(wav_fact->data.data, wav_fact->data.data_chunkSize, (U32)freq, vol);
+ }
+ else
+ {
+ WAV_NL *wav_nl = (WAV_NL *)file;
+ if (wav_nl->data.chunkID == DATA_CHUNK_ID)
+ {
+ /* non linear PCM */
+ sound_play_sample(wav_nl->data.data, wav_nl->data.chunkSize, (U32)freq, vol);
+ }
+ else
+ {
+ return -1;
+ }
+ }
+ }
+ return 1;
+}
+
+
+/*==============================================================================
+ * NXT USB API
+ *=============================================================================*/
+static U8 usb_reset_flag = 0;
+
+/**
+ * reset USB.
+ * This API can be invoked in either ecrobot_device_initialize
+ * and run-time application
+ */
+void ecrobot_init_usb(void)
+{
+ /* invoked in ecrobot_device_initialize */
+ if(!get_OS_flag())
+ {
+ /* invoked only for the first time */
+ if (deviceStatus == DEVICE_NO_INIT)
+ {
+ udp_reset();
+ usb_reset_flag = 1;
+ add_status_info(USB_INITIALIZED);
+ }
+ }
+ /* invoked in run-time application */
+ else
+ {
+ udp_reset();
+ usb_reset_flag = 1;
+ }
+}
+
+/**
+ * read USB data from host
+ *
+ * @param buf: buffer to return data
+ * @param len: length of the return data
+ * @return: 1(success)/0(failure)
+ */
+SINT ecrobot_read_usb(U8 *buf, U32 len)
+{
+ if (usb_reset_flag != 1)
+ return 0;
+
+ if (len > MAX_USB_DATA_SIZE)
+ return 0;
+
+ return udp_read(buf, len);
+}
+
+/**
+ * send USB data to host
+ *
+ * @param buf: buffer containing data to send
+ * @param len: length of the data to send
+ * @return: 1(success)/0(failure)
+ */
+SINT ecrobot_send_usb(U8 *buf, U32 len)
+{
+ if (usb_reset_flag != 1)
+ return 0;
+
+ if (len > MAX_USB_DATA_SIZE)
+ return 0;
+
+ udp_write(buf, len);
+ return len;
+}
+
+/**
+ * close a USB connection. (currently it's just reset the flag)
+ */
+void ecrobot_term_usb(void)
+{
+ usb_reset_flag = 0;
+ udp_close(0);
+}