roboforum.ruТехнический форум по робототехнике. |
|
|
/*---------------------------------------------------------------*/
/* 8-pin SD audio player R0.03 (C)ChaN, 2010 */
/*---------------------------------------------------------------*/
#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/sleep.h>
#include <avr/wdt.h>
#include <string.h>
#include "diskio.h"
#include "pff.h"
#ifndef MODE
#error Wrong make file.
#endif
#define FCC(c1,c2,c3,c4) (((DWORD)c4<<24)+((DWORD)c3<<16)+((WORD)c2<<8)+(BYTE)c1) /* FourCC */
/*---------------------------------------------------------*/
/* Work Area */
/*---------------------------------------------------------*/
volatile BYTE FifoRi, FifoWi, FifoCt; /* FIFO controls */
BYTE Buff[256]; /* Wave output FIFO */
FATFS fs; /* File system object */
DIR dir; /* Directory object */
FILINFO fno; /* File information */
WORD rb; /* Return value. Put this here to avoid bugs of avr-gcc */
EMPTY_INTERRUPT(WDT_vect);
/*---------------------------------------------------------*/
static
DWORD load_header (void) /* 0:Invalid format, 1:I/O error, >1:Number of samples */
{
DWORD fcc, sz;
UINT i;
FRESULT res;
res = pf_read(Buff, 256, &rb); /* Load file header (256 bytes) */
if (res) return 1;
if (rb != 256 || LD_DWORD(Buff+8) != FCC('W','A','V','E')) return 0;
i = 12;
while (i < 200) {
fcc = LD_DWORD(&Buff[i]); /* FCC */
sz = LD_DWORD(&Buff[i+4]); /* Chunk size */
i += 8;
switch (fcc) {
case FCC('f','m','t',' ') : /* 'fmt ' chunk */
if (sz > 100 || sz < 16) /* Check chunk size */
return 0;
if (Buff[i+0] != 1) /* Check coding type (1) */
return 0;
if (Buff[i+2] != 1 && Buff[i+2] != 2) /* Check channels (1/2) */
return 0;
GPIOR0 = Buff[i+2]; /* Channel flag */
if (Buff[i+14] != 8 && Buff[i+14] != 16) /* Check resolution (8/16) */
return 0;
GPIOR0 |= Buff[i+14]; /* Resolution flag */
OCR0A = (BYTE)(F_CPU / 8 / LD_WORD(&Buff[i+4])) - 1; /* Sampling freq */
break;
case FCC('f','a','c','t') : /* 'fact' chunk (skip) */
break;
case FCC('d','a','t','a') : /* 'data' chunk (start to play) */
fs.fptr = i;
return sz;
default : /* Unknown chunk (error) */
return 0;
}
i += sz;
}
return 0;
}
static
UINT play (
const char *fn
)
{
DWORD sz;
FRESULT res;
BYTE sw;
WORD btr;
if ((res = pf_open(fn)) == FR_OK) {
sz = load_header(); /* Load file header */
if (sz < 256) return (UINT)sz;
if (!TCCR1) { /* Enable audio out if not enabled */
PLLCSR = 0b00000110; /* Select PLL clock for TC1.ck */
GTCCR = 0b01100000; /* Enable TC1.OCB as PWM out (L-ch) */
OCR1B = 128; OCR1A = 128;
TCCR1 = MODE ? 0b01100001 : 0b00000001; /* Start TC1 with TC1.OCA is enabled as PWM out (R-ch) */
TCCR0A = 0b00000010; /* Enable TC0.ck = 2MHz as interval timer */
TCCR0B = 0b00000010;
TIMSK = _BV(OCIE0A);
}
FifoCt = 0; FifoRi = 0; FifoWi = 0; /* Reset FIFO */
pf_read(0, 512 - fs.fptr, &rb); /* Snip sector unaligned part */
sz -= rb;
sw = 1; /* Button status flag */
do {
/* Forward audio data */
btr = (sz > 1024) ? 1024 : (WORD)sz;
res = pf_read(0, btr, &rb);
if (res != FR_OK || btr != rb) break;
sz -= rb;
/* Check button down and break on button down */
sw <<= 1;
if (bit_is_clear(PINB, 0) && ++sw == 1) break;
wdt_reset();
} while (rb == 1024); /* Repeat until all data read */
}
while (FifoCt) ; /* Wait for FIFO empty */
OCR1A = 128; OCR1B = 128;
return res;
}
static
void delay500 (void)
{
TCCR1 = 0; GTCCR = 0; /* Stop TC1 */
TCCR0B = 0; TCCR0A = 0; /* Stop TC0 */
wdt_reset();
WDTCR = _BV(WDE) | _BV(WDIE) | 0b101; /* Enable WDT interrupt in timeout of 0.5s */
set_sleep_mode(SLEEP_MODE_PWR_DOWN); /* Enter power down mode */
sleep_mode();
WDTCR = _BV(WDE) | 0b110; /* Enable WDT reset in timeout of 1s */
}
/*-----------------------------------------------------------------------*/
/* Main */
int main (void)
{
MCUSR = 0;
WDTCR = _BV(WDE) | 0b110; /* Enable WDT reset in timeout of 1s */
PORTB = 0b111011; /* Initialize port: - - H H H L H P */
DDRB = 0b111110;
sei();
for (;;) {
delay500(); /* Delay 500ms in low power sleep mode */
if (pf_mount(&fs)) continue; /* Initialize FS */
for (;;) {
if (pf_opendir(&dir, "")) break; /* Open sound file directory (root dir) */
while (!pf_readdir(&dir, &fno) && fno.fname[0]) { /* Play all wav files in the dir */
if (!(fno.fattrib & (AM_DIR|AM_HID))
&& strstr(fno.fname, ".WAV")) {
if (play(fno.fname)) break;
}
}
}
}
}
Наверно вот:TrashVigor писал(а):А как там шим регулируется?
OCR0A = (BYTE)(F_CPU / 8 / LD_WORD(&Buff[i+4])) - 1; /* Sampling freq */
static
DWORD load_header (void) /* 0:Invalid format, 1:I/O error, >1:Number of samples */
res = pf_read(Buff, 256, &rb); /* Load file header (256 bytes) */
if (res) return 1;
if (rb != 256 || LD_DWORD(Buff+8) != FCC('W','A','V','E')) return 0;
case FCC('f','m','t',' ') : /* 'fmt ' chunk */
if (sz > 100 || sz < 16) /* Размер масива в пределах... */
return 0;
if (Buff[i+0] != 1) /* Check coding type (1) */
return 0;
if (Buff[i+2] != 1 && Buff[i+2] != 2) /*проверка моно или стерео */
return 0;
GPIOR0 = Buff[i+2]; /* Тут не понятно */
if (Buff[i+14] != 8 && Buff[i+14] != 16) /* 8 или 16 бит */
return 0;
GPIOR0 |= Buff[i+14]; /* опять не понятно */
OCR0A = (BYTE)(F_CPU / 8 / LD_WORD(&Buff[i+4])) - 1; /* Sampling freq */
break;
case FCC('f','a','c','t') : /* 'fact' chunk (skip) */
break;
case FCC('d','a','t','a') : /* 'data'стартуем проигрывать */
fs.fptr = i;
return sz;
static
void delay500 (void)
{
TCCR1 = 0; GTCCR = 0; /* Stop TC1 */
TCCR0B = 0; TCCR0A = 0; /* Stop TC0 */
wdt_reset();
WDTCR = _BV(WDE) | _BV(WDIE) | 0b101; /* Enable WDT interrupt in timeout of 0.5s */
set_sleep_mode(SLEEP_MODE_PWR_DOWN); /* Enter power down mode */
sleep_mode();
WDTCR = _BV(WDE) | 0b110; /* Enable WDT reset in timeout of 1s */
}
а в чем суть 250кгц? А если больше или меньше качество звука будет другое? Структура WAV-файлаОн обосновал свой выбор тем что у этих Тинь ШИМ 250 Кгц при нормальной битности-разрядности.
Вернуться в Электроника, электротехника
Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 33