//Author HiSER (c)2010 #include #include #define Q_FREQ 8000000 #define CS_PIN PORTB.2 #asm #define SD_DI 0x18,1 #define SD_DO 0x16,4 #define SD_CLK 0x18,5 #endasm typedef unsigned char byte; typedef unsigned int word; typedef unsigned long ulong; byte buff[256]; word pbuff=0; byte udbuff=0; ulong wavesize; ulong lba=0; byte ch=0; byte sdi=0; interrupt [TIM1_CAPT] void timer1_capt_isr(void) { if (pbuff==0||pbuff==128) udbuff=1; #asm push r26 push r27 push r25 clr r25 ldi r26,low(_buff) ldi r27,high(_buff) add r26,_pbuff adc r27,r25 ld r25,X out 0x23,r25 pop r25 pop r27 pop r26 inc _pbuff #endasm } byte spi(byte v) { #asm ld r30,Y push r22 ldi r22,8 __next_bit: sbrc r30,7 sbi SD_DI sbrs r30,7 cbi SD_DI sbi SD_CLK lsl r30 sbic SD_DO sbr r30,1 cbi SD_CLK dec r22 brne __next_bit pop r22 #endasm } byte sd_init() { byte i; CS_PIN=1; delay_ms(5); for (i=0;i<10;i++) spi(0xff); CS_PIN=0; delay_ms(5); spi(0x40); spi(0); spi(0); spi(0); spi(0); spi(0x95); spi(0xff); if (spi(0xff)!=1) return 0; i=0; do { spi(0x41); spi(0); spi(0); spi(0); spi(0); spi(0xff); spi(0xff); delay_us(10); i++; if (i==0) return 0; } while (spi(0xff)!=0); spi(0x50); spi(0); spi(0); spi(2); spi(0); spi(0xff); spi(0xff); spi(0xff); return 1; } byte sd_read() { word i=0; spi(0x51); spi((byte)(lba>>24)); spi((byte)(lba>>16)); spi((byte)(lba>>8)); spi((byte)lba); spi(0xff); spi(0xff); if (spi(0xff)!=0) return 0; while (spi(0xff)!=0xfe&&i<255) i++; if (i==255) return 0; return 1; } byte play() { word i; lba=0; sdi=sd_read(); if (sdi==0) return 0; for (i=0;i<128;i++) buff[i]=spi(0xff); pbuff=44; ch=1; udbuff=1; lba+=512; if (buff[20]!=1&&buff[21]!=0) return 0; wavesize=buff[24]; wavesize|=(ulong)buff[25]<<8; wavesize|=(ulong)buff[26]<<16; wavesize|=(ulong)buff[27]<<24; if (wavesize<8000||wavesize>48000) { return 0; }else{ wavesize=Q_FREQ/wavesize; ICR1H=(byte)(wavesize>>8); ICR1L=(byte)wavesize; } wavesize=buff[40]; wavesize|=(ulong)buff[41]<<8; wavesize|=(ulong)buff[42]<<16; wavesize|=(ulong)buff[43]<<24; wavesize-=84; TCNT1H=0; TCNT1L=0; TCCR1A=0; TCCR1B=0x19; TCNT2=0; return 1; } void stop() { TCCR1A=0; TCCR1B=0; OCR2=0x80; } void playlooping() { word i; if (udbuff!=0&&sdi!=0) { if (wavesize>127) wavesize-=128; else wavesize=0; if (wavesize==0) { stop(); play(); return; } if (pbuff<128) { for (i=128;i<256;i++) buff[i]=spi(0xff); }else{ for (i=0;i<128;i++) buff[i]=spi(0xff); } udbuff=0; ch++; if (ch==4) { spi(0xff); spi(0xff); lba+=512; sdi=sd_read(); ch=0; } } } void avr_init() { PORTB=0x10; DDRB=0x2e; TCCR1A=0; TCCR1B=0; TCNT1H=0; TCNT1L=0; ICR1H=0; ICR1L=0; ASSR=0x00; TCCR2=0x69; TCNT2=0x00; OCR2=0x80; TIMSK=0x20; } void main(void) { avr_init(); #asm("sei") while (1) { if (sdi==0) { stop(); sdi=sd_init(); if (sdi!=0) sdi=play(); }else{ playlooping(); } } }