BeRTOS
|
00001 00038 #include "dac_sam3.h" 00039 00040 #include "cfg/cfg_dac.h" 00041 00042 #include <cfg/macros.h> 00043 #include <cfg/compiler.h> 00044 00045 // Define log settings for cfg/log.h. 00046 #define LOG_LEVEL DAC_LOG_LEVEL 00047 #define LOG_FORMAT DAC_LOG_FORMAT 00048 #include <cfg/log.h> 00049 00050 #include <drv/dac.h> 00051 #include <drv/irq_cm3.h> 00052 00053 #include <cpu/types.h> 00054 00055 #include <io/cm3.h> 00056 00057 #include <string.h> 00058 00059 struct DacHardware 00060 { 00061 uint16_t channels; 00062 uint32_t rate; 00063 bool end; 00064 }; 00065 00066 struct DacHardware dac_hw; 00067 00068 #if CONFIG_DAC_TIMER == DACC_TRGSEL_TIO_CH0 /* Select Timer counter TIO Channel 0 */ 00069 #define DAC_TC_ID TC0_ID 00070 #define DAC_TC_CCR TC0_CCR0 00071 #define DAC_TC_IDR TC0_IDR0 00072 #define DAC_TC_CMR TC0_CMR0 00073 #define DAC_TC_SR TC0_SR0 00074 #define DAC_TC_RA TC0_RA0 00075 #define DAC_TC_RC TC0_RC0 00076 #elif CONFIG_DAC_TIMER == DACC_TRGSEL_TIO_CH1 /* Select Timer counter TIO Channel 1 */ 00077 #define DAC_TC_ID TC1_ID 00078 #define DAC_TC_CCR TC0_CCR1 00079 #define DAC_TC_IDR TC0_IDR1 00080 #define DAC_TC_CMR TC0_CMR1 00081 #define DAC_TC_SR TC0_SR1 00082 #define DAC_TC_RA TC0_RA1 00083 #define DAC_TC_RC TC0_RC1 00084 #elif CONFIG_DAC_TIMER == DACC_TRGSEL_TIO_CH2 /* Select Timer counter TIO Channel 2 */ 00085 #define DAC_TC_ID TC2_ID 00086 #define DAC_TC_CCR TC0_CCR2 00087 #define DAC_TC_IDR TC0_IDR2 00088 #define DAC_TC_CMR TC0_CMR2 00089 #define DAC_TC_SR TC0_SR2 00090 #define DAC_TC_RA TC0_RA2 00091 #define DAC_TC_RC TC0_RC2 00092 #elif CONFIG_DAC_TIMER == DACC_TRGSEL_PWM0 || CONFIG_DAC_TIMER == DACC_TRGSEL_PWM1 00093 #error unimplemented pwm triger select. 00094 #endif 00095 00096 INLINE void tc_setup(uint32_t freq, size_t n_sample) 00097 { 00098 pmc_periphEnable(DAC_TC_ID); 00099 00100 /* Disable TC clock */ 00101 DAC_TC_CCR = TC_CCR_CLKDIS; 00102 /* Disable interrupts */ 00103 DAC_TC_IDR = 0xFFFFFFFF; 00104 /* Clear status register */ 00105 volatile uint32_t dummy = DAC_TC_SR; 00106 (void)dummy; 00107 00108 /* 00109 * Setup the timer counter: 00110 * - select clock TCLK1 (MCK/2) 00111 * - enable wave form mode 00112 * - RA compare effect SET 00113 * - RC compare effect CLEAR 00114 * - UP mode with automatic trigger on RC Compare 00115 */ 00116 DAC_TC_CMR = TC_TIMER_CLOCK1 | BV(TC_CMR_WAVE) | TC_CMR_ACPA_SET | TC_CMR_ACPC_CLEAR | BV(TC_CMR_CPCTRG); 00117 00118 /* 00119 * Compute the sample frequency 00120 * the RC counter will update every MCK/2 (see above) 00121 * so to convert one sample at the user freq we generate 00122 * the trigger every TC_CLK / (numer_of_sample * user_freq) 00123 * where TC_CLK = MCK / 2. 00124 */ 00125 uint32_t rc = DIV_ROUND((CPU_FREQ / 2), n_sample * freq); 00126 DAC_TC_RC = rc; 00127 /* generate the square wave with duty = 50% */ 00128 DAC_TC_RA = DIV_ROUND(50 * rc, 100); 00129 00130 PIOB_PDR = BV(25); 00131 PIO_PERIPH_SEL(PIOB_BASE, BV(25), PIO_PERIPH_B); 00132 } 00133 00134 INLINE void tc_start(void) 00135 { 00136 DAC_TC_CCR = BV(TC_CCR_CLKEN)| BV(TC_CCR_SWTRG); 00137 } 00138 00139 INLINE void tc_stop(void) 00140 { 00141 DAC_TC_CCR = BV(TC_CCR_CLKDIS); 00142 } 00143 00144 static int sam3x_dac_write(struct Dac *dac, unsigned channel, uint16_t sample) 00145 { 00146 (void)dac; 00147 00148 ASSERT(channel <= DAC_MAXCH); 00149 00150 DACC_MR |= (channel << DACC_USER_SEL_SHIFT) & DACC_USER_SEL_MASK; 00151 DACC_CHER |= BV(channel); 00152 00153 DACC_CDR = sample ; 00154 00155 return 0; 00156 } 00157 00158 static void sam3x_dac_setCh(struct Dac *dac, uint32_t mask) 00159 { 00160 /* we have only the ch0 and ch1 */ 00161 ASSERT(mask < BV(3)); 00162 dac->hw->channels = mask; 00163 } 00164 00165 static void sam3x_dac_setSampleRate(struct Dac *dac, uint32_t rate) 00166 { 00167 (void)dac; 00168 00169 /* Eneble hw trigger */ 00170 DACC_MR |= BV(DACC_TRGEN) | (CONFIG_DAC_TIMER << DACC_TRGSEL_SHIFT); 00171 dac->hw->rate = rate; 00172 } 00173 00174 static void sam3x_dac_conversion(struct Dac *dac, void *buf, size_t len) 00175 { 00176 if (dac->hw->channels & BV(DACC_CH0)) 00177 DACC_MR |= (DACC_CH0 << DACC_USER_SEL_SHIFT) & DACC_USER_SEL_MASK; 00178 00179 if (dac->hw->channels & BV(DACC_CH1)) 00180 DACC_MR |= (DACC_CH1 << DACC_USER_SEL_SHIFT) & DACC_USER_SEL_MASK; 00181 00182 DACC_CHER |= dac->hw->channels; 00183 00184 /* setup timer and start it */ 00185 tc_setup(dac->hw->rate, len); 00186 tc_start(); 00187 00188 /* Setup dma and start it */ 00189 DACC_TPR = (uint32_t)buf ; 00190 DACC_TCR = len; 00191 DACC_PTCR |= BV(DACC_PTCR_TXTEN); 00192 } 00193 00194 static bool sam3x_dac_isFinished(struct Dac *dac) 00195 { 00196 (void)dac; 00197 return 0; 00198 } 00199 00200 static void sam3x_dac_start(struct Dac *dac, void *buf, size_t len, size_t slice_len) 00201 { 00202 (void)dac; 00203 (void)buf; 00204 (void)len; 00205 (void)slice_len; 00206 } 00207 00208 static void sam3x_dac_stop(struct Dac *dac) 00209 { 00210 (void)dac; 00211 } 00212 00213 00214 void dac_init(struct Dac *dac) 00215 { 00216 00217 /* Fill the virtual table */ 00218 dac->ctx.write = sam3x_dac_write; 00219 dac->ctx.setCh = sam3x_dac_setCh; 00220 dac->ctx.setSampleRate = sam3x_dac_setSampleRate; 00221 dac->ctx.conversion = sam3x_dac_conversion; 00222 dac->ctx.isFinished = sam3x_dac_isFinished; 00223 dac->ctx.start = sam3x_dac_start; 00224 dac->ctx.stop = sam3x_dac_stop; 00225 dac->ctx._type = DAC_SAM3X; 00226 dac->hw = &dac_hw; 00227 00228 /* Clock DAC peripheral */ 00229 pmc_periphEnable(DACC_ID); 00230 00231 /* Reset hw */ 00232 DACC_CR |= BV(DACC_SWRST); 00233 DACC_MR = 0; 00234 00235 /* Configure the dac */ 00236 DACC_MR |= (CONFIG_DAC_REFRESH << DACC_REFRESH_SHIFT) & DACC_REFRESH_MASK; 00237 DACC_MR |= (CONFIG_DAC_STARTUP << DACC_STARTUP_SHIFT) & DACC_STARTUP_MASK; 00238 }