📄 vs1001k.c
字号:
* Feed the decoder until its buffer is full or we ran out of data. */ else { char *bp = 0; size_t consumed = 0; size_t available = 0; do { if(consumed >= available) { /* Commit previously consumed bytes. */ if(consumed) { NutSegBufReadCommit(consumed); consumed = 0; } /* All bytes consumed, request new. */ bp = NutSegBufReadRequest(&available); if(available == 0) { /* End of stream. */ vs_status = VS_STATUS_EOF; break; } } /* We have some data in the buffer, feed it. */ VsSdiPutByte(*bp); bp++; consumed++; /* Allow 32 bytes to be sent as long as DREQ is set, This includes the one in progress. */ if (bit_is_set(VS_DREQ_PIN, VS_DREQ_BIT)) j = 32; } while(j--); /* Finally re-enable the producer buffer. */ NutSegBufReadLast(consumed); } VsPlayerInterrupts(ief);}/*! * \brief Start playback. * * This routine will send the first MP3 data bytes to the * decoder, until it is completely filled. The data buffer * should have been filled before calling this routine. * * Decoder interrupts will be enabled. * * \return 0 on success, -1 otherwise. */int VsPlayerKick(void){ /* * Start feeding the decoder with data. */ VsPlayerInterrupts(0); vs_status = VS_STATUS_RUNNING; VsPlayerFeed(NULL); VsPlayerInterrupts(1); return 0;}/*! * \brief Stops the playback. * * This routine will stops the MP3 playback, VsPlayerKick() may be used * to resume the playback. * * \return 0 on success, -1 otherwise. */int VsPlayerStop(void){ u_char ief; ief = VsPlayerInterrupts(0); /* Check whether we need to stop at all to not overwrite other than running status */ if (vs_status == VS_STATUS_RUNNING) vs_status = VS_STATUS_STOPPED; VsPlayerInterrupts(ief); return 0;}/*! * \brief Sets up decoder internal buffer flushing. * * This routine will set up internal VS buffer flushing, * unless the buffer is already empty and starts the playback * if necessary. The internal VS buffer is flushed in VsPlayerFeed() * at the end of the stream. * * Decoder interrupts will be enabled. * * \return 0 on success, -1 otherwise. */int VsPlayerFlush(void){ VsPlayerInterrupts(0); /* Set up fluhing unless both buffers are empty. */ if (vs_status != VS_STATUS_EMPTY || NutSegBufUsed()) { if (vs_flush == 0) vs_flush = VS_FLUSH_BYTES; /* start the playback if necessary */ if (vs_status != VS_STATUS_RUNNING) VsPlayerKick(); } VsPlayerInterrupts(1); return 0;}/*! * \brief Initialize the VS1001 hardware interface. * * \return 0 on success, -1 otherwise. */int VsPlayerInit(void){ /* Disable decoder interrupts. */ VsPlayerInterrupts(0); /* Keep decoder in reset state. */ cbi(VS_RESET_PORT, VS_RESET_BIT); sbi(VS_RESET_DDR, VS_RESET_BIT); /* Set BSYNC output low. */ cbi(VS_BSYNC_PORT, VS_BSYNC_BIT); sbi(VS_BSYNC_DDR, VS_BSYNC_BIT); /* Set MP3 chip select output low. */ sbi(VS_XCS_PORT, VS_XCS_BIT); sbi(VS_XCS_DDR, VS_XCS_BIT); /* Set DREQ input with pullup. */ sbi(VS_DREQ_PORT, VS_DREQ_BIT); cbi(VS_DREQ_DDR, VS_DREQ_BIT); /* Init SPI Port. */ sbi(VS_SI_DDR, VS_SI_BIT); sbi(VS_SS_DDR, VS_SS_BIT); cbi(VS_SO_DDR, VS_SO_BIT); /* Set SCK output low. */ cbi(VS_SCK_PORT, VS_SCK_BIT); sbi(VS_SCK_DDR, VS_SCK_BIT);#ifndef VS_NOSPI { u_char dummy; /* Required by some compilers. */ /* * Init SPI mode to no interrupts, enabled, MSB first, master mode, * rising clock and fosc/4 clock speed. Send an initial zero byte to * make sure SPIF is set. Note, that the decoder reset line is still * active. */ outp(BV(MSTR) | BV(SPE), SPCR); dummy = inp(SPSR); outp(0, SPDR); }#endif /* Rising edge will generate interrupts. */ sbi(EICR, 5); sbi(EICR, 4); /* Register the interrupt routine */ NutRegisterIrqHandler(&sig_INTERRUPT6, VsPlayerFeed, NULL); /* Release decoder reset line. */ sbi(VS_RESET_PORT, VS_RESET_BIT); NutDelay(4); /* Force frequency change (see datasheet). */ VsRegWrite(VS_CLOCKF_REG, 0x9800); VsRegWrite(VS_INT_FCTLH_REG, 0x8008); NutDelay(200); /* Clear any spurious interrupt. */ outp(BV(VS_DREQ_BIT), EIFR); return 0;}/*! * \brief Software reset the decoder. * * This function is typically called after VsPlayerInit() and at the end * of each track. * * \param mode Any of the following flags may be or'ed * - VS_SM_DIFF Left channel inverted. * - VS_SM_FFWD Fast forward. * - VS_SM_RESET Force hardware reset. * - VS_SM_PDOWN Switch to power down mode. * - VS_SM_BASS Bass/treble enhancer. * * \return 0 on success, -1 otherwise. */int VsPlayerReset(u_short mode){ /* Disable decoder interrupts and feeding. */ VsPlayerInterrupts(0); vs_status = VS_STATUS_STOPPED; /* Software reset, set modes of decoder. */ VsRegWrite(VS_MODE_REG, VS_SM_RESET | mode); NutDelay(2); /* * Check for correct reset. */ if ((mode & VS_SM_RESET) != 0 || bit_is_clear(VS_DREQ_PIN, VS_DREQ_BIT)) { /* If not succeeded, give it one more chance and try hw reset, HW reset may also be forced by VS_SM_RESET mode bit. */ cbi(VS_RESET_PORT, VS_RESET_BIT); _NOP(); sbi(VS_RESET_PORT, VS_RESET_BIT); NutDelay(4); /* Set the requested modes. */ VsRegWrite(VS_MODE_REG, VS_SM_RESET | mode); NutDelay(2); if (bit_is_clear(VS_DREQ_PIN, VS_DREQ_BIT)) return -1; } /* Force frequency change (see datasheet). */ VsRegWrite(VS_CLOCKF_REG, 0x9800); VsRegWrite(VS_INT_FCTLH_REG, 0x8008); NutDelay(2); /* Clear any spurious interrupts. */ outp(BV(VS_DREQ_BIT), EIFR); return 0;}/*! * \brief Set mode register of the decoder. * * \param mode Any of the following flags may be or'ed * - VS_SM_DIFF Left channel inverted. * - VS_SM_FFWD Fast forward. * - VS_SM_RESET Software reset. * - VS_SM_PDOWN Switch to power down mode. * - VS_SM_BASS Bass/treble enhancer. * * \return 0 on success, -1 otherwise. */int VsPlayerSetMode(u_short mode){ u_char ief; ief = VsPlayerInterrupts(0); VsRegWrite(VS_MODE_REG, mode); VsPlayerInterrupts(ief); return 0;}/*! * \brief Returns play time since last reset. * * \return Play time since reset in seconds */u_short VsPlayTime(void){ u_short rc; u_char ief; ief = VsPlayerInterrupts(0); rc = VsRegRead(VS_DECODE_TIME_REG); VsPlayerInterrupts(ief); return rc;}/*! * \brief Returns status of the player. * * \return Any of the following value: * - VS_STATUS_STOPPED Player is ready to be started by VsPlayerKick(). * - VS_STATUS_RUNNING Player is running. * - VS_STATUS_EOF Player has reached the end of a stream after VsPlayerFlush() has been called. * - VS_STATUS_EMPTY Player runs out of data. VsPlayerKick() will restart it. */u_char VsGetStatus(void){ return vs_status;}#ifdef __GNUC__/*! * \brief Query MP3 stream header information. * * \param vshi Pointer to VS_HEADERINFO structure. * * \return 0 on success, -1 otherwise. */int VsGetHeaderInfo(VS_HEADERINFO * vshi){ u_short *usp = (u_short *) vshi; u_char ief; ief = VsPlayerInterrupts(0); *usp = VsRegRead(VS_HDAT1_REG); *++usp = VsRegRead(VS_HDAT0_REG); VsPlayerInterrupts(ief); return 0;}#endif/*! * \brief Initialize decoder memory test and return result. * * \return Memory test result. * - Bit 0: Good X ROM * - Bit 1: Good Y ROM (high) * - Bit 2: Good Y ROM (low) * - Bit 3: Good Y RAM * - Bit 4: Good X RAM * - Bit 5: Good Instruction RAM (high) * - Bit 6: Good Instruction RAM (low) */u_short VsMemoryTest(void){ u_short rc; u_char ief; static prog_char mtcmd[] = { 0x4D, 0xEA, 0x6D, 0x54, 0x00, 0x00, 0x00, 0x00 }; ief = VsPlayerInterrupts(0); VsSdiWrite_P(mtcmd, sizeof(mtcmd)); NutDelay(40); rc = VsRegRead(VS_HDAT0_REG); VsPlayerInterrupts(ief); return rc;}/*! * \brief Set volume. * * \param left Left channel volume. * \param right Right channel volume. * * \return 0 on success, -1 otherwise. */int VsSetVolume(u_char left, u_char right){ u_char ief; ief = VsPlayerInterrupts(0); VsRegWrite(VS_VOL_REG, (((u_short) left) << 8) | (u_short) right); VsPlayerInterrupts(ief); return 0;}/*! * \brief Sine wave beep. * * \param fsin Frequency. * \param ms Duration. * * \return 0 on success, -1 otherwise. */int VsBeep(u_char fsin, u_char ms){ u_char ief; static prog_char on[] = { 0x53, 0xEF, 0x6E }; static prog_char off[] = { 0x45, 0x78, 0x69, 0x74 }; static prog_char end[] = { 0x00, 0x00, 0x00, 0x00 }; /* Disable decoder interrupts. */ ief = VsPlayerInterrupts(0); fsin = 56 + (fsin & 7) * 9; VsSdiWrite_P(on, sizeof(on)); VsSdiWrite(&fsin, 1); VsSdiWrite_P(end, sizeof(end)); NutDelay(ms); VsSdiWrite_P(off, sizeof(off)); VsSdiWrite_P(end, sizeof(end)); /* Enable decoder interrupts. */ VsPlayerInterrupts(ief); return 0;}/*@}*/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -