# include <avr/io.h>
# include <util/delay.h>
# include <avr/interrupt.h>
# include "ringbuf_small.c"
# include "mmc.h"
# include "gg.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, ISR_NAKED)
{
__asm__ ( " in r2, 0x3f " ) ; // save sreg
if ( - - cnt_to_ocr_incr ) {
OCR1A = cur_ocr + 1 ;
}
if ( - - cnt_to_next ) {
cur_ocr = next_ocr ;
OCR1A = cur_ocr ;
cnt_to_ocr_incr = next_cnt_to_incr ;
cnt_to_next = 8 ;
needs_new_data_flag = 1 ;
}
__asm__ ( " out 0x2f,r2 " ) ; // restore sreg
reti ( ) ;
} //*/
ISR ( TIMER1_OVF1_vect ) {
// next try: simplistic, not too much looking at speed
uint16_t next ;
if ( - - cnt_to_next ) {
next = ringbuf_get ( ringbuf ) ;
OCR1A = next > > 8 ;
cnt_to_ocr_incr = 7 - ( next & 0x7 ) ;
cnt_to_next = 7 ;
} else {
if ( - - cnt_to_ocr_incr ) {
OCR1A + = 1 ;
}
}
}
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 ;
}
}
}