Соответственно переписал вот такой код:
Спойлер
Код: Выделить всё
; Read and forward a partial data block
;
; void fwd_blk_part (void*, WORD, WORD);
.global fwd_blk_part
.func fwd_blk_part
fwd_blk_part:
movw XL, r24 ;X = R25:R24 (memory address)
movw ZL, r22 ;Z = R23:R22 (byte offset in the sector)
ldi r18, lo8(514) ;R19:R18 = 514, Number of bytes to receive
ldi r19, hi8(514) ;/
sub r18, ZL ;R19:R18 -= Z
sbc r19, ZH ;/
sub r18, r20 ;R19:R18 -= R21:R20
sbc r19, r21 ;/
; Skip leading data bytes
ldi r24, 0b000100 ;PB2(SCK)
1: sbiw ZL, 1 ;Skip leading data...
brcs 2f ;
.rept 16 ;Discard a byte on SPI
out _SFR_IO_ADDR(PINB), r24 ;
.endr ;/
rjmp 1b ;
2: sbiw XL, 0 ;Destination?
breq fb_wave
fb_mem: ; Store intermediate data bytes to the memory
rcall rcv_spi ;do
st X+, r24 ; *X++ = rcv_spi()
subi r20, 1 ;while (--r21:r20)
sbci r21, 0 ;
brne fb_mem ;/
rjmp fb_exit
fb_wave: ; Forward intermediate data bytes to the wave FIFO
sbic _FLAGS, 4 ;if (16bit data) R21:R20 /= 2;
lsr r21 ;
sbic _FLAGS, 4 ;
ror r20 ;/
sbic _FLAGS, 1 ;if (Stereo data) R21:R20 /= 2;
lsr r21 ;
sbic _FLAGS, 1 ;
ror r20 ;/
lds r22, FifoWi ;r22 = FIFO write index
3: ldi XL, lo8(Buff) ;X = Buff + R22
ldi XH, hi8(Buff) ;
add XL, r22 ;
adc XH, r1 ;/
4: lds r24, FifoCt ;wait while FIFO full
cpi r24, 252 ;
brcc 4b ;/
#if MODE >= 1 // Dual output
#if MODE == 2 // Hi-Res
rcall rcv_spi ;Get L-ch/Mono data into Z
clr ZL ;
sbis _FLAGS, 4 ;
rjmp 6f ;
mov ZL, r24 ;
rcall rcv_spi ;
subi r24, 0x80 ;
6: mov ZH, r24 ;/
sbis _FLAGS, 1 ;if Mono data, do not process R-ch data
rjmp 8f ;/
rcall rcv_spi ;Get R-ch data and mix it to Z
clr r25 ;
sbis _FLAGS, 4 ;
rjmp 7f ;
mov r25, r24 ;
rcall rcv_spi ;
subi r24, 0x80 ;
7: add ZL, r25 ;
adc ZH, r24 ;
ror ZH ;
ror ZL ;/
#else // Stereo
sbic _FLAGS, 4 ;Get L-ch/Mono data into ZH, ZL
rcall rcv_spi ;
rcall rcv_spi ;
sbic _FLAGS, 4 ;
subi r24, 0x80 ;
mov ZL, r24 ;
mov ZH, r24 ;/
sbis _FLAGS, 1 ;if Mono data, do not process R-ch data
rjmp 8f ;/
sbic _FLAGS, 4 ;Get R-ch data into ZL
rcall rcv_spi ;
rcall rcv_spi ;
sbic _FLAGS, 4 ;
subi r24, 0x80 ;
mov ZL, r24 ;/
#endif
8: st X+, ZL ;Store Z into FIFO
st X+, ZH ;/
cli ;
lds r24, FifoCt ;
subi r24, -2 ;
sts FifoCt, r24 ;
sei ;
subi r22, -2 ;/
#else // Single output
sbic _FLAGS, 4 ;Get L-ch/Mono data into ZL
rcall rcv_spi ;
rcall rcv_spi ;
sbic _FLAGS, 4 ;
subi r24, 0x80 ;
mov ZL, r24 ;/
sbis _FLAGS, 1 ;if Mono data, do not process R-ch data
rjmp 8f ;/
sbic _FLAGS, 4 ;Get R-ch data
rcall rcv_spi ;
rcall rcv_spi ;
sbic _FLAGS, 4 ;
subi r24, 0x80 ;/
add ZL, r24 ;ZL = (ZL + R-ch) / 2
ror ZL ;/
8: st X+, ZL ;Store ZL into FIFO
cli ;
lds r24, FifoCt ;
inc r24 ;
sts FifoCt, r24 ;
sei ;
inc r22 ;/
#endif
subi r20, lo8(1) ;while(--R21:R20)
sbci r21, hi8(1) ;
brne 3b ;/
sts FifoWi, r22 ;Save FIFO write index
fb_exit:
ldi r24, 0b000100 ;PB2(SCK)
9: .rept 16 ;Discard a byte on SPI
out _SFR_IO_ADDR(PINB), r24 ;
.endr ;/
subi r18, lo8(1) ;Repeat r19:r18 times
sbci r19, hi8(1) ;
brne 9b ;/
ret
.endfunc
;---------------------------------------------------------------------------;
; Read and forward the data block
;
; ISR(TIM0_COMPA_vect);
.global TIM0_COMPA_vect
.func TIM0_COMPA_vect
TIM0_COMPA_vect:
push r24 ;Save regs.
in r24, _SFR_IO_ADDR(SREG) ;
push r24 ;
push ZL ;
push ZH ;/
lds ZL, FifoRi ;Get FIFO read index
clr ZH ;Z = pointer to the top of FIFO
subi ZL, lo8(-(Buff)) ;
sbci ZH, hi8(-(Buff)) ;/
lds r24, FifoCt ;Load FIFO data counter
#if MODE >= 1 // Dual output
subi r24, 2 ;Check availability of the sampling data
brcs 9f ;/
sts FifoCt, r24 ;Save FIFO data counter
ld r24, Z+ ;Get R-ch/LSB data and send it to PWM
out _SFR_IO_ADDR(OCR1A), r24 ;/
ld r24, Z+ ;Get L-ch/MSB data and send it to PWM
out _SFR_IO_ADDR(OCR1B), r24 ;/
#else // Single output
subi r24, 1 ;Check availability of the sampling data
brcs 9f ;/
sts FifoCt, r24 ;Save FIFO data counter
ld r24, Z+ ;Send data to PWM
out _SFR_IO_ADDR(OCR1B), r24 ;/
#endif
subi ZL, lo8(Buff) ;Save FIFO read index
sts FifoRi, ZL ;/
9: pop ZH ;Restore regs.
pop ZL ;
pop r24 ;
out _SFR_IO_ADDR(SREG), r24 ;
pop r24 ;/
reti
.endfuncСпойлер
Код: Выделить всё
interrupt [TIM1_COMPA] void timer1_compa_isr(void){
if(CB_Ct > 1){
CB_Ct -= 1;
OCR0A = CB[CB_Ri++];
}
}
char CardType;
extern volatile BYTE CB_Ri, CB_Wi, CB_Ct;
#define MODE 0
#define mono 0
void fwd_blk_part(BYTE *dest, WORD offset, WORD count){
//Байты, которые останутся после заполнения
//предложенного буфера, но всё равно будут выдаваться картой, так как размер
//выдаваемых данных кратен 512 байтам
int skip_counter = 514 - offset - count;
char res = 0;
BYTE CB_Wi_buf = CB_Wi;
//BYTE CB_Wi_buf = 0;
BYTE recv_byte;
BYTE buff_byte;
//Пропускаем такое количество байт, чтобы начать считывать
//начиная с указанного смещения
while(offset--){
res = spi_send(0xFF);
}
//Если указали буфер, в который надо считать данные, то считываем
//указанное от смещения количество байт данных в буфер
if(dest != NULL){
do{
*dest++ = spi_send(0xFF);
} while(--count);
}
else{
//Считываем данные в кольцевой буфер для проигрывания
#ifdef 16_bit
count /= 2;
#else
#ifdef stereo
count /= 2;
#endif
#endif
dest += CB_Wi_buf;
do{
while(CB_Ct < 252); // Ждем, пока буффер заполнится полностью
#if MODE >= 1 //Вывод на 2 динамика
#if MODE == 2 //HI-RES
#else //STEREO
#endif
#else //Вывод на 1 динамик
recv_byte = spi_send(0xFF);
#ifdef 16_bit
recv_byte = spi_send(0xFF);
recv_byte -= 0x80;
#endif
buff_byte = recv_byte;
#ifndef mono
recv_byte = spi_send(0xFF);
#ifdef 16_bit
recv_byte = spi_send(0xFF);
recv_byte -= 0x80;
#endif
buff_byte = (buff_byte + recv_byte) / 2;
#endif
*dest++ = buff_byte;
#asm("cli");
CB_Ct++;
#asm("sei");
CB_Wi_buf++;
#endif
} while (--count);
CB_Wi = CB_Wi_buf;
}
//Пропускаем количество байт, оставшиеся непрочитанными в блоке
spi_send_cycle(0xFF, skip_counter);
}
Подрубаем 16 МГц внешний кварц.
Запускаем 0-й счетчик с частотой 16 МГц (без делителя), в режиме FastPWM. Это тот режим когда устанавливаются все 3 бита WGM00:02
Получается что счетчик считает от 0 до указанного в регистре OCR0A значения. Это наша несущая.
Дальше делим 1-й счетчик на 8 - получаем 2 МГц, что дает примерно 8 кГц период выборки. С такой частотой надо доставать новый байт из буфера и отправлять его на проигрывание в регистр OCR0A 0-го счетчика.
Соответственно кольцевой буфер заполняется переписанной мною с ассемблера на СИ функцией fwd_blk_part.
На практике МК заводится, сигналит по UART компу, что карточка инициализирована нормально, что начал читать блоки от 1.WAV файла и потом тишина. Звук быть должен достаточно громкий, чтобы его услышать (знаю так как собирал схему автора на этих же элементах, кроме МК).
Помогите найти ошибку в коде или в логике. Спасибо.

