You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

84 lines
3.0 KiB

  1. #include "config.h"
  2. #include "adc.h"
  3. #include "timer.h"
  4. /* Layout of buffer:
  5. adc_dmabuf[x] contains 16 samples of channel AN0
  6. */
  7. uint16_t adc_dmabuf[16] __attribute__((space(dma)));
  8. void (*adc_adc_callback)(void) = 0;
  9. void (*adc_dma_callback)(void) = 0;
  10. /* ADC1 interrupt after each sample (if enabled) */
  11. void __attribute__((__interrupt__,auto_psv)) _ADC1Interrupt(void)
  12. {
  13. if (adc_adc_callback)
  14. (*adc_adc_callback)();
  15. IFS0bits.AD1IF = 0;
  16. }
  17. /* DMA0 interrupt after 16 samples */
  18. void __attribute__((__interrupt__,auto_psv)) _DMA0Interrupt(void)
  19. {
  20. if (adc_dma_callback)
  21. (*adc_dma_callback)();
  22. IFS0bits.DMA0IF = 0;
  23. }
  24. /* Initialize ADC1 to constantly DMA AN0. */
  25. void adc_init(void)
  26. {
  27. /* AD1CON1 */
  28. AD1CON1bits.ADDMABM = 1; /* Scatter-gather DMA */
  29. AD1CON1bits.AD12B = 1; /* 12-bit, 1 channel */
  30. AD1CON1bits.FORM = 0; /* Integer output 0000dddddddddddd */
  31. AD1CON1bits.SSRC = 2; /* Convert on Timer3 */
  32. AD1CON1bits.ASAM = 1; /* Automatically start sampling */
  33. AD1CON1bits.SIMSAM = 0; /* Simul sampling, N/A when AD12B=1 */
  34. /* AD1CON2 */
  35. AD1CON2bits.VCFG = 0; /* Ref: AVDD / AVSS */
  36. // AD1CON2bits.VCFG = 3; /* Ref: VREF+ / VREF- */
  37. AD1CON2bits.CSCNA = 0; /* Do not scan inputs on Mux A */
  38. AD1CON2bits.CHPS = 0; /* Convert CH0 only, N/A when AD12B=1 */
  39. AD1CON2bits.SMPI = 0; /* Increase DMA address at each sample */
  40. AD1CON2bits.BUFM = 0; /* Fill buffer from start */
  41. AD1CON2bits.ALTS = 0; /* Always use Mux A settings */
  42. /* AD1CON3 */
  43. AD1CON3bits.ADRC = 0; /* Use system clock, not internal RC */
  44. AD1CON3bits.SAMC = 0; /* Sample time, N/A when ADRC = 0 */
  45. AD1CON3bits.ADCS = 0x7; /* Tad = 8 * Tcy */
  46. /* AD1CON4 */
  47. AD1CON4bits.DMABL = 4; /* Each input gets 16 words in DMA buf */
  48. /* Channel 0 setup */
  49. AD1CHS0bits.CH0NA = 0; /* CH0-: Vrefl */
  50. AD1CHS0bits.CH0SA = 0; /* CH0+: AN0 */
  51. /* Set Timer3 to trigger conversion at 128KHz */
  52. timer_setup_16bit(3, 128000, 0);
  53. /* Turn it on */
  54. AD1PCFGL = 0xfffe; /* Analog = AN0 */
  55. AD1PCFGH = 0xffff;
  56. AD2PCFGL = 0xffff;
  57. AD1CON1bits.ADON = 1;
  58. /* DMA0 setup */
  59. DMA0CONbits.AMODE = 0; /* Register indirect, post-increment */
  60. DMA0CONbits.MODE = 0; /* Continuous, no ping-pong */
  61. DMA0PAD = (int)&ADC1BUF0; /* Get addresses from ADC1 */
  62. DMA0CNT = 15; /* 16 transfers before wraparound */
  63. DMA0STA = __builtin_dmaoffset(&adc_dmabuf);
  64. DMA0REQbits.IRQSEL = 13; /* Triggered by ADC1 */
  65. IFS0bits.DMA0IF = 0;
  66. IEC0bits.DMA0IE = 1; /* DMA interrupt (every 16 samples) */
  67. DMA0CONbits.CHEN = 1; /* enable this DMA channel */
  68. IFS0bits.AD1IF = 0;
  69. IEC0bits.AD1IE = 0; /* No ADC interrupt (every sample) */
  70. }