Guest User

Untitled

a guest
Jan 6th, 2018
148
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. }
RAW Paste Data

Adblocker detected! Please consider disabling it...

We've detected AdBlock Plus or some other adblocking software preventing Pastebin.com from fully loading.

We don't have any obnoxious sound, or popup ads, we actively block these annoying types of ads!

Please add Pastebin.com to your ad blocker whitelist or disable your adblocking software.

×