// AudioColorizer.
// Pros 2010

#define F_CPU 16000000UL
#define UART

#ifndef PRG_RDB
#define PRG_RDB(x) pgm_read_byte(x)
#endif

#ifndef P
#define P(s) ({static const char c[] __attribute__ ((progmem)) = s;c;})
#endif

#include <avr/io.h>
#include <avr/pgmspace.h>
#include <avr/interrupt.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <util/delay.h>

#include "ffft.h"                                               // Defs for using Fixed-point FFT module
#ifdef UART
#include "UART.c"
#endif


int16_t                 capture[FFT_N];                         // Wave captureing buffer
complex_t               bfly_buff[FFT_N];                       // FFT buffer
uint16_t                spectrum[FFT_N / 2];                    // Spectrum output buffer
unsigned int            channel[4];
unsigned int            cntch;
int                     sampletmp;

int main(void)
{
    int16_t                *buffer;
#ifdef UART
    char                    txt[32];
    uint16_t                mnuart_flag = 0;
#endif

    ADCSRA = 0;
    ADMUX = _BV(REFS0);                                         // Ref = 5V; ADC0 = ingang
    TCCR0 = _BV(WGM00) | _BV(COM01) | _BV(CS00) | _BV(CS01);
    OCR0 = 128;
    DDRB = _BV(PB0) | _BV(PB1) | _BV(PB3);
    TCCR1A = _BV(COM1A1) | _BV(COM1B1) | _BV(WGM10);
    TCCR1B = _BV(CS10) | _BV(CS11);
    OCR1A = 128;
    OCR1B = 128;
    DDRD = _BV(PD4) | _BV(PD5) | _BV(PD7);
    TCCR2 = _BV(WGM20) | _BV(COM21) | _BV(CS22);
    OCR2 = 128;
    TCNT0 = 0;
    TCNT1 = 80;
    TCNT2 = 160;
#ifdef UART
    uart_init();
    sei();
#endif

    while (1) {
        PORTB |= _BV(PB0);
        buffer = capture;
        for (cnt = 0cnt < FFT_Ncnt++) {
            ADCSRA = _BV(ADEN) | _BV(ADSC) | _BV(ADATE) | _BV(ADIF) | _BV(ADPS2) | _BV(ADPS1);
            while (bit_is_clear(ADCSRAADIF));                 // Sampelen
            *buffer = ADC - 32768;
            buffer++;
        }
        ADCSRA = 0;
        PORTB |= _BV(PB1);
        fft_input(capturebfly_buff);                          // Bewerken
        fft_execute(bfly_buff);
        fft_output(bfly_buffspectrum);
        PORTB &= ~(_BV(PB0));

        sample = spectrum[2];
        if (spectrum[3] > sample) {                             // Voor elke groep
            sample = spectrum[3];                               // de hoogste waarde opzoeken
        }
        channel[0] = sample;

        sample = spectrum[4];
        for (n = 5n < 8n++) {
            if (spectrum[n] > sample) {
                sample = spectrum[n];
            }
        }
        channel[1] = sample;

        sample = spectrum[8];
        for (n = 9n < 16n++) {
            if (spectrum[n] > sample) {
                sample = spectrum[n];
            }
        }
        channel[2] = sample;

        sample = spectrum[17];
        for (n = 18n < 51n++) {
            if (spectrum[n] > sample) {
                sample = spectrum[n];
            }
        }
        channel[3] = sample;
#ifdef UART
        uart_flag = 0;
        if (uart_linecomplete != 0) {                           // RS232-input?
            if (strncmp(uart_outbuf"Who"3) == 0) {          // Wie heb ik aan de lijn?
                uart_sendstr_P("  AudioColorizer\n");
            } else {
                switch (uart_outbuf[0]) {
                case 'w':                                       // w: show waveform 
                    for (n = 0n < FFT_Nn++) {
                        sample = capture[n];
                        sample = (sample + 32768) / 10;
                        for (m = 0m < samplem++) {
                            uart_sendchar('*');
                        }
                        uart_sendchar('\n');
                    }
                    break;

                case 's':                                       // s: show spectrum
                    uart_flag = 1;
                    for (n = 2n < FFT_N / 2n++) {
                        sprintf(txt"%4u  "n);
                        uart_sendstr(txt);
                        for (m = 0m < spectrum[n]; m++) {
                            uart_sendchar('*');
                        }
                        uart_sendchar('\n');
                    }
                    for (n = 0n < 4n++) {
                        sprintf(txt"Ch[%u] =  "n);
                        uart_sendstr(txt);
                        for (m = 0m < channel[n]; m++) {
                            uart_sendchar('*');
                        }
                        uart_sendchar('\n');
                    }
                    uart_sendchar('\n');
                    break;

                default:                                        // Unknown command
                    uart_sendchar('?');
                    break;
                }
                uart_sendchar('\n');
            }
            uart_linecomplete = 0;
        }
#endif

        sample = channel[0];
        ch = 0;
        for (cnt = 1cnt < 4cnt++) {                         // channel met de hoogste waarde zoeken
            if (channel[cnt] > sample) {
                sample = channel[cnt];
                ch = cnt;
            }
        }
        channel[ch] = 250;                                      // Die zetten we op maximum

        sample = channel[0];
        ch = 0;
        for (cnt = 1cnt < 4cnt++) {                         // channel met de laagste waarde zoeken
            if (channel[cnt] < sample) {
                sample = channel[cnt];
                ch = cnt;
            }
        }
        channel[ch] = 1;                                        // Die zetten we op minimum


        if (channel[0] < 20) {
            channel[0] = 1;
        } else if (channel[0] > 150) {
            channel[0] = 253;
        }
        if (channel[1] < 20) {
            channel[1] = 1;
        } else if (channel[1] > 150) {
            channel[1] = 253;
        }
        if (channel[2] < 20) {
            channel[2] = 1;
        } else if (channel[2] > 150) {
            channel[2] = 253;
        }
        if (channel[3] < 20) {
            channel[3] = 1;
        } else if (channel[3] > 150) {
            channel[3] = 253;
        }
        channel[0] /= 4;                                        // Van de nieuwe waarde nemen we 1/4
        channel[0] += OCR0 * 3;                                 // Van de oude waarde 3/4
        OCR0 = channel[0] / 4;                                  // Uitmiddelen
        channel[1] /= 4;
        channel[1] += OCR1A * 3;
        OCR1A = channel[1] / 4;
        channel[2] /= 4;
        channel[2] += OCR1B * 3;
        OCR1B = channel[2] / 4;
        channel[3] /= 4;
        channel[3] += OCR2 * 3;
        OCR2 = channel[3] / 4;
#ifdef UART
        if (uart_flag != 0) {
            sprintf(txt"OCR0 =  %3u\n"OCR0);
            uart_sendstr(txt);
            sprintf(txt"OCR1A = %3u\n"OCR1A);
            uart_sendstr(txt);
            sprintf(txt"OCR1B =  %3u\n"OCR1B);
            uart_sendstr(txt);
            sprintf(txt"OCR2 =  %3u\n"OCR2);
            uart_sendstr(txt);
            uart_flag = 0;
        }
#endif
        PORTB &= ~(_BV(PB1));
    }
}