mirror of https://github.com/EspoTek/Labrador.git
678 lines
28 KiB
C
678 lines
28 KiB
C
/*
|
|
* tiny_dma.c
|
|
*
|
|
* Created: 25/06/2015 9:00:42 AM
|
|
* Author: Esposch
|
|
*/
|
|
|
|
#include "tiny_dma.h"
|
|
#include "tiny_adc.h"
|
|
#include "tiny_uart.h"
|
|
#include "tiny_calibration.h"
|
|
#include "globals.h"
|
|
#include "util/delay.h"
|
|
|
|
#ifndef SINGLE_ENDPOINT_INTERFACE
|
|
#define DMA_STANDARD_INTERRUPT (0x00)
|
|
#define DMA_STANDARD_CTRLA (DMA_CH_BURSTLEN_1BYTE_gc | DMA_CH_SINGLE_bm | DMA_CH_REPEAT_bm)
|
|
#define DMA_STANDARD_TRANSFER_LENGTH (PACKET_SIZE)
|
|
#else
|
|
#define DMA_STANDARD_INTERRUPT (0x03)
|
|
#define DMA_STANDARD_CTRLA (DMA_CH_BURSTLEN_1BYTE_gc | DMA_CH_SINGLE_bm)
|
|
#define DMA_STANDARD_TRANSFER_LENGTH (HALFPACKET_SIZE)
|
|
#endif
|
|
|
|
void tiny_dma_setup(void){
|
|
//Turn on DMA
|
|
PR.PRGEN &=0b111111110; //Turn on DMA clk
|
|
#ifndef SINGLE_ENDPOINT_INTERFACE
|
|
DMA.CTRL = DMA_ENABLE_bm | DMA_PRIMODE_CH0123_gc;
|
|
#else
|
|
DMA.CTRL = DMA_ENABLE_bm | DMA_PRIMODE_RR0123_gc;
|
|
#warning "Round Robin on DMA"
|
|
#endif
|
|
|
|
}
|
|
void tiny_dma_flush(void){
|
|
DMA.CH0.CTRLA = 0x00;
|
|
DMA.CH0.CTRLA = DMA_CH_RESET_bm;
|
|
|
|
DMA.CH1.CTRLA = 0x00;
|
|
DMA.CH1.CTRLA = DMA_CH_RESET_bm;
|
|
|
|
DMA.CH2.CTRLA = 0x00;
|
|
DMA.CH2.CTRLA = DMA_CH_RESET_bm;
|
|
|
|
DMA.CH3.CTRLA = 0x00;
|
|
DMA.CH3.CTRLA = DMA_CH_RESET_bm;
|
|
|
|
b1_state = 0;
|
|
b2_state = 0;
|
|
usb_state = 0;
|
|
|
|
dma_ch0_ran = 0;
|
|
dma_ch1_ran = 0;
|
|
}
|
|
void tiny_dma_delayed_set(unsigned char mode){
|
|
futureMode = mode;
|
|
modeChanged = 1;
|
|
}
|
|
void tiny_dma_set_mode_0(void){
|
|
|
|
global_mode = 0;
|
|
|
|
tiny_dma_flush();
|
|
|
|
DMA.CH2.REPCNT = 0; //Repeat forever!
|
|
DMA.CH2.CTRLA = DMA_CH_BURSTLEN_1BYTE_gc | DMA_CH_SINGLE_bm | DMA_CH_REPEAT_bm;
|
|
DMA.CH2.CTRLB = 0x00; //No interrupt for DacBuf!!
|
|
DMA.CH2.ADDRCTRL = DMA_CH_DESTRELOAD_BURST_gc | DMA_CH_DESTDIR_INC_gc | DMA_CH_SRCRELOAD_BLOCK_gc | DMA_CH_SRCDIR_INC_gc; //Dest reloads after each burst, with byte incrementing. Src reloads at end of block, also incrementing address.
|
|
DMA.CH2.TRIGSRC = DMA_CH_TRIGSRC_EVSYS_CH1_gc; //Triggered from TCC0 when it hits PER
|
|
DMA.CH2.TRFCNT = auxDacBufLen;
|
|
|
|
DMA.CH2.SRCADDR0 = (( (uint16_t) &dacBuf_CH2[0]) >> 0) & 0xFF; //Source address is dacbuf
|
|
DMA.CH2.SRCADDR1 = (( (uint16_t) &dacBuf_CH2[0]) >> 8) & 0xFF;
|
|
DMA.CH2.SRCADDR2 = 0x00;
|
|
|
|
DMA.CH2.DESTADDR0 = (( (uint16_t) &DACB.CH1DATAH) >> 0) & 0xFF; //Dest address is high byte of DAC register
|
|
DMA.CH2.DESTADDR1 = (( (uint16_t) &DACB.CH1DATAH) >> 8) & 0xFF;
|
|
DMA.CH2.DESTADDR2 = 0x00;
|
|
|
|
//Must enable last for REPCNT won't work!
|
|
DMA.CH2.CTRLA |= DMA_CH_ENABLE_bm; //Enable!
|
|
|
|
DMA.CH3.REPCNT = 0; //Repeat forever!
|
|
DMA.CH3.CTRLA = DMA_CH_BURSTLEN_1BYTE_gc | DMA_CH_SINGLE_bm | DMA_CH_REPEAT_bm;
|
|
DMA.CH3.CTRLB = 0x00; //Hi interrupt on block complete
|
|
DMA.CH3.ADDRCTRL = DMA_CH_DESTRELOAD_BURST_gc | DMA_CH_DESTDIR_INC_gc | DMA_CH_SRCRELOAD_BLOCK_gc | DMA_CH_SRCDIR_INC_gc; //Dest reloads after each burst, with byte incrementing. Src reloads at end of block, also incrementing address.
|
|
DMA.CH3.TRIGSRC = DMA_CH_TRIGSRC_EVSYS_CH2_gc; //Triggered from TCC0 when it hits PER
|
|
DMA.CH3.TRFCNT = dacBuf_len;
|
|
|
|
DMA.CH3.SRCADDR0 = (( (uint16_t) &dacBuf_CH1[0]) >> 0) & 0xFF; //Source address is dacbuf
|
|
DMA.CH3.SRCADDR1 = (( (uint16_t) &dacBuf_CH1[0]) >> 8) & 0xFF;
|
|
DMA.CH3.SRCADDR2 = 0x00;
|
|
|
|
DMA.CH3.DESTADDR0 = (( (uint16_t) &DACB.CH0DATAH) >> 0) & 0xFF; //Dest address is high byte of DAC register
|
|
DMA.CH3.DESTADDR1 = (( (uint16_t) &DACB.CH0DATAH) >> 8) & 0xFF;
|
|
DMA.CH3.DESTADDR2 = 0x00;
|
|
|
|
//Must enable last for REPCNT won't work!
|
|
DMA.CH3.CTRLA |= DMA_CH_ENABLE_bm; //Enable!
|
|
|
|
DMA.CH0.CTRLA = 0x00;
|
|
DMA.CH0.CTRLA = DMA_CH_RESET_bm;
|
|
|
|
DMA.CH0.CTRLA = DMA_STANDARD_CTRLA;
|
|
DMA.CH0.CTRLB = DMA_STANDARD_INTERRUPT;
|
|
DMA.CH0.ADDRCTRL = DMA_CH_SRCRELOAD_BURST_gc | DMA_CH_SRCDIR_INC_gc | DMA_CH_DESTDIR_INC_gc | DMA_CH_DESTRELOAD_BLOCK_gc; //Source reloads after each burst, with byte incrementing. Dest does not reload, but does increment address.
|
|
DMA.CH0.TRIGSRC = DMA_CH_TRIGSRC_ADCA_CH0_gc; //Triggered from ADCA channel 0
|
|
DMA.CH0.TRFCNT = DMA_STANDARD_TRANSFER_LENGTH;
|
|
|
|
DMA.CH0.SRCADDR0 = (( (uint16_t) &ADCA.CH0.RESL) >> 0) & 0xFF; //Source address is ADC
|
|
DMA.CH0.SRCADDR1 = (( (uint16_t) &ADCA.CH0.RESL) >> 8) & 0xFF;
|
|
DMA.CH0.SRCADDR2 = 0x00;
|
|
|
|
DMA.CH0.DESTADDR0 = (( (uint16_t) &isoBuf[0]) >> 0) & 0xFF; //Dest address is isoBuf
|
|
DMA.CH0.DESTADDR1 = (( (uint16_t) &isoBuf[0]) >> 8) & 0xFF;
|
|
DMA.CH0.DESTADDR2 = 0x00;
|
|
|
|
tiny_calibration_synchronise_phase(500, 200);
|
|
median_TRFCNT = 200;
|
|
median_TRFCNT_delay = 1; //Wait a few frames before actually setting median_TRFCNT, in case a SOF interrupt was queued during tiny_dma_set_mode_xxx.
|
|
DMA.CH0.CTRLA |= DMA_CH_ENABLE_bm; //Enable!
|
|
|
|
}
|
|
|
|
void tiny_dma_loop_mode_0(void){
|
|
return;
|
|
}
|
|
|
|
void tiny_dma_set_mode_1(void){
|
|
global_mode = 1;
|
|
|
|
tiny_dma_flush();
|
|
|
|
//AUX channel (to keep it tx, therefore always rx)
|
|
DMA.CH2.CTRLA = 0x00;
|
|
DMA.CH2.CTRLA = DMA_CH_RESET_bm;
|
|
|
|
DMA.CH2.CTRLA = DMA_CH_BURSTLEN_1BYTE_gc | DMA_CH_SINGLE_bm; //Do not repeat!
|
|
DMA.CH2.CTRLB = 0x00; //No int
|
|
DMA.CH2.ADDRCTRL = DMA_CH_SRCDIR_FIXED_gc | DMA_CH_DESTDIR_FIXED_gc; //Source and address fixed.
|
|
DMA.CH2.TRIGSRC = DMA_CH_TRIGSRC_USARTC0_RXC_gc;
|
|
DMA.CH2.TRFCNT = 0;
|
|
DMA.CH2.REPCNT = 0;
|
|
|
|
DMA.CH2.SRCADDR0 = (( (uint16_t) &dummy) >> 0) & 0xFF;
|
|
DMA.CH2.SRCADDR1 = (( (uint16_t) &dummy) >> 8) & 0xFF;
|
|
DMA.CH2.SRCADDR2 = 0x00;
|
|
|
|
DMA.CH2.DESTADDR0 = (( (uint16_t) &USARTC0.DATA) >> 0) & 0xFF;
|
|
DMA.CH2.DESTADDR1 = (( (uint16_t) &USARTC0.DATA) >> 8) & 0xFF;
|
|
DMA.CH2.DESTADDR2 = 0x00;
|
|
|
|
//Must enable last for REPCNT won't work!
|
|
DMA.CH2.CTRLA |= DMA_CH_REPEAT_bm | DMA_CH_ENABLE_bm; //Enable!
|
|
|
|
USARTC0.DATA = 0x55;
|
|
USARTC0.DATA = 0x55;
|
|
|
|
DMA.CH3.REPCNT = 0; //Repeat forever!
|
|
DMA.CH3.CTRLA = DMA_CH_BURSTLEN_1BYTE_gc | DMA_CH_SINGLE_bm | DMA_CH_REPEAT_bm;
|
|
DMA.CH3.CTRLB = 0x00; //No interrupt for DacBuf!!
|
|
DMA.CH3.ADDRCTRL = DMA_CH_DESTRELOAD_BURST_gc | DMA_CH_DESTDIR_INC_gc | DMA_CH_SRCRELOAD_BLOCK_gc | DMA_CH_SRCDIR_INC_gc; //Dest reloads after each burst, with byte incrementing. Src reloads at end of block, also incrementing address.
|
|
DMA.CH3.TRIGSRC = DMA_CH_TRIGSRC_EVSYS_CH1_gc; //Triggered from TCC0 when it hits PER
|
|
DMA.CH3.TRFCNT = auxDacBufLen;
|
|
|
|
DMA.CH3.SRCADDR0 = (( (uint16_t) &dacBuf_CH2[0]) >> 0) & 0xFF; //Source address is dacbuf
|
|
DMA.CH3.SRCADDR1 = (( (uint16_t) &dacBuf_CH2[0]) >> 8) & 0xFF;
|
|
DMA.CH3.SRCADDR2 = 0x00;
|
|
|
|
DMA.CH3.DESTADDR0 = (( (uint16_t) &DACB.CH1DATAH) >> 0) & 0xFF; //Dest address is high byte of DAC register
|
|
DMA.CH3.DESTADDR1 = (( (uint16_t) &DACB.CH1DATAH) >> 8) & 0xFF;
|
|
DMA.CH3.DESTADDR2 = 0x00;
|
|
|
|
//Must enable last for REPCNT won't work!
|
|
DMA.CH3.CTRLA |= DMA_CH_ENABLE_bm; //Enable!
|
|
|
|
DMA.CH1.CTRLA = DMA_STANDARD_CTRLA;
|
|
DMA.CH1.CTRLB = DMA_STANDARD_INTERRUPT;
|
|
DMA.CH1.ADDRCTRL = DMA_CH_SRCRELOAD_BURST_gc | DMA_CH_SRCDIR_INC_gc | DMA_CH_DESTDIR_INC_gc | DMA_CH_DESTRELOAD_BLOCK_gc; //Source reloads after each burst, with byte incrementing. Dest does not reload, but does increment address.
|
|
DMA.CH1.TRIGSRC = DMA_CH_TRIGSRC_USARTC0_RXC_gc;
|
|
DMA.CH1.TRFCNT = DMA_STANDARD_TRANSFER_LENGTH;
|
|
|
|
DMA.CH1.SRCADDR0 = (( (uint16_t) &USARTC0.DATA) >> 0) & 0xFF;
|
|
DMA.CH1.SRCADDR1 = (( (uint16_t) &USARTC0.DATA) >> 8) & 0xFF;
|
|
DMA.CH1.SRCADDR2 = 0x00;
|
|
|
|
DMA.CH1.DESTADDR0 = (( (uint16_t) &isoBuf[PACKET_SIZE]) >> 0) & 0xFF; //Dest address is isoBuf
|
|
DMA.CH1.DESTADDR1 = (( (uint16_t) &isoBuf[PACKET_SIZE]) >> 8) & 0xFF;
|
|
DMA.CH1.DESTADDR2 = 0x00;
|
|
|
|
DMA.CH0.CTRLA = DMA_STANDARD_CTRLA;
|
|
DMA.CH0.CTRLB = DMA_STANDARD_INTERRUPT;
|
|
DMA.CH0.ADDRCTRL = DMA_CH_SRCRELOAD_BURST_gc | DMA_CH_SRCDIR_INC_gc | DMA_CH_DESTDIR_INC_gc | DMA_CH_DESTRELOAD_BLOCK_gc; //Source reloads after each burst, with byte incrementing. Dest does not reload, but does increment address.
|
|
DMA.CH0.TRIGSRC = DMA_CH_TRIGSRC_ADCA_CH0_gc; //Triggered from ADCA channel 0
|
|
DMA.CH0.TRFCNT = DMA_STANDARD_TRANSFER_LENGTH;
|
|
|
|
DMA.CH0.SRCADDR0 = (( (uint16_t) &ADCA.CH0.RESL) >> 0) & 0xFF; //Source address is ADC
|
|
DMA.CH0.SRCADDR1 = (( (uint16_t) &ADCA.CH0.RESL) >> 8) & 0xFF;
|
|
DMA.CH0.SRCADDR2 = 0x00;
|
|
|
|
DMA.CH0.DESTADDR0 = (( (uint16_t) &isoBuf[0]) >> 0) & 0xFF; //Dest address is isoBuf
|
|
DMA.CH0.DESTADDR1 = (( (uint16_t) &isoBuf[0]) >> 8) & 0xFF;
|
|
DMA.CH0.DESTADDR2 = 0x00;
|
|
|
|
tiny_calibration_synchronise_phase(500, 200);
|
|
median_TRFCNT = 200;
|
|
median_TRFCNT_delay = 1; //Wait a few frames before actually setting median_TRFCNT, in case a SOF interrupt was queued during tiny_dma_set_mode_xxx.
|
|
DMA.CH1.CTRLA |= DMA_CH_ENABLE_bm; //Enable!
|
|
DMA.CH0.CTRLA |= DMA_CH_ENABLE_bm; //Enable!
|
|
}
|
|
|
|
void tiny_dma_loop_mode_1(void){
|
|
return;
|
|
}
|
|
|
|
void tiny_dma_set_mode_2(void){
|
|
|
|
global_mode = 2;
|
|
|
|
tiny_dma_flush();
|
|
|
|
DMA.CH2.REPCNT = 0; //Repeat forever!
|
|
DMA.CH2.CTRLA = DMA_CH_BURSTLEN_1BYTE_gc | DMA_CH_SINGLE_bm | DMA_CH_REPEAT_bm;
|
|
DMA.CH2.CTRLB = 0x00; //No interrupt for DacBuf!!
|
|
DMA.CH2.ADDRCTRL = DMA_CH_DESTRELOAD_BURST_gc | DMA_CH_DESTDIR_INC_gc | DMA_CH_SRCRELOAD_BLOCK_gc | DMA_CH_SRCDIR_INC_gc; //Dest reloads after each burst, with byte incrementing. Src reloads at end of block, also incrementing address.
|
|
DMA.CH2.TRIGSRC = DMA_CH_TRIGSRC_EVSYS_CH1_gc; //Triggered from TCC0 when it hits PER
|
|
DMA.CH2.TRFCNT = auxDacBufLen;
|
|
|
|
DMA.CH2.SRCADDR0 = (( (uint16_t) &dacBuf_CH2[0]) >> 0) & 0xFF; //Source address is dacbuf
|
|
DMA.CH2.SRCADDR1 = (( (uint16_t) &dacBuf_CH2[0]) >> 8) & 0xFF;
|
|
DMA.CH2.SRCADDR2 = 0x00;
|
|
|
|
DMA.CH2.DESTADDR0 = (( (uint16_t) &DACB.CH1DATAH) >> 0) & 0xFF; //Dest address is high byte of DAC register
|
|
DMA.CH2.DESTADDR1 = (( (uint16_t) &DACB.CH1DATAH) >> 8) & 0xFF;
|
|
DMA.CH2.DESTADDR2 = 0x00;
|
|
|
|
//Must enable last for REPCNT won't work!
|
|
DMA.CH2.CTRLA |= DMA_CH_ENABLE_bm; //Enable!
|
|
|
|
DMA.CH3.REPCNT = 0; //Repeat forever!
|
|
DMA.CH3.CTRLA = DMA_CH_BURSTLEN_1BYTE_gc | DMA_CH_SINGLE_bm | DMA_CH_REPEAT_bm;
|
|
DMA.CH3.CTRLB = 0x00; //Hi interrupt on block complete
|
|
DMA.CH3.ADDRCTRL = DMA_CH_DESTRELOAD_BURST_gc | DMA_CH_DESTDIR_INC_gc | DMA_CH_SRCRELOAD_BLOCK_gc | DMA_CH_SRCDIR_INC_gc; //Dest reloads after each burst, with byte incrementing. Src reloads at end of block, also incrementing address.
|
|
DMA.CH3.TRIGSRC = DMA_CH_TRIGSRC_EVSYS_CH2_gc; //Triggered from TCC0 when it hits PER
|
|
DMA.CH3.TRFCNT = dacBuf_len;
|
|
|
|
DMA.CH3.SRCADDR0 = (( (uint16_t) &dacBuf_CH1[0]) >> 0) & 0xFF; //Source address is dacbuf
|
|
DMA.CH3.SRCADDR1 = (( (uint16_t) &dacBuf_CH1[0]) >> 8) & 0xFF;
|
|
DMA.CH3.SRCADDR2 = 0x00;
|
|
|
|
DMA.CH3.DESTADDR0 = (( (uint16_t) &DACB.CH0DATAH) >> 0) & 0xFF; //Dest address is high byte of DAC register
|
|
DMA.CH3.DESTADDR1 = (( (uint16_t) &DACB.CH0DATAH) >> 8) & 0xFF;
|
|
DMA.CH3.DESTADDR2 = 0x00;
|
|
|
|
//Must enable last for REPCNT won't work!
|
|
DMA.CH3.CTRLA |= DMA_CH_ENABLE_bm; //Enable!
|
|
|
|
DMA.CH0.CTRLA = 0x00;
|
|
DMA.CH0.CTRLA = DMA_CH_RESET_bm;
|
|
|
|
DMA.CH0.CTRLA = DMA_STANDARD_CTRLA;
|
|
DMA.CH0.CTRLB = DMA_STANDARD_INTERRUPT;
|
|
DMA.CH0.ADDRCTRL = DMA_CH_SRCRELOAD_BURST_gc | DMA_CH_SRCDIR_INC_gc | DMA_CH_DESTDIR_INC_gc | DMA_CH_DESTRELOAD_BLOCK_gc; //Source reloads after each burst, with byte incrementing. Dest does not reload, but does increment address.
|
|
DMA.CH0.TRIGSRC = DMA_CH_TRIGSRC_ADCA_CH0_gc; //Triggered from ADCA channel 0
|
|
DMA.CH0.TRFCNT = DMA_STANDARD_TRANSFER_LENGTH;
|
|
|
|
DMA.CH0.SRCADDR0 = (( (uint16_t) &ADCA.CH0.RESL) >> 0) & 0xFF; //Source address is ADC
|
|
DMA.CH0.SRCADDR1 = (( (uint16_t) &ADCA.CH0.RESL) >> 8) & 0xFF;
|
|
DMA.CH0.SRCADDR2 = 0x00;
|
|
|
|
DMA.CH0.DESTADDR0 = (( (uint16_t) &isoBuf[0]) >> 0) & 0xFF; //Dest address is isoBuf
|
|
DMA.CH0.DESTADDR1 = (( (uint16_t) &isoBuf[0]) >> 8) & 0xFF;
|
|
DMA.CH0.DESTADDR2 = 0x00;
|
|
|
|
|
|
DMA.CH1.CTRLA = DMA_STANDARD_CTRLA;
|
|
DMA.CH1.CTRLB = DMA_STANDARD_INTERRUPT;
|
|
DMA.CH1.ADDRCTRL = DMA_CH_SRCRELOAD_BURST_gc | DMA_CH_SRCDIR_INC_gc | DMA_CH_DESTDIR_INC_gc | DMA_CH_DESTRELOAD_BLOCK_gc; //Source reloads after each burst, with byte incrementing. Dest does not reload, but does increment address.
|
|
DMA.CH1.TRIGSRC = DMA_CH_TRIGSRC_ADCA_CH0_gc; //Triggered from ADCA channel 0
|
|
DMA.CH1.TRFCNT = DMA_STANDARD_TRANSFER_LENGTH;
|
|
|
|
DMA.CH1.SRCADDR0 = (( (uint16_t) &ADCA.CH2.RESL) >> 0) & 0xFF; //Source address is ADC
|
|
DMA.CH1.SRCADDR1 = (( (uint16_t) &ADCA.CH2.RESL) >> 8) & 0xFF;
|
|
DMA.CH1.SRCADDR2 = 0x00;
|
|
|
|
DMA.CH1.DESTADDR0 = (( (uint16_t) &isoBuf[PACKET_SIZE]) >> 0) & 0xFF; //Dest address is isoBuf
|
|
DMA.CH1.DESTADDR1 = (( (uint16_t) &isoBuf[PACKET_SIZE]) >> 8) & 0xFF;
|
|
DMA.CH1.DESTADDR2 = 0x00;
|
|
|
|
//Must enable last for REPCNT won't work!
|
|
|
|
tiny_calibration_synchronise_phase(500, 200);
|
|
median_TRFCNT = 200;
|
|
median_TRFCNT_delay = 1; //Wait a few frames before actually setting median_TRFCNT, in case a SOF interrupt was queued during tiny_dma_set_mode_xxx.
|
|
DMA.CH0.CTRLA |= DMA_CH_ENABLE_bm; //Enable!
|
|
DMA.CH1.CTRLA |= DMA_CH_ENABLE_bm; //Enable!
|
|
|
|
}
|
|
|
|
void tiny_dma_loop_mode_2(void){
|
|
return;
|
|
}
|
|
|
|
|
|
|
|
void tiny_dma_set_mode_3(void){
|
|
global_mode = 3;
|
|
tiny_dma_flush();
|
|
|
|
DMA.CH3.REPCNT = 0; //Repeat forever!
|
|
DMA.CH3.CTRLA = DMA_CH_BURSTLEN_1BYTE_gc | DMA_CH_SINGLE_bm | DMA_CH_REPEAT_bm;
|
|
DMA.CH3.CTRLB = 0x00; //No interrupt for DacBuf!!
|
|
DMA.CH3.ADDRCTRL = DMA_CH_DESTRELOAD_BURST_gc | DMA_CH_DESTDIR_INC_gc | DMA_CH_SRCRELOAD_BLOCK_gc | DMA_CH_SRCDIR_INC_gc; //Dest reloads after each burst, with byte incrementing. Src reloads at end of block, also incrementing address.
|
|
DMA.CH3.TRIGSRC = DMA_CH_TRIGSRC_EVSYS_CH1_gc; //Triggered from TCC0 when it hits PER
|
|
DMA.CH3.TRFCNT = auxDacBufLen;
|
|
|
|
DMA.CH3.SRCADDR0 = (( (uint16_t) &dacBuf_CH2[0]) >> 0) & 0xFF; //Source address is dacbuf
|
|
DMA.CH3.SRCADDR1 = (( (uint16_t) &dacBuf_CH2[0]) >> 8) & 0xFF;
|
|
DMA.CH3.SRCADDR2 = 0x00;
|
|
|
|
DMA.CH3.DESTADDR0 = (( (uint16_t) &DACB.CH1DATAH) >> 0) & 0xFF; //Dest address is high byte of DAC register
|
|
DMA.CH3.DESTADDR1 = (( (uint16_t) &DACB.CH1DATAH) >> 8) & 0xFF;
|
|
DMA.CH3.DESTADDR2 = 0x00;
|
|
|
|
//Must enable last for REPCNT won't work!
|
|
DMA.CH3.CTRLA |= DMA_CH_ENABLE_bm; //Enable!
|
|
|
|
DMA.CH2.REPCNT = 0; //Repeat forever!
|
|
DMA.CH2.CTRLA = DMA_CH_BURSTLEN_1BYTE_gc | DMA_CH_SINGLE_bm | DMA_CH_REPEAT_bm;
|
|
DMA.CH2.CTRLB = 0x00; //Hi interrupt on block complete
|
|
DMA.CH2.ADDRCTRL = DMA_CH_DESTRELOAD_BURST_gc | DMA_CH_DESTDIR_INC_gc | DMA_CH_SRCRELOAD_BLOCK_gc | DMA_CH_SRCDIR_INC_gc; //Dest reloads after each burst, with byte incrementing. Src reloads at end of block, also incrementing address.
|
|
DMA.CH2.TRIGSRC = DMA_CH_TRIGSRC_EVSYS_CH2_gc; //Triggered from TCC0 when it hits PER
|
|
DMA.CH2.TRFCNT = dacBuf_len;
|
|
|
|
DMA.CH2.SRCADDR0 = (( (uint16_t) &dacBuf_CH1[0]) >> 0) & 0xFF; //Source address is dacbuf
|
|
DMA.CH2.SRCADDR1 = (( (uint16_t) &dacBuf_CH1[0]) >> 8) & 0xFF;
|
|
DMA.CH2.SRCADDR2 = 0x00;
|
|
|
|
DMA.CH2.DESTADDR0 = (( (uint16_t) &DACB.CH0DATAH) >> 0) & 0xFF; //Dest address is high byte of DAC register
|
|
DMA.CH2.DESTADDR1 = (( (uint16_t) &DACB.CH0DATAH) >> 8) & 0xFF;
|
|
DMA.CH2.DESTADDR2 = 0x00;
|
|
|
|
//Must enable last for REPCNT won't work!
|
|
DMA.CH2.CTRLA |= DMA_CH_ENABLE_bm; //Enable!
|
|
|
|
|
|
//AUX channel (to keep it tx, therefore always rx)
|
|
DMA.CH1.CTRLA = 0x00;
|
|
DMA.CH1.CTRLA = DMA_CH_RESET_bm;
|
|
|
|
DMA.CH1.CTRLA = DMA_CH_BURSTLEN_1BYTE_gc | DMA_CH_SINGLE_bm; //Do not repeat!
|
|
DMA.CH1.CTRLB = 0x00; //No int
|
|
DMA.CH1.ADDRCTRL = DMA_CH_SRCDIR_FIXED_gc | DMA_CH_DESTDIR_FIXED_gc; //Source and address fixed.
|
|
DMA.CH1.TRIGSRC = DMA_CH_TRIGSRC_USARTC0_RXC_gc;
|
|
DMA.CH1.TRFCNT = 0;
|
|
DMA.CH1.REPCNT = 0;
|
|
|
|
DMA.CH1.SRCADDR0 = (( (uint16_t) &dummy) >> 0) & 0xFF;
|
|
DMA.CH1.SRCADDR1 = (( (uint16_t) &dummy) >> 8) & 0xFF;
|
|
DMA.CH1.SRCADDR2 = 0x00;
|
|
|
|
DMA.CH1.DESTADDR0 = (( (uint16_t) &USARTC0.DATA) >> 0) & 0xFF;
|
|
DMA.CH1.DESTADDR1 = (( (uint16_t) &USARTC0.DATA) >> 8) & 0xFF;
|
|
DMA.CH1.DESTADDR2 = 0x00;
|
|
|
|
//Must enable last for REPCNT won't work!
|
|
DMA.CH1.CTRLA |= DMA_CH_REPEAT_bm | DMA_CH_ENABLE_bm; //Enable!
|
|
|
|
USARTC0.DATA = 0x55;
|
|
|
|
//Actual data being transferred
|
|
DMA.CH0.CTRLA = 0x00;
|
|
DMA.CH0.CTRLA = DMA_CH_RESET_bm;
|
|
|
|
DMA.CH0.CTRLA = DMA_STANDARD_CTRLA;
|
|
DMA.CH0.CTRLB = DMA_STANDARD_INTERRUPT;
|
|
DMA.CH0.ADDRCTRL = DMA_CH_SRCRELOAD_BURST_gc | DMA_CH_SRCDIR_INC_gc | DMA_CH_DESTDIR_INC_gc | DMA_CH_DESTRELOAD_BLOCK_gc; //Source reloads after each burst, with byte incrementing. Dest does not reload, but does increment address.
|
|
DMA.CH0.TRIGSRC = DMA_CH_TRIGSRC_USARTC0_RXC_gc;
|
|
DMA.CH0.TRFCNT = DMA_STANDARD_TRANSFER_LENGTH;
|
|
|
|
DMA.CH0.SRCADDR0 = (( (uint16_t) &USARTC0.DATA) >> 0) & 0xFF; //Source address is ADC
|
|
DMA.CH0.SRCADDR1 = (( (uint16_t) &USARTC0.DATA) >> 8) & 0xFF;
|
|
DMA.CH0.SRCADDR2 = 0x00;
|
|
|
|
DMA.CH0.DESTADDR0 = (( (uint16_t) &isoBuf[0]) >> 0) & 0xFF; //Dest address is isoBuf
|
|
DMA.CH0.DESTADDR1 = (( (uint16_t) &isoBuf[0]) >> 8) & 0xFF;
|
|
DMA.CH0.DESTADDR2 = 0x00;
|
|
|
|
tiny_calibration_synchronise_phase(500, 200);
|
|
median_TRFCNT = 200;
|
|
median_TRFCNT_delay = 1; //Wait a few frames before actually setting median_TRFCNT, in case a SOF interrupt was queued during tiny_dma_set_mode_xxx.
|
|
|
|
//Must enable last for REPCNT won't work!
|
|
DMA.CH0.CTRLA |= DMA_CH_ENABLE_bm; //Enable!
|
|
}
|
|
|
|
void tiny_dma_loop_mode_3(void){
|
|
return;
|
|
}
|
|
|
|
void tiny_dma_set_mode_4(void){
|
|
|
|
global_mode = 4;
|
|
|
|
tiny_dma_flush();
|
|
|
|
//AUX channel (to keep it tx, therefore always rx)
|
|
DMA.CH2.CTRLA = 0x00;
|
|
DMA.CH2.CTRLA = DMA_CH_RESET_bm;
|
|
|
|
DMA.CH2.CTRLA = DMA_CH_BURSTLEN_1BYTE_gc | DMA_CH_SINGLE_bm; //Do not repeat!
|
|
DMA.CH2.CTRLB = 0x00; //No int
|
|
DMA.CH2.ADDRCTRL = DMA_CH_SRCDIR_FIXED_gc | DMA_CH_DESTDIR_FIXED_gc; //Source and address fixed.
|
|
DMA.CH2.TRIGSRC = DMA_CH_TRIGSRC_USARTC0_RXC_gc;
|
|
DMA.CH2.TRFCNT = 0;
|
|
DMA.CH2.REPCNT = 0;
|
|
|
|
DMA.CH2.SRCADDR0 = (( (uint16_t) &dummy) >> 0) & 0xFF;
|
|
DMA.CH2.SRCADDR1 = (( (uint16_t) &dummy) >> 8) & 0xFF;
|
|
DMA.CH2.SRCADDR2 = 0x00;
|
|
|
|
DMA.CH2.DESTADDR0 = (( (uint16_t) &USARTC0.DATA) >> 0) & 0xFF;
|
|
DMA.CH2.DESTADDR1 = (( (uint16_t) &USARTC0.DATA) >> 8) & 0xFF;
|
|
DMA.CH2.DESTADDR2 = 0x00;
|
|
|
|
//Must enable last for REPCNT won't work!
|
|
DMA.CH2.CTRLA |= DMA_CH_REPEAT_bm | DMA_CH_ENABLE_bm; //Enable!
|
|
|
|
USARTC0.DATA = 0x55;
|
|
|
|
DMA.CH3.REPCNT = 0; //Repeat forever!
|
|
DMA.CH3.CTRLA = DMA_CH_BURSTLEN_1BYTE_gc | DMA_CH_SINGLE_bm | DMA_CH_REPEAT_bm;
|
|
DMA.CH3.CTRLB = 0x00; //No interrupt for DacBuf!!
|
|
DMA.CH3.ADDRCTRL = DMA_CH_DESTRELOAD_BURST_gc | DMA_CH_DESTDIR_INC_gc | DMA_CH_SRCRELOAD_BLOCK_gc | DMA_CH_SRCDIR_INC_gc; //Dest reloads after each burst, with byte incrementing. Src reloads at end of block, also incrementing address.
|
|
DMA.CH3.TRIGSRC = DMA_CH_TRIGSRC_EVSYS_CH1_gc; //Triggered from TCC0 when it hits PER
|
|
DMA.CH3.TRFCNT = auxDacBufLen;
|
|
|
|
DMA.CH3.SRCADDR0 = (( (uint16_t) &dacBuf_CH2[0]) >> 0) & 0xFF; //Source address is dacbuf
|
|
DMA.CH3.SRCADDR1 = (( (uint16_t) &dacBuf_CH2[0]) >> 8) & 0xFF;
|
|
DMA.CH3.SRCADDR2 = 0x00;
|
|
|
|
DMA.CH3.DESTADDR0 = (( (uint16_t) &DACB.CH1DATAH) >> 0) & 0xFF; //Dest address is high byte of DAC register
|
|
DMA.CH3.DESTADDR1 = (( (uint16_t) &DACB.CH1DATAH) >> 8) & 0xFF;
|
|
DMA.CH3.DESTADDR2 = 0x00;
|
|
|
|
//Must enable last for REPCNT won't work!
|
|
DMA.CH3.CTRLA |= DMA_CH_ENABLE_bm; //Enable!
|
|
|
|
//Actual data being transferred
|
|
DMA.CH0.CTRLA = DMA_STANDARD_CTRLA;
|
|
DMA.CH0.CTRLB = DMA_STANDARD_INTERRUPT;
|
|
DMA.CH0.ADDRCTRL = DMA_CH_SRCRELOAD_BURST_gc | DMA_CH_SRCDIR_INC_gc | DMA_CH_DESTDIR_INC_gc | DMA_CH_DESTRELOAD_BLOCK_gc; //Source reloads after each burst, with byte incrementing. Dest does not reload, but does increment address.
|
|
DMA.CH0.TRIGSRC = DMA_CH_TRIGSRC_USARTC0_RXC_gc;
|
|
DMA.CH0.TRFCNT = DMA_STANDARD_TRANSFER_LENGTH;
|
|
|
|
DMA.CH0.SRCADDR0 = (( (uint16_t) &USARTC0.DATA) >> 0) & 0xFF; //Source address is ADC
|
|
DMA.CH0.SRCADDR1 = (( (uint16_t) &USARTC0.DATA) >> 8) & 0xFF;
|
|
DMA.CH0.SRCADDR2 = 0x00;
|
|
|
|
DMA.CH0.DESTADDR0 = (( (uint16_t) &isoBuf[0]) >> 0) & 0xFF; //Dest address is isoBuf
|
|
DMA.CH0.DESTADDR1 = (( (uint16_t) &isoBuf[0]) >> 8) & 0xFF;
|
|
DMA.CH0.DESTADDR2 = 0x00;
|
|
|
|
|
|
DMA.CH1.CTRLA = DMA_STANDARD_CTRLA;
|
|
DMA.CH1.CTRLB = DMA_STANDARD_INTERRUPT;
|
|
DMA.CH1.ADDRCTRL = DMA_CH_SRCRELOAD_BURST_gc | DMA_CH_SRCDIR_INC_gc | DMA_CH_DESTDIR_INC_gc | DMA_CH_DESTRELOAD_BLOCK_gc; //Source reloads after each burst, with byte incrementing. Dest does not reload, but does increment address.
|
|
DMA.CH1.TRIGSRC = DMA_CH_TRIGSRC_SPIC_gc;
|
|
DMA.CH1.TRFCNT = DMA_STANDARD_TRANSFER_LENGTH;
|
|
|
|
DMA.CH1.SRCADDR0 = (( (uint16_t) &SPIC.DATA) >> 0) & 0xFF; //Source address is ADC
|
|
DMA.CH1.SRCADDR1 = (( (uint16_t) &SPIC.DATA) >> 8) & 0xFF;
|
|
DMA.CH1.SRCADDR2 = 0x00;
|
|
|
|
DMA.CH1.DESTADDR0 = (( (uint16_t) &isoBuf[PACKET_SIZE]) >> 0) & 0xFF; //Dest address is isoBuf
|
|
DMA.CH1.DESTADDR1 = (( (uint16_t) &isoBuf[PACKET_SIZE]) >> 8) & 0xFF;
|
|
DMA.CH1.DESTADDR2 = 0x00;
|
|
|
|
tiny_calibration_synchronise_phase(500, 200);
|
|
median_TRFCNT = 200;
|
|
median_TRFCNT_delay = 1; //Wait a few frames before actually setting median_TRFCNT, in case a SOF interrupt was queued during tiny_dma_set_mode_xxx.
|
|
DMA.CH0.CTRLA |= DMA_CH_ENABLE_bm; //Enable!
|
|
DMA.CH1.CTRLA |= DMA_CH_ENABLE_bm; //Enable!
|
|
|
|
// Hack: manually trigger a transfer to ensure zero phase difference.
|
|
DMA.CH0.CTRLA |= DMA_CH_TRFREQ_bm;
|
|
}
|
|
|
|
void tiny_dma_loop_mode_4(void){
|
|
return;
|
|
}
|
|
|
|
|
|
void tiny_dma_set_mode_5(void){
|
|
while(1); //Deliberate Crash! Mode 5 should be invalid.
|
|
}
|
|
|
|
void tiny_dma_set_mode_6(void){
|
|
|
|
global_mode = 6;
|
|
|
|
tiny_dma_flush();
|
|
|
|
DMA.CH2.REPCNT = 0; //Repeat forever!
|
|
DMA.CH2.CTRLA = DMA_CH_BURSTLEN_1BYTE_gc | DMA_CH_SINGLE_bm | DMA_CH_REPEAT_bm;
|
|
DMA.CH2.CTRLB = 0x00; //Hi interrupt on block complete
|
|
DMA.CH2.ADDRCTRL = DMA_CH_DESTRELOAD_BURST_gc | DMA_CH_DESTDIR_INC_gc | DMA_CH_SRCRELOAD_BLOCK_gc | DMA_CH_SRCDIR_INC_gc; //Dest reloads after each burst, with byte incrementing. Src reloads at end of block, also incrementing address.
|
|
DMA.CH2.TRIGSRC = DMA_CH_TRIGSRC_EVSYS_CH2_gc; //Triggered from TCC0 when it hits PER
|
|
DMA.CH2.TRFCNT = dacBuf_len;
|
|
|
|
DMA.CH2.SRCADDR0 = (( (uint16_t) &dacBuf_CH1[0]) >> 0) & 0xFF; //Source address is dacbuf
|
|
DMA.CH2.SRCADDR1 = (( (uint16_t) &dacBuf_CH1[0]) >> 8) & 0xFF;
|
|
DMA.CH2.SRCADDR2 = 0x00;
|
|
|
|
DMA.CH2.DESTADDR0 = (( (uint16_t) &DACB.CH0DATAH) >> 0) & 0xFF; //Dest address is high byte of DAC register
|
|
DMA.CH2.DESTADDR1 = (( (uint16_t) &DACB.CH0DATAH) >> 8) & 0xFF;
|
|
DMA.CH2.DESTADDR2 = 0x00;
|
|
|
|
//Must enable last for REPCNT won't work!
|
|
DMA.CH2.CTRLA |= DMA_CH_ENABLE_bm; //Enable!
|
|
|
|
DMA.CH3.REPCNT = 0; //Repeat forever!
|
|
DMA.CH3.CTRLA = DMA_CH_BURSTLEN_1BYTE_gc | DMA_CH_SINGLE_bm | DMA_CH_REPEAT_bm;
|
|
DMA.CH3.CTRLB = 0x00; //No interrupt for DacBuf!!
|
|
DMA.CH3.ADDRCTRL = DMA_CH_DESTRELOAD_BURST_gc | DMA_CH_DESTDIR_INC_gc | DMA_CH_SRCRELOAD_BLOCK_gc | DMA_CH_SRCDIR_INC_gc; //Dest reloads after each burst, with byte incrementing. Src reloads at end of block, also incrementing address.
|
|
DMA.CH3.TRIGSRC = DMA_CH_TRIGSRC_EVSYS_CH1_gc; //Triggered from TCC0 when it hits PER
|
|
DMA.CH3.TRFCNT = auxDacBufLen;
|
|
|
|
DMA.CH3.SRCADDR0 = (( (uint16_t) &dacBuf_CH2[0]) >> 0) & 0xFF; //Source address is dacbuf
|
|
DMA.CH3.SRCADDR1 = (( (uint16_t) &dacBuf_CH2[0]) >> 8) & 0xFF;
|
|
DMA.CH3.SRCADDR2 = 0x00;
|
|
|
|
DMA.CH3.DESTADDR0 = (( (uint16_t) &DACB.CH1DATAH) >> 0) & 0xFF; //Dest address is high byte of DAC register
|
|
DMA.CH3.DESTADDR1 = (( (uint16_t) &DACB.CH1DATAH) >> 8) & 0xFF;
|
|
DMA.CH3.DESTADDR2 = 0x00;
|
|
|
|
//Must enable last for REPCNT won't work!
|
|
DMA.CH3.CTRLA |= DMA_CH_ENABLE_bm; //Enable!
|
|
|
|
DMA.CH0.CTRLA = 0x00;
|
|
DMA.CH0.CTRLA = DMA_CH_RESET_bm;
|
|
|
|
DMA.CH0.CTRLA = DMA_CH_BURSTLEN_1BYTE_gc | DMA_CH_SINGLE_bm | DMA_CH_REPEAT_bm;
|
|
DMA.CH0.CTRLB = 0x00; //No interrupt!
|
|
DMA.CH0.ADDRCTRL = DMA_CH_SRCRELOAD_BURST_gc | DMA_CH_SRCDIR_INC_gc | DMA_CH_DESTDIR_INC_gc | DMA_CH_DESTRELOAD_BLOCK_gc; //Source reloads after each burst, with byte incrementing. Dest does not reload, but does increment address.
|
|
DMA.CH0.TRIGSRC = DMA_CH_TRIGSRC_ADCA_CH0_gc; //Triggered from ADCA channel 0
|
|
DMA.CH0.TRFCNT = BUFFER_SIZE;
|
|
|
|
DMA.CH0.SRCADDR0 = (( (uint16_t) &ADCA.CH0.RESL) >> 0) & 0xFF; //Source address is ADC
|
|
DMA.CH0.SRCADDR1 = (( (uint16_t) &ADCA.CH0.RESL) >> 8) & 0xFF;
|
|
DMA.CH0.SRCADDR2 = 0x00;
|
|
|
|
DMA.CH0.DESTADDR0 = (( (uint16_t) &isoBuf[0]) >> 0) & 0xFF; //Dest address is isoBuf
|
|
DMA.CH0.DESTADDR1 = (( (uint16_t) &isoBuf[0]) >> 8) & 0xFF;
|
|
DMA.CH0.DESTADDR2 = 0x00;
|
|
|
|
tiny_calibration_synchronise_phase(500, 200);
|
|
median_TRFCNT = 400;
|
|
median_TRFCNT_delay = 1; //Wait a few frames before actually setting median_TRFCNT, in case a SOF interrupt was queued during tiny_dma_set_mode_xxx.
|
|
DMA.CH0.CTRLA |= DMA_CH_ENABLE_bm; //Enable!
|
|
|
|
|
|
}
|
|
|
|
void tiny_dma_loop_mode_6(void){
|
|
return;
|
|
}
|
|
|
|
void tiny_dma_set_mode_7(void){
|
|
|
|
global_mode = 7;
|
|
|
|
tiny_dma_flush();
|
|
|
|
DMA.CH2.REPCNT = 0; //Repeat forever!
|
|
DMA.CH2.CTRLA = DMA_CH_BURSTLEN_1BYTE_gc | DMA_CH_SINGLE_bm | DMA_CH_REPEAT_bm;
|
|
DMA.CH2.CTRLB = 0x00; //Hi interrupt on block complete
|
|
DMA.CH2.ADDRCTRL = DMA_CH_DESTRELOAD_BURST_gc | DMA_CH_DESTDIR_INC_gc | DMA_CH_SRCRELOAD_BLOCK_gc | DMA_CH_SRCDIR_INC_gc; //Dest reloads after each burst, with byte incrementing. Src reloads at end of block, also incrementing address.
|
|
DMA.CH2.TRIGSRC = DMA_CH_TRIGSRC_EVSYS_CH2_gc; //Triggered from TCC0 when it hits PER
|
|
DMA.CH2.TRFCNT = dacBuf_len;
|
|
|
|
DMA.CH2.SRCADDR0 = (( (uint16_t) &dacBuf_CH1[0]) >> 0) & 0xFF; //Source address is dacbuf
|
|
DMA.CH2.SRCADDR1 = (( (uint16_t) &dacBuf_CH1[0]) >> 8) & 0xFF;
|
|
DMA.CH2.SRCADDR2 = 0x00;
|
|
|
|
DMA.CH2.DESTADDR0 = (( (uint16_t) &DACB.CH0DATAH) >> 0) & 0xFF; //Dest address is high byte of DAC register
|
|
DMA.CH2.DESTADDR1 = (( (uint16_t) &DACB.CH0DATAH) >> 8) & 0xFF;
|
|
DMA.CH2.DESTADDR2 = 0x00;
|
|
|
|
//Must enable last for REPCNT won't work!
|
|
DMA.CH2.CTRLA |= DMA_CH_ENABLE_bm; //Enable!
|
|
|
|
DMA.CH3.REPCNT = 0; //Repeat forever!
|
|
DMA.CH3.CTRLA = DMA_CH_BURSTLEN_1BYTE_gc | DMA_CH_SINGLE_bm | DMA_CH_REPEAT_bm;
|
|
DMA.CH3.CTRLB = 0x00; //No interrupt for DacBuf!!
|
|
DMA.CH3.ADDRCTRL = DMA_CH_DESTRELOAD_BURST_gc | DMA_CH_DESTDIR_INC_gc | DMA_CH_SRCRELOAD_BLOCK_gc | DMA_CH_SRCDIR_INC_gc; //Dest reloads after each burst, with byte incrementing. Src reloads at end of block, also incrementing address.
|
|
DMA.CH3.TRIGSRC = DMA_CH_TRIGSRC_EVSYS_CH1_gc; //Triggered from TCC0 when it hits PER
|
|
DMA.CH3.TRFCNT = auxDacBufLen;
|
|
|
|
DMA.CH3.SRCADDR0 = (( (uint16_t) &dacBuf_CH2[0]) >> 0) & 0xFF; //Source address is dacbuf
|
|
DMA.CH3.SRCADDR1 = (( (uint16_t) &dacBuf_CH2[0]) >> 8) & 0xFF;
|
|
DMA.CH3.SRCADDR2 = 0x00;
|
|
|
|
DMA.CH3.DESTADDR0 = (( (uint16_t) &DACB.CH1DATAH) >> 0) & 0xFF; //Dest address is high byte of DAC register
|
|
DMA.CH3.DESTADDR1 = (( (uint16_t) &DACB.CH1DATAH) >> 8) & 0xFF;
|
|
DMA.CH3.DESTADDR2 = 0x00;
|
|
|
|
//Must enable last for REPCNT won't work!
|
|
DMA.CH3.CTRLA |= DMA_CH_ENABLE_bm; //Enable!
|
|
|
|
DMA.CH0.CTRLA = 0x00;
|
|
DMA.CH0.CTRLA = DMA_CH_RESET_bm;
|
|
|
|
DMA.CH0.CTRLA = DMA_CH_BURSTLEN_2BYTE_gc | DMA_CH_SINGLE_bm | DMA_CH_REPEAT_bm; //Do not repeat!
|
|
DMA.CH0.CTRLB = 0x00; //No interrupt!
|
|
DMA.CH0.ADDRCTRL = DMA_CH_SRCRELOAD_BURST_gc | DMA_CH_SRCDIR_INC_gc | DMA_CH_DESTDIR_INC_gc | DMA_CH_DESTRELOAD_BLOCK_gc; //Source reloads after each burst, with byte incrementing. Dest does not reload, but does increment address.
|
|
DMA.CH0.TRIGSRC = DMA_CH_TRIGSRC_ADCA_CH0_gc; //Triggered from ADCA channel 0
|
|
DMA.CH0.TRFCNT = BUFFER_SIZE;
|
|
|
|
DMA.CH0.SRCADDR0 = (( (uint16_t) &ADCA.CH0.RESL) >> 0) & 0xFF; //Source address is ADC
|
|
DMA.CH0.SRCADDR1 = (( (uint16_t) &ADCA.CH0.RESL) >> 8) & 0xFF;
|
|
DMA.CH0.SRCADDR2 = 0x00;
|
|
|
|
DMA.CH0.DESTADDR0 = (( (uint16_t) &isoBuf[0]) >> 0) & 0xFF; //Dest address is isoBuf
|
|
DMA.CH0.DESTADDR1 = (( (uint16_t) &isoBuf[0]) >> 8) & 0xFF;
|
|
DMA.CH0.DESTADDR2 = 0x00;
|
|
|
|
tiny_calibration_synchronise_phase(500, 200);
|
|
median_TRFCNT = 400;
|
|
median_TRFCNT_delay = 1; //Wait a few frames before actually setting median_TRFCNT, in case a SOF interrupt was queued during tiny_dma_set_mode_xxx.
|
|
DMA.CH0.CTRLA |= DMA_CH_ENABLE_bm; //Enable!
|
|
|
|
}
|
|
|
|
void tiny_dma_loop_mode_7(void){
|
|
}
|
|
|
|
ISR(DMA_CH0_vect){
|
|
DMA.INTFLAGS = 0x01;
|
|
//dma_ch0_ran++;
|
|
//uds.dma_ch0_cntL = dma_ch0_ran & 0xff;
|
|
//uds.dma_ch0_cntH = (dma_ch0_ran >> 8) & 0xff;
|
|
|
|
#ifdef SINGLE_ENDPOINT_INTERFACE
|
|
DMA.CH0.CTRLA = 0x00;
|
|
DMA.CH0.CTRLA = DMA_CH_BURSTLEN_1BYTE_gc | DMA_CH_SINGLE_bm; //Do not repeat!
|
|
DMA.CH0.TRFCNT = HALFPACKET_SIZE;
|
|
|
|
short ptr = usb_state ? 0 : PACKET_SIZE;
|
|
|
|
DMA.CH0.DESTADDR0 = (( (uint16_t) &isoBuf[ptr]) >> 0) & 0xFF; //Dest address is isoBuf
|
|
DMA.CH0.DESTADDR1 = (( (uint16_t) &isoBuf[ptr]) >> 8) & 0xFF;
|
|
|
|
DMA.CH0.CTRLA |= DMA_CH_ENABLE_bm;
|
|
#endif
|
|
}
|
|
|
|
ISR(DMA_CH1_vect){
|
|
DMA.INTFLAGS = 0x02;
|
|
//dma_ch1_ran++;
|
|
//uds.dma_ch1_cntL = dma_ch1_ran & 0xff;
|
|
//uds.dma_ch1_cntH = (dma_ch1_ran >> 8) & 0xff;
|
|
|
|
#ifdef SINGLE_ENDPOINT_INTERFACE
|
|
DMA.CH1.CTRLA = 0x00;
|
|
DMA.CH1.CTRLA = DMA_CH_BURSTLEN_1BYTE_gc | DMA_CH_SINGLE_bm; //Do not repeat!
|
|
DMA.CH1.TRFCNT = HALFPACKET_SIZE;
|
|
|
|
short ptr = usb_state ? HALFPACKET_SIZE : PACKET_SIZE + HALFPACKET_SIZE;
|
|
|
|
DMA.CH1.DESTADDR0 = (( (uint16_t) &isoBuf[ptr]) >> 0) & 0xFF; //Dest address is isoBuf
|
|
DMA.CH1.DESTADDR1 = (( (uint16_t) &isoBuf[ptr]) >> 8) & 0xFF;
|
|
|
|
DMA.CH1.CTRLA |= DMA_CH_ENABLE_bm;
|
|
#endif
|
|
}
|