dac_sam3.c
Go to the documentation of this file.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
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 <cpu/irq.h>
00052 #include <drv/irq_cm3.h>
00053
00054 #include <cpu/types.h>
00055
00056 #include <mware/event.h>
00057
00058 #include <io/cm3.h>
00059
00060 #include <string.h>
00061
00062 struct DacHardware
00063 {
00064 uint16_t channels;
00065 uint32_t rate;
00066 bool end;
00067 };
00068
00069 struct DacHardware dac_hw;
00070
00071
00072
00073 static Event buff_emtpy;
00074
00075 #if CONFIG_DAC_TIMER == DACC_TRGSEL_TIO_CH0
00076 #define DAC_TC_ID TC0_ID
00077 #define DAC_TC_CCR TC0_CCR0
00078 #define DAC_TC_IDR TC0_IDR0
00079 #define DAC_TC_CMR TC0_CMR0
00080 #define DAC_TC_SR TC0_SR0
00081 #define DAC_TC_RA TC0_RA0
00082 #define DAC_TC_RC TC0_RC0
00083 #elif CONFIG_DAC_TIMER == DACC_TRGSEL_TIO_CH1
00084 #define DAC_TC_ID TC1_ID
00085 #define DAC_TC_CCR TC0_CCR1
00086 #define DAC_TC_IDR TC0_IDR1
00087 #define DAC_TC_CMR TC0_CMR1
00088 #define DAC_TC_SR TC0_SR1
00089 #define DAC_TC_RA TC0_RA1
00090 #define DAC_TC_RC TC0_RC1
00091 #elif CONFIG_DAC_TIMER == DACC_TRGSEL_TIO_CH2
00092 #define DAC_TC_ID TC2_ID
00093 #define DAC_TC_CCR TC0_CCR2
00094 #define DAC_TC_IDR TC0_IDR2
00095 #define DAC_TC_CMR TC0_CMR2
00096 #define DAC_TC_SR TC0_SR2
00097 #define DAC_TC_RA TC0_RA2
00098 #define DAC_TC_RC TC0_RC2
00099 #elif CONFIG_DAC_TIMER == DACC_TRGSEL_PWM0 || CONFIG_DAC_TIMER == DACC_TRGSEL_PWM1
00100 #error unimplemented pwm triger select.
00101 #endif
00102
00103
00104 INLINE void tc_init(void)
00105 {
00106 pmc_periphEnable(DAC_TC_ID);
00107
00108
00109 DAC_TC_CCR = BV(TC_CCR_CLKDIS);
00110
00111 DAC_TC_IDR = 0xFFFFFFFF;
00112
00113 volatile uint32_t dummy = DAC_TC_SR;
00114 (void)dummy;
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124 DAC_TC_CMR = TC_TIMER_CLOCK1 | BV(TC_CMR_WAVE) | TC_CMR_ACPA_SET | TC_CMR_ACPC_CLEAR | BV(TC_CMR_CPCTRG);
00125
00126
00127
00128 PIOB_PDR = BV(25);
00129 PIO_PERIPH_SEL(PIOB_BASE, BV(25), PIO_PERIPH_B);
00130 }
00131
00132 INLINE void tc_setup(uint32_t freq, size_t n_sample)
00133 {
00134
00135
00136
00137
00138
00139
00140
00141 uint32_t rc = DIV_ROUND((CPU_FREQ / 2), n_sample * freq);
00142 DAC_TC_RC = rc;
00143
00144 DAC_TC_RA = DIV_ROUND(50 * rc, 100);
00145 }
00146
00147 INLINE void tc_start(void)
00148 {
00149 DAC_TC_CCR = BV(TC_CCR_CLKEN)| BV(TC_CCR_SWTRG);
00150 }
00151
00152 INLINE void tc_stop(void)
00153 {
00154 DAC_TC_CCR = BV(TC_CCR_CLKDIS);
00155 }
00156
00157 static int sam3x_dac_write(struct Dac *dac, unsigned channel, uint16_t sample)
00158 {
00159 (void)dac;
00160
00161 ASSERT(channel <= DAC_MAXCH);
00162
00163 DACC_MR |= (channel << DACC_USER_SEL_SHIFT) & DACC_USER_SEL_MASK;
00164 DACC_CHER |= BV(channel);
00165
00166 DACC_CDR = sample ;
00167
00168 return 0;
00169 }
00170
00171 static void sam3x_dac_setCh(struct Dac *dac, uint32_t mask)
00172 {
00173
00174 ASSERT(mask < BV(3));
00175 dac->hw->channels = mask;
00176
00177 if (mask & BV(DACC_CH0))
00178 DACC_MR |= (DACC_CH0 << DACC_USER_SEL_SHIFT) & DACC_USER_SEL_MASK;
00179
00180 if (mask & BV(DACC_CH1))
00181 DACC_MR |= (DACC_CH1 << DACC_USER_SEL_SHIFT) & DACC_USER_SEL_MASK;
00182
00183 DACC_CHER |= mask;
00184
00185 }
00186
00187 static void sam3x_dac_setSampleRate(struct Dac *dac, uint32_t rate)
00188 {
00189
00190 DACC_MR |= BV(DACC_TRGEN) | (CONFIG_DAC_TIMER << DACC_TRGSEL_SHIFT);
00191 dac->hw->rate = rate;
00192 }
00193
00194 static void sam3x_dac_conversion(struct Dac *dac, void *buf, size_t len)
00195 {
00196
00197 tc_setup(dac->hw->rate, len);
00198 tc_start();
00199
00200
00201 DACC_TPR = (uint32_t)buf;
00202 DACC_TCR = len;
00203 DACC_PTCR |= BV(DACC_PTCR_TXTEN);
00204 }
00205
00206 static uint16_t *sample_buff;
00207 static size_t next_idx = 0;
00208 static size_t chunk_size = 0;
00209 static size_t remaing_size = 0;
00210
00211 static DECLARE_ISR(irq_dac)
00212 {
00213 if (DACC_ISR & BV(DACC_ENDTX))
00214 {
00215 if (remaing_size > 0)
00216 {
00217 DACC_TNPR = (uint32_t)&sample_buff[next_idx];
00218 DACC_TNCR = chunk_size;
00219
00220 remaing_size -= chunk_size;
00221 next_idx += chunk_size;
00222 }
00223 else
00224
00225 DACC_TCR = 1;
00226 }
00227 event_do(&buff_emtpy);
00228 }
00229
00230
00231 static bool sam3x_dac_isFinished(struct Dac *dac)
00232 {
00233 return dac->hw->end;
00234 }
00235
00236 static void sam3x_dac_start(struct Dac *dac, void *_buf, size_t len, size_t slice_len)
00237 {
00238 ASSERT(dac);
00239 ASSERT(len >= slice_len);
00240
00241
00242 dac->hw->end = false;
00243
00244 sample_buff = (uint16_t *)_buf;
00245 next_idx = 0;
00246 chunk_size = slice_len;
00247 remaing_size = len;
00248
00249
00250
00251 dac->ctx.callback(dac, &sample_buff[0], chunk_size);
00252 DACC_TPR = (uint32_t)&sample_buff[0];
00253 DACC_TCR = chunk_size;
00254 remaing_size -= chunk_size;
00255 next_idx += chunk_size;
00256
00257 if (chunk_size <= remaing_size)
00258 {
00259 dac->ctx.callback(dac, &sample_buff[next_idx], chunk_size);
00260
00261 DACC_TNPR = (uint32_t)&sample_buff[next_idx];
00262 DACC_TNCR = chunk_size;
00263
00264 remaing_size -= chunk_size;
00265 next_idx += chunk_size;
00266
00267 }
00268
00269 DACC_PTCR |= BV(DACC_PTCR_TXTEN);
00270 DACC_IER = BV(DACC_ENDTX);
00271
00272
00273 tc_setup(dac->hw->rate, len);
00274 tc_start();
00275
00276 while (1)
00277 {
00278 event_wait(&buff_emtpy);
00279 if (remaing_size <= 0)
00280 {
00281 DAC_TC_CCR = BV(TC_CCR_CLKDIS);
00282 dac->hw->end = true;
00283 next_idx = 0;
00284 chunk_size = 0;
00285 remaing_size = 0;
00286 break;
00287 }
00288
00289 dac->ctx.callback(dac, &sample_buff[next_idx], chunk_size);
00290 }
00291 }
00292
00293 static void sam3x_dac_stop(struct Dac *dac)
00294 {
00295 dac->hw->end = false;
00296
00297 DACC_IDR = BV(DACC_ENDTX);
00298 DACC_PTCR |= BV(DACC_PTCR_TXTDIS);
00299 DAC_TC_CCR = BV(TC_CCR_CLKDIS);
00300 }
00301
00302
00303 void dac_init(struct Dac *dac)
00304 {
00305
00306 event_initGeneric(&buff_emtpy);
00307
00308
00309 dac->ctx.write = sam3x_dac_write;
00310 dac->ctx.setCh = sam3x_dac_setCh;
00311 dac->ctx.setSampleRate = sam3x_dac_setSampleRate;
00312 dac->ctx.conversion = sam3x_dac_conversion;
00313 dac->ctx.isFinished = sam3x_dac_isFinished;
00314 dac->ctx.start = sam3x_dac_start;
00315 dac->ctx.stop = sam3x_dac_stop;
00316 DB(dac->ctx._type = DAC_SAM3X;)
00317 dac->hw = &dac_hw;
00318
00319
00320 pmc_periphEnable(DACC_ID);
00321
00322
00323 DACC_CR |= BV(DACC_SWRST);
00324 DACC_MR = 0;
00325
00326
00327 DACC_MR |= (CONFIG_DAC_REFRESH << DACC_REFRESH_SHIFT) & DACC_REFRESH_MASK;
00328 DACC_MR |= (CONFIG_DAC_STARTUP << DACC_STARTUP_SHIFT) & DACC_STARTUP_MASK;
00329
00330 DACC_IDR = 0xFFFFFFFF;
00331 sysirq_setHandler(INT_DACC, irq_dac);
00332
00333 tc_init();
00334 }