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.
 
 
 
 

235 lines
4.3 KiB

  1. #include "config.h"
  2. #include "adc.h"
  3. #include "adcext.h"
  4. #include "dac.h"
  5. #include "uart.h"
  6. #include "timer.h"
  7. #include <stdio.h>
  8. #include <math.h>
  9. #include "scaling.h"
  10. #include "util.h"
  11. int send_data = 0;
  12. uint16_t send_adc;
  13. uint16_t send_dac;
  14. int possible_overflow = 0;
  15. #define DAC_MIN 0x0000
  16. #define DAC_MAX 0xFFFF
  17. float dac_current;
  18. float dac_current_min;
  19. float dac_current_max;
  20. #define TIMER_RATE 8000 /* how often to read the ADC and update DAC */
  21. #define PC_RATE 8000 /* how often to send data to the PC */
  22. void TISR_HANDLER(5)
  23. {
  24. static int count = 0;
  25. static uint16_t dac_cmd;
  26. uint16_t v;
  27. float i;
  28. /* toggle A9 every time an interrupt occurs */
  29. LATAbits.LATA9 ^= 1;
  30. timer_clear_txif(5);
  31. /* Get most recent sample from 12-bit ADC. */
  32. v = adc_get();
  33. if (v < 0 || v >= 2047)
  34. possible_overflow = 1;
  35. /* Send data to PC at 1 Hz */
  36. if (++count >= (TIMER_RATE / PC_RATE)) {
  37. count = 0;
  38. /* Send most recent sample and old DAC value */
  39. send_adc = v;
  40. send_dac = dac_cmd;
  41. send_data = 1;
  42. }
  43. /* Convert ADC value to current */
  44. i = adc12_to_current(v);
  45. /* Adjust DAC to null this current to 0 */
  46. dac_current -= i;
  47. if (dac_current < dac_current_min)
  48. dac_current = dac_current_min;
  49. if (dac_current > dac_current_max)
  50. dac_current = dac_current_max;
  51. /* Now send it out */
  52. dac_cmd = current_to_dac(dac_current);
  53. dac_write(dac_cmd);
  54. }
  55. void send_to_pc(uint16_t adc, uint16_t dac)
  56. {
  57. /* Sent data format:
  58. 1Aaa aaaa 0aaa aaDd 0ddd dddd 0ddd dddd
  59. Aaaaaaaaaaaa = 12-bit ADC value (2s compliment signed)
  60. Dddddddddddddddd = 16-bit DAC command (unsigned)
  61. */
  62. uart1_put(0x80 | ((adc & 0x0FE0) >> 5));
  63. uart1_put(((adc & 0x001F) << 2) | ((dac & 0xC000) >> 14));
  64. uart1_put((dac & 0x3F80) >> 7);
  65. uart1_put((dac & 0x007F));
  66. }
  67. void degauss(void)
  68. {
  69. dac_write(65535); /* max */
  70. msleep(25);
  71. dac_write(0); /* min */
  72. msleep(25);
  73. dac_write(32768); /* middle */
  74. msleep(25);
  75. }
  76. void run_debug(void)
  77. {
  78. uint16_t dac = 32768;
  79. int16_t adc;
  80. int32_t v;
  81. char buf[4];
  82. uart1_init(115200);
  83. uart1_put_string("Zoom NILM Debug\r\n");
  84. while (1) {
  85. dac_write(dac);
  86. uart1_put_dec(dac);
  87. uart1_put(' ');
  88. adc = adc_get();
  89. uart1_put_hex16(adc);
  90. uart1_put(' ');
  91. uart1_put_dec(adc);
  92. uart1_crlf();
  93. switch (uart1_get()) {
  94. case '[':
  95. dac--;
  96. break;
  97. case ']':
  98. dac++;
  99. break;
  100. case '-':
  101. dac -= 16;
  102. break;
  103. case '+':
  104. case '=':
  105. dac += 16;
  106. break;
  107. case ',':
  108. case '<':
  109. dac -= 1024;
  110. break;
  111. case '.':
  112. case '>':
  113. dac += 1024;
  114. break;
  115. case '0':
  116. dac = 32768;
  117. break;
  118. case 'd':
  119. uart1_put_string("degauss...");
  120. degauss();
  121. uart1_crlf();
  122. dac = 32768;
  123. break;
  124. case 'v':
  125. case 'V':
  126. buf[0] = uart1_get();
  127. buf[1] = uart1_get();
  128. buf[2] = uart1_get();
  129. buf[3] = uart1_get();
  130. v = hex_to_u16(buf);
  131. if (v < 0)
  132. uart1_put_string("bad value\r\n");
  133. else
  134. dac = v;
  135. break;
  136. }
  137. }
  138. }
  139. void run_normal(void)
  140. {
  141. uart1_init(500000);
  142. /* Assume startup current is 0 */
  143. dac_current = 0.0;
  144. dac_write(current_to_dac(dac_current));
  145. msleep(100);
  146. degauss();
  147. /* Set min/max */
  148. dac_current_min = dac_to_current(DAC_MIN);
  149. dac_current_max = dac_to_current(DAC_MAX);
  150. timer_setup_16bit(5, TIMER_RATE, 1);
  151. while(1) {
  152. if (send_data) {
  153. /* There's data to send. Disable the ISR briefly
  154. while we grab it */
  155. uint16_t a, d;
  156. disable_int({
  157. if (possible_overflow) {
  158. /* Mark a possible overflow in the output
  159. by setting ADC to an unlikely value */
  160. possible_overflow = 0;
  161. a = 0x0800;
  162. } else {
  163. a = send_adc;
  164. }
  165. d = send_dac;
  166. send_data = 0;
  167. });
  168. send_to_pc(a, d);
  169. }
  170. }
  171. }
  172. /* This mode is used when the programmer is connected,
  173. or PGD is tied to ground (jumper between ICD pins 3 and 4) */
  174. #define MODE_1 run_normal
  175. /* This mode is used when the programmer is not connected
  176. and PGD is left floating */
  177. #define MODE_2 run_debug
  178. int main(void)
  179. {
  180. config_init();
  181. /* Pull PGD high internally. */
  182. TRISCbits.TRISC13 = 1;
  183. CNPU1bits.CN1PUE = 1;
  184. /* Output RA9 (PICVREF-) is used for debugging */
  185. TRISAbits.TRISA9 = 0;
  186. adcext_init();
  187. dac_init();
  188. dac_write(32768);
  189. adc_init();
  190. msleep(100);
  191. degauss();
  192. /* If PGD is externally tied to ground, use MODE_1
  193. (Short ICD pins 3 and 4) */
  194. if (PORTCbits.RC13 == 0)
  195. MODE_1();
  196. else
  197. MODE_2();
  198. for (;;)
  199. continue;
  200. }