Advertisement
Guest User

Untitled

a guest
Jan 6th, 2018
160
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. /*
  2.  
  3.     XMega DMA DAC audio test program
  4.     Copyright (C) 2018 Nicholas W. Sayer
  5.  
  6.     This program is free software; you can redistribute it and/or modify
  7.     it under the terms of the GNU General Public License as published by
  8.     the Free Software Foundation; either version 2 of the License, or
  9.     (at your option) any later version.
  10.  
  11.     This program is distributed in the hope that it will be useful,
  12.     but WITHOUT ANY WARRANTY; without even the implied warranty of
  13.     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14.     GNU General Public License for more details.
  15.  
  16.     You should have received a copy of the GNU General Public License along
  17.     with this program; if not, write to the Free Software Foundation, Inc.,
  18.     51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  19.    
  20.   */
  21.  
  22. #define F_CPU (32000000UL)
  23.  
  24. #include <stdlib.h>  
  25. #include <stdio.h>  
  26. #include <string.h>
  27. #include <math.h>
  28. #include <avr/cpufunc.h>
  29. #include <avr/io.h>
  30. #include <avr/power.h>
  31. #include <avr/wdt.h>
  32. #include <avr/interrupt.h>
  33. #include <avr/pgmspace.h>
  34. #include <util/atomic.h>
  35.  
  36. #include "pff.h"
  37.  
  38. #define FILENAME "/AUDIO.RAW"
  39.  
  40. // double buffer for audio I/O.
  41. static volatile unsigned char audio_buf[2][512];
  42.  
  43. volatile unsigned long millis_cnt;
  44.  
  45. ISR(TCD5_OVF_vect) {
  46.     TCD5.INTFLAGS = TC5_OVFIF_bm; // ack
  47.     millis_cnt++;
  48. }
  49.  
  50. void __ATTR_NORETURN__ main(void) {
  51.  
  52.         // We have a 16 MHz crystal. Use the PLL to double that to 32 MHz.
  53.  
  54.         // Run the CPU at 32 MHz using the RC osc.
  55.         OSC.CTRL |= OSC_RC32MEN_bm;
  56.         while(!(OSC.STATUS & OSC_RC32MRDY_bm)) ; // wait for it.
  57.  
  58.         _PROTECTED_WRITE(CLK.CTRL, CLK_SCLKSEL_RC32M_gc); // switch to it
  59.         OSC.CTRL &= ~(OSC_RC2MEN_bm); // we're done with the 2 MHz osc.
  60.  
  61.         // Turn on the 32 kHz reference oscillator
  62.         OSC.XOSCCTRL = OSC_X32KLPM_bm | OSC_XOSCSEL_32KHz_gc;
  63.         OSC.CTRL |= OSC_XOSCEN_bm;
  64.         while(!(OSC.STATUS & OSC_XOSCRDY_bm)) ; // wait for it.
  65.  
  66.         // Set up the DFLL to discipline the 32 MHz RC oscillator from the crystal
  67.         OSC.DFLLCTRL = OSC_RC32MCREF_XOSC32K_gc;
  68.         DFLLRC32M.COMP1 = (unsigned char)(F_CPU / 1024);
  69.         DFLLRC32M.COMP2 = (unsigned char)((F_CPU / 1024) >> 8);
  70.         DFLLRC32M.CTRL = DFLL_ENABLE_bm;
  71.  
  72.         // Leave on only the parts of the chip we use.
  73.         PR.PRGEN = PR_XCL_bm | PR_RTC_bm;
  74.         PR.PRPA = PR_ADC_bm | PR_AC_bm;
  75.         PR.PRPC = PR_TWI_bm | PR_HIRES_bm;
  76.         PR.PRPD = PR_USART0_bm;
  77.  
  78.     PORTA.DIRCLR = 0xff; // everything is an input.
  79.     PORTA.PIN2CTRL = PORT_ISC_INPUT_DISABLE_gc; //... except that pin 2 is DAC output
  80.  
  81.     PORTC.OUTSET = _BV(4); // de-assert CD_CS - high
  82.     PORTC.DIRSET = _BV(4) | _BV(5) | _BV(7);
  83.     PORTC.PIN6CTRL = PORT_OPC_PULLUP_gc; // pull card output pin up
  84.  
  85.     // All of port D is output
  86.     PORTD.DIRSET = 0xff;
  87.     PORTD.OUTCLR = 0xff; // start all low.
  88.  
  89.     DACA.CTRLA = DAC_CH0EN_bm | DAC_ENABLE_bm;
  90.     DACA.CTRLB = DAC_CHSEL_SINGLE_gc | DAC_CH0TRIG_bm; // Trigger a conversion on event 0 - from the 8 kHz timer
  91.     DACA.CTRLC = DAC_REFSEL_AVCC_gc | DAC_LEFTADJ_bm; // lop off the low 4 bits of each sample
  92.     DACA.EVCTRL = DAC_EVSEL_0_gc; // trigger event 0
  93.  
  94.     EDMA.CTRL = EDMA_RESET_bm;
  95.     while(EDMA.CTRL & EDMA_RESET_bm); // wait for it
  96.  
  97.     // DMA is two double-buffered, standard channels.
  98.     EDMA.CTRL = EDMA_ENABLE_bm | EDMA_CHMODE_STD02_gc | EDMA_DBUFMODE_BUF0123_gc | EDMA_PRIMODE_RR0123_gc;
  99.  
  100.     EDMA.CH0.CTRLA = EDMA_CH_SINGLE_bm | EDMA_CH_BURSTLEN_bm; // single-shot, two byte burst
  101.     EDMA.CH0.CTRLB = 0; // no interrupts
  102.     EDMA.CH0.ADDRCTRL = EDMA_CH_RELOAD_TRANSACTION_gc | EDMA_CH_DIR_INC_gc;
  103.     EDMA.CH0.DESTADDRCTRL = EDMA_CH_RELOAD_BURST_gc | EDMA_CH_DIR_INC_gc;
  104.     EDMA.CH0.TRIGSRC = EDMA_CH_TRIGSRC_DACA_CH0_gc;
  105.     EDMA.CH0.DESTADDR = (unsigned int)&(DACA.CH0DATA);
  106.     EDMA.CH0.TRFCNT = sizeof(audio_buf[0]);
  107.     EDMA.CH0.ADDR = (unsigned int)&(audio_buf[0]);
  108.  
  109.     // Channel 2 is configured exactly the same way as channel 0, but with the 2nd memory buffer.
  110.     EDMA.CH2.CTRLA = EDMA_CH_SINGLE_bm | EDMA_CH_BURSTLEN_bm; // single-shot, two byte burst
  111.     EDMA.CH2.CTRLB = 0;
  112.     EDMA.CH2.ADDRCTRL = EDMA_CH_RELOAD_TRANSACTION_gc | EDMA_CH_DIR_INC_gc;
  113.     EDMA.CH2.DESTADDRCTRL = EDMA_CH_RELOAD_BURST_gc| EDMA_CH_DIR_INC_gc;
  114.     EDMA.CH2.TRIGSRC = EDMA_CH_TRIGSRC_DACA_CH0_gc;
  115.     EDMA.CH2.DESTADDR = (unsigned int)&(DACA.CH0DATA);
  116.     EDMA.CH2.TRFCNT = sizeof(audio_buf[1]);
  117.     EDMA.CH2.ADDR = (unsigned int)&(audio_buf[1]);
  118.  
  119.     // Event 0 is the overflow from TCC4, which will free-run at 8 kHz.
  120.     // The DAC will use that as its sample clock.
  121.     EVSYS.CH0MUX = EVSYS_CHMUX_TCC4_OVF_gc;
  122.         EVSYS.CH0CTRL = 0;
  123.  
  124.         // TCC4 is an 8 kHz clock for triggering DMA to the DAC for audio
  125.         // playback.
  126.         TCC4.CTRLA = TC45_CLKSEL_DIV8_gc; // 4 MHz timer clocking.
  127.         TCC4.CTRLB = 0;
  128.         TCC4.CTRLC = 0;
  129.         TCC4.CTRLD = 0;
  130.         TCC4.CTRLE = 0;
  131.         TCC4.INTCTRLA = 0;
  132.         TCC4.INTCTRLB = 0;
  133.         TCC4.PER = 499; // 8 kHz
  134.  
  135.     // TCC5 is unused
  136.  
  137.         // TCD5 generates 1 kHz output on OC5A. This is toggled on
  138.         // and off in software. As a side effect, it keeps a milli timer for the SD subsystem
  139.         TCD5.CTRLA = TC45_CLKSEL_DIV64_gc; // 500 kHz clocking
  140.         TCD5.CTRLB = TC45_WGMODE_FRQ_gc; // frequency generation mode
  141.         TCD5.CTRLC = 0;
  142.         TCD5.CTRLD = 0;
  143.         TCD5.CTRLE = TC45_CCAMODE_COMP_gc;
  144.         TCD5.INTCTRLA = TC45_OVFINTLVL_HI_gc;
  145.         TCD5.INTCTRLB = 0;
  146.         TCD5.CCA = 249; // toggle at 2 kHz -> output 1 kHz
  147.  
  148.     PMIC.CTRL = PMIC_LOLVLEN_bm | PMIC_MEDLVLEN_bm | PMIC_HILVLEN_bm;
  149.         sei();
  150.  
  151.     FATFS fatfs;
  152.  
  153.     FRESULT status;
  154.     if ((status = pf_mount(&fatfs))) goto fail;
  155.     if ((status = pf_open(FILENAME))) goto fail;
  156.  
  157.     unsigned char done = 0, first = 1, chan = 1;
  158.     do {
  159.         chan = !chan;
  160.         unsigned int cnt;
  161.         if ((status = pf_read((void*)(audio_buf[chan]), sizeof(audio_buf[chan]), &cnt))) goto fail;
  162.         (chan?&(EDMA.CH2):&(EDMA.CH0))->TRFCNT = cnt;
  163.         done = (cnt != sizeof(audio_buf[chan])); // last read?
  164.         if (!done) {
  165.             (chan?&(EDMA.CH2):&(EDMA.CH0))->CTRLA |= EDMA_CH_REPEAT_bm; // repeat
  166.         }
  167.         if (first) {
  168.             first = 0;
  169.             (chan?&(EDMA.CH2):&(EDMA.CH0))->CTRLA |= EDMA_CH_ENABLE_bm; // start
  170.             if (!done)
  171.                 continue; // don't wait for the first transfer
  172.         }
  173.         while(!(EDMA.INTFLAGS & (EDMA_CH0TRNFIF_bm | EDMA_CH2TRNFIF_bm))) ; // wait for complete
  174.         EDMA.INTFLAGS |= EDMA_CH0TRNFIF_bm | EDMA_CH2TRNFIF_bm; // ack
  175.     } while(!done);
  176.  
  177.     PORTD.OUT = _BV(0); // success
  178.     while(1);
  179. fail:
  180.     PORTD.OUT = (status << 5) | _BV(1);
  181.     while(1);
  182. }
Advertisement
Advertisement
Advertisement
RAW Paste Data Copied
Advertisement