# include <avr/io.h>
# include <util/delay.h>
# include <avr/interrupt.h>
# include "mmc.h"
void timer_init_tiny26 ( void )
{
PLLCSR = 1 < < PLLE ; /* pll enable */
_delay_us ( 100 ) ;
while ( ! ( PLLCSR & ( 1 < < PLOCK ) ) ) { ; } /* wait for lock */
PLLCSR | = 1 < < PCKE ; /* use pll */
OCR1C = 0xff ; /* unused */
/* output pin: OC1A = PB1 = 1 or OC1B = PB3 = 2 */
OCR1A = 0 ;
TCCR1A = ( 1 < < COM1A1 ) | ( 1 < < PWM1A ) ; /* pwm enable, not inverted */
TCCR1B = ( 1 < < CS10 ) ; /* fast pwm, no prescaler */
DDRB | = ( 1 < < PB1 ) ;
TIMSK = 1 < < TOIE1 ; /* interrupt on overflow */
}
uint8_t length [ 4 ] ; /* remaining samples */
uint32_t mmc_position ; /* current reading position on mmc */
uint8_t overflows = 1 ; /* remaining counter overflows until next sample */
# define SAMPLE_BITS 11
# define BUFFER_SIZE 64
# define REFRESH_AMOUNT 32
# define REFRESH_SIZE (BUFFER_SIZE - REFRESH_AMOUNT)
uint8_t buffer [ BUFFER_SIZE ] ; /* buffer for mmc data */
uint8_t pos = 0 ; /* current playing position */
uint8_t refresh_buffer = 0 ; /* position to start buffer refreshing */
ISR ( TIMER1_OVF1_vect )
{
//if(!(TIFR & (1 << TOV1))) {continue;}/* interrupt flag polling */
//TIFR |= (1 << TOV1);/* done by hardware */
overflows - - ;
if ( ! overflows )
{
overflows = 1 < < ( SAMPLE_BITS - 8 ) ;
pos = ( pos + 1 ) % BUFFER_SIZE ;
}
/* TODO: a-law decoding */
/* TODO: 11bit PWM emulation */
OCR1A = buffer [ pos ] ; /* play sample */
}
int main ( void ) __attribute__ ( ( noreturn ) ) ;
int main ( void )
{
uint8_t ref ; // TODO: what does this do?
if ( mmc_init ( ) ! = 0 ) { /* mmc fail */ ; }
timer_init_tiny26 ( ) ;
sei ( ) ;
for ( ; ; )
{
if ( pos = = refresh_buffer ) /* refresh buffer if running low */
{
/* TODO: this won't do. we don't have enough time to read unnecessary bytes -> read data with the same speed as we consume it, keeping a small buffer. */
/* expect 2 bit read from mmc between 2 timer interrupts --> 2 byte read per sample played */
mmc_read_sector ( mmc_position , buffer + ( ref + REFRESH_SIZE ) % BUFFER_SIZE ) ; //, BUFFER_SIZE - ref), buffer, REFRESH_AMOUNT - (BUFFER_SIZE - ref));
/* pos on sd , first buffer address , 1st buffer size ,2nd buf, 2nd buffer size */
refresh_buffer = ( refresh_buffer + REFRESH_AMOUNT ) % BUFFER_SIZE ;
}
}
}