#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>

#include "ringbuf_small.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 */
	OCR1B = 0x66;
	cnt_to_next = 1;/* overflows to next sample */
	
	TCCR1A = (1 << COM1B1) | (1 << PWM1B);/* pwm enable, not inverted */
	TCCR1B = (1 << CS11);/* fast pwm, prescaler / 2 */
	DDRB |= (1 << PB3);
	
	TIMSK = 1 << TOIE1;/* interrupt on overflow */
}

#define BUFFER_SIZE 32
uint16_t buffer[BUFFER_SIZE];/* buffer for mmc data */
ringbuf_t rb;
uint32_t length;/* remaining samples */

/*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 0x3f,r2"); // restore sreg
    reti();
}// */

ISR(TIMER1_OVF1_vect){
    // next try: simplistic, not too much looking at speed
    uint16_t next = 0;

//    OCR1B += 1; // test pwm
    if(!--cnt_to_next){
        ringbuf_get(&rb, &next);
        OCR1B = next>>8;
        cnt_to_ocr_incr = 8 - (next & 0x7);
        cnt_to_next = 8;
/*        if(!--length)
        {
        	// shut down
        	PORTA &= ~(1 << PA7);
        }*/
    } else {
        if(!--cnt_to_ocr_incr){
           OCR1B += 1;
        }
    }
    
}


int main(void) __attribute__((noreturn));
int main(void)
{
    _delay_ms(30); // wait for card to get power
    uint8_t debug=0;
	DDRA |= (1 << PA7);
	PORTA |= (1 << PA7);
	ringbuf_init(&rb, buffer, BUFFER_SIZE);
    debug = 1;
//    while(debug){
    	debug=mmc_init();
//    }
    debug = 2-debug;
    char_to_sound(25);
	
    debug = mmc_read_part(1, (unsigned char *) &length, 4);
    debug = 1;
    if(length==0){
        debug = 2;
    }
    char_to_sound((length>>24) & 0xff);
    mmc_read_part(0, (unsigned char *) &length, 4);
    char_to_sound((length>>8) & 0xff);

	
	timer_init_tiny26();
	sei();
	
/*    
	unsigned long block = 0;
	for(;; block++)
	{
		//mmc_read_to_ringbuffer(block, &rb);
		mmc_read_to_ringbuffer(0, &rb);
	} // */
//    debug = 0;



}

void char_to_sound(uint8_t val){
    uint8_t i,r,b, sound;
    uint16_t a,to;
    for(b=0; b<8; b++){
        if(val & 0x80){
            sound = 16;
        }else{
            sound = 8;
        }
        val <<= 1;
        for(to=0; to<3200; to++){
            i += sound;
            a = i<<8;
            r=1;
            while(r){
                r=ringbuf_put(&rb, a);
            }
        }
        for(to=0; to<800; to++){
            r=1;
            while(r){
                r=ringbuf_put(&rb, 0);
            }
        }
    }
}
