/* Copyright (C) 2011 DJ Delorie This file is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. This file is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this file; see the file COPYING3. If not see . */ #include #include "iodefine.h" #include "ivects.h" #include "tty.h" #include "cprintf.h" #include "timer.h" #include "sdram.h" #include "usb.h" #include "critsec.h" #define BUFFER_SIZE 512 #define USE_DAC 1 #define USE_USB 0 #define LED0 PORT2.DR.BIT.B5 #define LED1 PORT2.DR.BIT.B4 #define LED2 PORT2.DR.BIT.B3 #define LED3 PORT2.DR.BIT.B2 #define LED4 PORT2.DR.BIT.B1 /*--------------------------------------------------------------*/ /* Generic Buffer Functions */ typedef struct { uint16_t left; uint16_t right; } BufferEntry[BUFFER_SIZE]; typedef struct { int get_ptr, put_ptr; volatile int count; volatile BufferEntry data; } Buffer; static inline void buffer_put (Buffer *b, uint16_t left, uint16_t right) { int psw; int i = b->put_ptr; b->put_ptr = (b->put_ptr + 1) % BUFFER_SIZE; ENTER_CRITICAL_SECTION (psw); b->count ++; LEAVE_CRITICAL_SECTION (psw); b->data[i].left = left; b->data[i].right = right; } static inline void buffer_get (Buffer *b, uint16_t *left, uint16_t *right) { int psw; int i = b->get_ptr; b->get_ptr = (b->get_ptr + 1) % BUFFER_SIZE; ENTER_CRITICAL_SECTION (psw); b->count --; LEAVE_CRITICAL_SECTION (psw); *left = b->data[i].left; *right = b->data[i].right; } static inline int buffer_full (Buffer *b) { return b->count == BUFFER_SIZE; } static inline int buffer_empty (Buffer *b) { return b->count == 0; } Buffer adc_buffer; #if USE_DAC Buffer dac_buffer; #endif /*--------------------------------------------------------------*/ /* LED Functions */ volatile int adc_left_led; volatile int adc_right_led; volatile int dac_left_led; volatile int dac_right_led; volatile int max_adc_left = 0; volatile int max_adc_right = 0; volatile int max_dac_left = 0; volatile int max_dac_right = 0; volatile int col = 0; unsigned char ledvals[256]; static int __attribute__((inline)) max_to_led (int m) { m >>= 8; m -= 128; if (m < 0) m = 0; m <<= 1; if ((m & 0xfc) == 0) m = 0x80; return m; } static void __attribute__((interrupt)) led_handler () { col ++; PORT4.DR.BYTE = 0; switch (col & 3) { case 0: PORT4.DR.BYTE = adc_left_led; PORT9.DR.BYTE = 1; break; case 1: PORT4.DR.BYTE = adc_right_led; PORT9.DR.BYTE = 2; break; case 2: PORT4.DR.BYTE = dac_left_led; PORT9.DR.BYTE = 4; break; case 3: PORT4.DR.BYTE = dac_right_led; PORT9.DR.BYTE = 8; break; } if (col > 0x40) { col &= 0x3f; #define LL(l,m) l = ledvals[m>>8]; m = 0 LL (adc_left_led, max_adc_left); LL (adc_right_led, max_adc_right); LL (dac_left_led, max_dac_left); LL (dac_right_led, max_dac_right); } } static void led_init () { int i; for (i=0; i<256; i++) ledvals[i] = max_to_led (i<<8); PORT9.DDR.BYTE |= 0x0f; PORT4.DDR.BYTE |= 0xfc; MSTP(MTU0) = 0; _vectors[VECT(MTU3,TGIA3)] = led_handler; IEN(MTU3,TGIA3) = 1; IPR(MTU3,TGIA3) = 6; MTU3.TCR.BYTE = 0x20; /* TGRA, PCLK/1 = 48 MHz */ MTU3.TIER.BYTE = 0x01; /* interrupt on TGRA */ MTU3.TGRA = 48000; /* should be 1 KHz */ MTUA.TSTR.BIT.CST3 = 1; /* start timer */ } /*--------------------------------------------------------------*/ /* ADC Functions */ static int p6 = 0; /* H AN7 YINPUT2 G AN6 XINPUT2 <-- right F AN5 YINPUT1 E AN4 XINPUT1 <-- left */ static void __attribute__((interrupt)) adc_handler (void) { uint16_t left, right; left = S12AD.ADDRA; right = S12AD.ADDRB; if (!buffer_full (&adc_buffer)) { buffer_put (&adc_buffer, left, right); LED2 = 0; LED3 = 1; } else { LED2 = 1; LED3 = 0; } if (max_adc_left < left) max_adc_left = left; if (max_adc_right < right) max_adc_right = right; } void adc_init (void) { PORT4.DDR.BYTE = 0; PORT4.ICR.BYTE = ~0; MSTP(S12AD) = 0; S12AD.ADANS.WORD = 0x0003; /* scan channels 0 and 1 */ S12AD.ADADS.WORD = 0x0003; S12AD.ADADC.BYTE = 3; S12AD.ADCSR.BYTE = 0x1e; S12AD.ADCER.BIT.ADRFMT = 1; /* left aligned data */ S12AD.ADSTRGR.BYTE = 0x3; /* TRGAN_0 */ _vectors[VECT(S12AD,ADI)] = adc_handler; IEN(S12AD,ADI) = 1; IPR(S12AD,ADI) = 6; MSTP(MTU0) = 0; MTU1.TCR.BYTE = 0x20; /* TGRA, PCLK/1 = 48 MHz */ MTU1.TIER.BIT.TTGE = 1; /* ADC trigger enabled */ MTU1.TGRA = 1088; /* should be 44100 KHz */ } void adc_start (void) { MTUA.TSTR.BIT.CST1 = 1; /* start timer */ } void adc_stop (void) { MTUA.TSTR.BIT.CST1 = 0; /* start timer */ } void adc_rate (int samples_per_second) { MTU1.TGRA = 48000000 / samples_per_second; } /*--------------------------------------------------------------*/ /* DAC Functions */ #if USE_DAC static void __attribute__((interrupt)) mtu2_handler () { uint16_t left, right; if (! buffer_empty (&dac_buffer)) { buffer_get (&dac_buffer, &left, &right); DA.DADR0 = left; DA.DADR1 = right; if (max_dac_left < left) max_dac_left = left; if (max_dac_right < right) max_dac_right = right; } } void dac_init (void) { MSTP(DA) = 0; DA.DACR.BYTE = 0xe0; DA.DADPR.BYTE = 0x80; /* left-aligned */ PORT0.DDR.BIT.B3 = 1; PORT0.DDR.BIT.B5 = 1; MSTP(MTU0) = 0; _vectors[VECT(MTU2,TGIA2)] = mtu2_handler; IEN(MTU2,TGIA2) = 1; IPR(MTU2,TGIA2) = 5; MTU2.TCR.BYTE = 0x20; /* TGRA, PCLK/1 = 48 MHz */ MTU2.TIER.BYTE = 0x01; /* interrupt on TGRA */ MTU2.TGRA = 1088; /* should be 44100 KHz */ MTUA.TSTR.BIT.CST2 = 1; /* start timer */ } void dac_rate (int samples_per_second) { MTU2.TGRA = 48000000 / samples_per_second; } #endif /*--------------------------------------------------------------*/ int main(void) { int min, max; unsigned long last_print = 0; unsigned long last_led = 0; SYSTEM.SCKCR.LONG = 0x00010100; PORT2.DDR.BYTE = 0xff; LED0 = LED1 = LED2 = LED3 = 0; PORT6.DDR.BYTE = ~0; PORT6.DR.BYTE = 4; timer_init (); tty_init (); tty_puts("\nOGG TEST\n"); sram_init (); #if USE_USB tty_puts ("hit a key..."); while (tty_getc () == 3) ; tty_puts("\n"); usb_init (); while (!usb_connected) ; tty_puts("\n"); #endif #if USE_DAC dac_init (); dac_rate (44100); #endif adc_init (); adc_rate (44100); adc_start (); led_init (); while (1) { uint16_t left, right; if (adc_buffer.count > 1) { unsigned char sample[4]; buffer_get (&adc_buffer, &left, &right); #if USE_DAC buffer_put (&dac_buffer, left, right); #endif if (min > left) min = left; if (max < left) max = left; #if 0 left -= 0x8000; right -= 0x8000; #endif #if USE_USB sample[0] = left & 0xff; sample[1] = left >> 8; sample[2] = right & 0xff; sample[3] = right >> 8; usb_write (sample, 4); #endif } if (tty_idle () && (int)(timer_ms - last_print) > 300) { cprintf(" %w.%w", left, right); cprintf(" %w-%w %w", min, max, 0x1234); cprintf(" %w", MTU1.TCNT); cprintf(" %w.%w \r", adc_buffer.count, dac_buffer.count); min = 0x10000; max = -0x10000; last_print = timer_ms; } } }