📄 vs1001k.c
字号:
* \return 0 on success, -1 otherwise. */int VsPlayerStop(void){ cbi(EIMSK, VS_DREQ_BIT); /* 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; sbi(EIMSK, VS_DREQ_BIT); 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. * * \return 0 on success, -1 otherwise. */int VsPlayerFlush(void){ cbi(EIMSK, VS_DREQ_BIT); /* Set up fluhing unless both buffers are empty. */ if (vs_status != VS_STATUS_EMPTY || vs_readptr != vs_writeptr) { if (vs_flush == 0) vs_flush = VS_FLUSH_BYTES; /* start the playback if necessary */ if (vs_status != VS_STATUS_RUNNING) VsPlayerKick(); } sbi(EIMSK, VS_DREQ_BIT); return 0;}/*! * \brief Initialize the VS1001 hardware interface. * * \return 0 on success, -1 otherwise. */int VsPlayerInit(void){ /* Disable decoder interrupts. */ cbi(EIMSK, VS_DREQ_BIT); /* 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 and enable decoder interrupts. */ outp(BV(VS_DREQ_BIT), EIFR); sbi(EIMSK, VS_DREQ_BIT); 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. */ cbi(EIMSK, VS_DREQ_BIT); 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 interrupt and enable decoder interrupts. */ outp(BV(VS_DREQ_BIT), EIFR); sbi(EIMSK, VS_DREQ_BIT); 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){ cbi(EIMSK, VS_DREQ_BIT); VsRegWrite(VS_MODE_REG, mode); sbi(EIMSK, VS_DREQ_BIT); return 0;}/*! * \brief Initialize the MP3 data buffer. * * \param size Number of bytes to allocate for the data buffer. * Should be at least 4k. If this parameter is 0, * all available memory minus 8k are allocated. * * \return Pointer to the data buffer or null on failures. */u_char *VsBufferInit(u_short size){ if (size == 0) size = NutHeapAvailable() - 8192; if ((vs_databuff = NutHeapAlloc(size)) != 0) vs_dataend = vs_databuff + size; vs_readptr = vs_writeptr = vs_databuff; return vs_writeptr;}/*! * \brief Reset all MP3 data buffer pointers. * * \return Pointer to the data buffer. */u_char *VsBufferReset(void){ cbi(EIMSK, VS_DREQ_BIT); vs_readptr = vs_writeptr = vs_databuff; sbi(EIMSK, VS_DREQ_BIT); return vs_databuff;}/*! * \brief Request MP3 data buffer space. * * \param sizep Pointer to an unsigned short, which receives the * number of bytes available in the buffer. * * \return Pointer to the next write position. */u_char *VsBufferRequest(u_short * sizep){ cbi(EIMSK, VS_DREQ_BIT); if (vs_writeptr >= vs_readptr) *sizep = vs_dataend - vs_writeptr - (vs_readptr == vs_databuff); else *sizep = vs_readptr - vs_writeptr - 1; sbi(EIMSK, VS_DREQ_BIT); return vs_writeptr;}/*! * \brief Acknowledge filled buffer space. * * \return Pointer to the next write position. */u_char *VsBufferAcknowledge(u_short nbytes){ cbi(EIMSK, VS_DREQ_BIT); vs_writeptr += nbytes; if (vs_writeptr == vs_dataend) vs_writeptr = vs_databuff; /* Cancel flushing in progress. */ vs_flush = 0; sbi(EIMSK, VS_DREQ_BIT); return vs_writeptr;}/*! * \brief Returns total free buffer space. * * \return Total number of free bytes in the buffer. */u_short VsBufferAvailable(void){ u_short avail; cbi(EIMSK, VS_DREQ_BIT); if (vs_writeptr >= vs_readptr) avail = (vs_dataend - vs_databuff) - (vs_writeptr - vs_readptr); else avail = (vs_readptr - vs_writeptr) - 1; sbi(EIMSK, VS_DREQ_BIT); return avail;}/*! * \brief Returns play time since last reset. * * \return Play time since reset in seconds */u_short VsPlayTime(void){ u_short rc; cbi(EIMSK, VS_DREQ_BIT); rc = VsRegRead(VS_DECODE_TIME_REG); sbi(EIMSK, VS_DREQ_BIT); 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; cbi(EIMSK, VS_DREQ_BIT); *usp = VsRegRead(VS_HDAT1_REG); *++usp = VsRegRead(VS_HDAT0_REG); sbi(EIMSK, VS_DREQ_BIT); 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; static prog_char mtcmd[] = { 0x4D, 0xEA, 0x6D, 0x54, 0x00, 0x00, 0x00, 0x00 }; cbi(EIMSK, VS_DREQ_BIT); VsSdiWrite_P(mtcmd, sizeof(mtcmd)); NutDelay(40); rc = VsRegRead(VS_HDAT0_REG); sbi(EIMSK, VS_DREQ_BIT); 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){ cbi(EIMSK, VS_DREQ_BIT); VsRegWrite(VS_VOL_REG, (((u_short) left) << 8) | (u_short) right); sbi(EIMSK, VS_DREQ_BIT); 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){ 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. */ cbi(EIMSK, VS_DREQ_BIT); 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. */ sbi(EIMSK, VS_DREQ_BIT); return 0;}/*@}*/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -