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.
 
 
 
 

104 lines
2.4 KiB

  1. #include "config.h"
  2. #include "adc.h"
  3. /* The ADC (AD7846) is tricky, as new conversions start
  4. automatically when the previous data read finishes.
  5. To allow more control over start/read, we stretch the
  6. read indefinitely by delaying the final SCK edge.
  7. This means we can't have the hardware do SPI for us. */
  8. /* External serial clock, 2-wire I/O -- tie /EXT low,
  9. tie SDI for rate selection, tie /CS low, use BUSY for
  10. interrupt notification if desired */
  11. #define TRIS_SDO TRISEbits.TRISE7
  12. #define R_SDO PORTEbits.RE7
  13. #define TRIS_SCK TRISEbits.TRISE6
  14. #define LAT_SCK LATEbits.LATE6
  15. /* Short delays */
  16. #define wait_200ns() do { \
  17. nop(); nop(); nop(); nop(); nop(); nop(); nop(); nop(); \
  18. } while(0)
  19. #define wait_25ns() nop()
  20. /* Initialize ADC */
  21. void adc_init(void)
  22. {
  23. int i;
  24. TRIS_SDO = 1;
  25. LAT_SCK = 0;
  26. TRIS_SCK = 0;
  27. /* Startup delay CS down to SCK high t4 = 5000ns */
  28. for (i = 0; i < 5000 / 25; i++)
  29. wait_25ns();
  30. /* Trigger a dummy read so we're prepared for the
  31. next conversion */
  32. (void) adc_read();
  33. }
  34. /* Start a conversion if it hasn't already been started.
  35. Wait for conversion to finish.
  36. Read the result. */
  37. uint32_t adc_read(void)
  38. {
  39. uint32_t val;
  40. int i;
  41. /* Start conversion by completing previous read */
  42. LAT_SCK = 0;
  43. /* Wait tKQMAX for SCK down to SDO valid */
  44. wait_200ns();
  45. /* Wait for conversion to finish */
  46. while (R_SDO == 1)
  47. continue;
  48. /* Read it out */
  49. val = 0;
  50. for (i = 0; i < 32; i++) {
  51. /* SCK low tLESCK = 25ns */
  52. wait_25ns();
  53. LAT_SCK = 1;
  54. /* SCK high tHESCK = 25ns, but
  55. we also have SCK down to SDO valid tKQMAX = 200ns?
  56. Probably misspecified but wait tKQMAX anyway. */
  57. wait_200ns();
  58. val <<= 1;
  59. if (R_SDO)
  60. val |= 1;
  61. /* Leave SCK high on final bit to delay new conversion */
  62. if (i < 31)
  63. LAT_SCK = 0;
  64. }
  65. /* Done */
  66. return val;
  67. }
  68. /* Start a new conversion. If a conversion was already started
  69. but the result was not read, this does nothing. */
  70. void adc_start_conversion(void)
  71. {
  72. /* Start conversion by completing previous read */
  73. LAT_SCK = 0;
  74. /* Wait tKQMAX for SCK down to SDO valid in case we
  75. call adc_is_conversion_finished right away. */
  76. wait_200ns();
  77. }
  78. /* Return 1 if a conversion is in progress, 0 otherwise */
  79. int adc_is_conversion_finished(void)
  80. {
  81. if (LAT_SCK == 0 && R_SDO == 1)
  82. return 1;
  83. return 0;
  84. }