Demo.C 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486
  1. /*
  2. v3.0
  3. New board.
  4. - Less input noise
  5. - High range, high precision output voltage by using 2 DACS
  6. - Automatic gain and offset selection
  7. - Faster loop (<100microseconds after waveform acquisition is completed)
  8. */
  9. #include<ADuC7020.h>
  10. #include<stdlib.h>
  11. #include<stdio.h>
  12. #include<string.h>
  13. void My_IRQ_Handler(void);
  14. ///////////////////////////////////////
  15. // VARIABLE AND OPTION DEFINITIONS
  16. ///////////////////////////////////////
  17. short i = 0; // Dummy loop variables
  18. // I2C stuff
  19. unsigned char Byte_addr = 0;
  20. int first = 1;
  21. int i2c_cnt = 0;
  22. // BigDat stores the latest valid waveform
  23. // This is used so that if the acquisition is corrupted due to communication
  24. // with the board only data but not BigDat is corrupted
  25. #define BIGDAT_SZ 256
  26. unsigned short BigDat[BIGDAT_SZ];
  27. char text[512];
  28. // DAC outputs
  29. unsigned short Vout[4]; // DAC values, used via get_DACs and set_DACs
  30. unsigned short Vlearn; // Coarse output of the board when in learn mode
  31. double Vin, Vin_gnd; // Measurements of the signal and ground in the last waveform
  32. unsigned short start, stop; // Points at which to start and stop measuring the signal
  33. unsigned short start_gnd, stop_gnd; // Points at which to start and stop measuring the background
  34. unsigned short Vset; // Value measured in learn mode to which we aim to stabilize in lock mode
  35. unsigned short wf_len; // Number of points to measure
  36. unsigned short step_max; // Maximum fine output step allowed in one iteration of the loop
  37. unsigned short N; // Number of waveforms to average before stabilizing
  38. unsigned char transf; // i2c
  39. unsigned short enab_gnd; // Subtract the background from the signal in enab_gnd=1.
  40. unsigned short busy; // i2c
  41. unsigned short remote_trigg; // Set to 0 so that the microcontroller uses the trigger input,
  42. // set it to 1 so that it continuously triggers
  43. unsigned short auto_set_pga; // Whether the microcontroller should automatically select the
  44. // best offset and gain when in learn mode
  45. unsigned short coarse_fine_ratio; // Ratio of sensitivities of the fine to coarse voltage
  46. // outputs of the board
  47. unsigned short mode; // read_only; 0 when in learn; 1 when in lock
  48. unsigned short out_of_lock; // 1 when the board is out of lock
  49. unsigned int trigg_cnt; // Total number of triggers. Never reset, may overflow.
  50. unsigned long long int v_cnt; // Total number of Vout updates. Never reset, may overflow.
  51. unsigned long long int wf_cnt; // Total number of non-corrupted waveforms measured so far. May overflow.
  52. float Gain; // Gain of the feedback loop
  53. // pga_state is defined via = g*16+8 where g is such that the gain G
  54. // in the input measurements is G=2^g and G is one of {1, 2, 4, 8, 16, 32, 64, 128}
  55. // i.e. 0<g<7 or pga_state = {0x08, 0x18, 0x28, 0x38, 0x48, 0x58, 0x68, 0x78}
  56. unsigned char pga_state = 0x08; // gain 1 channel 8 default
  57. unsigned char * pbuff; // Pi communication
  58. unsigned char * plist[256];
  59. ///////////////////////////////////////
  60. // HELPER FUNCTIONS
  61. ///////////////////////////////////////
  62. // Dummy delay function
  63. void delay(int length) {
  64. while (length >= 0)
  65. length--;
  66. }
  67. // Conversion of the read value into it corresponding 12bits integer
  68. int ADCtoDAT(unsigned long ADC) {
  69. return (ADC & 0xFFF0000) >> 16;
  70. }
  71. // Conversion of 12bits integer into the corresponding ADC or DAC value
  72. unsigned long DATtoADC(int DAT) {
  73. unsigned long ADC;
  74. ADC = DAT;
  75. return ADC << 16;
  76. }
  77. unsigned long DATtoDAC(unsigned short DAT) {
  78. unsigned int ADC;
  79. ADC = DAT;
  80. return ADC << 16;
  81. }
  82. // Read GPIO pin P0.n. Return is either 0 (low) or (high)
  83. int Read_Digital(int n) {
  84. return ((GP0DAT & 0x000000FF) >> n) & 0x1;
  85. }
  86. // Write to GPIO pin P2.n. State is either 0 (low) or (high)
  87. void Write_Digital(int n, int state) {
  88. if (state == 1)
  89. GP2DAT = (0x00000001 << (n + 16)) | GP2DAT;
  90. else
  91. GP2DAT = ~((0x00000001 << (n + 16)) | (~GP2DAT));
  92. }
  93. // TO DO
  94. void ADCpoweron(int time) {
  95. ADCCON = 0x620; // power-on the ADC
  96. while (time >= 0) // wait for ADC to be fully powered on
  97. time--;
  98. }
  99. // Sync the values of the DACs with those stored in the array Vout
  100. // i.e. after changing the value in Vout[i] remember to call this
  101. void set_DACs(void) {
  102. DAC0DAT = DATtoDAC(Vout[0]);
  103. DAC1DAT = DATtoDAC(Vout[1]);
  104. DAC2DAT = DATtoDAC(Vout[2]);
  105. DAC3DAT = DATtoDAC(Vout[3]);
  106. }
  107. void get_DACs(void) {
  108. Vout[0] = DAC0DAT >> 16;
  109. Vout[1] = DAC1DAT >> 16;
  110. Vout[2] = DAC2DAT >> 16;
  111. Vout[3] = DAC3DAT >> 16;
  112. }
  113. // Sync the state of the pga with that stored in the pga_state
  114. // i.e. after changing the value of pga_state remember to call this
  115. void set_pga() {
  116. SPITX = 0x3A; // transmit command or any dummy data
  117. while ((SPISTA & 0x02) != 0x02); // wait for data received status bit
  118. SPITX = pga_state; // transmit command or any dummy data
  119. while ((SPISTA & 0x02) != 0x02); // wait for data received status bit
  120. }
  121. void get_pga() {
  122. SPITX = 0x7A; //0x3A; // transmit command or any dummy data
  123. while ((SPISTA & 0x02) != 0x02); // wait for data received status bit
  124. SPITX = 0; //pga_state; // transmit command or any dummy data
  125. while ((SPISTA & 0x02) != 0x02); // wait for data received status bit
  126. delay(500);
  127. SPITX = 0; //0x3A; // transmit command or any dummy data
  128. while ((SPISTA & 0x02) != 0x02); // wait for data received status bit
  129. SPITX = 0; //pga_state; // transmit command or any dummy data
  130. while ((SPISTA & 0x02) != 0x02); // wait for data received status bit
  131. }
  132. ///////////////////////////////////////
  133. // MAIN FUNCTION: LOCKING
  134. ///////////////////////////////////////
  135. void lock_StabPulse_i2c(void) {
  136. // DEFINITIONS AND INITIALIZATION //////////////////////
  137. unsigned int cnt_N; // Number of non-corrupted waveforms measured
  138. unsigned long int sum, sum_gnd; // Sum of the points in the signal and background
  139. unsigned short Vout0, Vout1, Vout2; // Used to set the DACs
  140. // Vout0: input offset; Vout1: coarse output; Vout2: fine output
  141. int step = 100; // Step to move by in the loop, dummy initialization
  142. short armed; // This is used to detect the trigger :
  143. // when the trigger input is low armed is set to 1
  144. // when a measurement start it is set to 0
  145. short valid_data; //
  146. register int k; // Dummy loop variable
  147. unsigned short Data[256]; // Waveform measurement
  148. //
  149. POWKEY1 = 0x01;
  150. POWCON = 0x00; // 41.78MHz
  151. POWKEY2 = 0xF4;
  152. // ADC&DAC setting
  153. ADCpoweron(20000); // power on ADC
  154. REFCON = 0x01; // internal 2.5V reference
  155. DAC0CON = 0x12; // AGND-ARef range 0x12 2.5V
  156. DAC1CON = 0x12; // AGND-ARef range 0x12 2.5V
  157. DAC2CON = 0x12; // AGND-ARef range 0x12 2.5V
  158. DAC3CON = 0x12; // AGND-ARef range 0x12 2.5V
  159. ADCCP = 0x03; // conversion on ADC0
  160. ADCCON = 0x3E4; // continuous conversion
  161. // IO setting
  162. GP2CON = 0x00000000; // IO initialization
  163. GP2DAT = 0xFF000000; // set P2.n as digital output
  164. GP0CON = 0x00000000; // IO initialization
  165. GP0DAT = 0x00000000; // set P0.n as digital input
  166. // Initialize locking parameter defaults
  167. // This will likely be selected using the Pi
  168. N = 10;
  169. Vin = 0;
  170. Vin_gnd = 0;
  171. start = 100;
  172. stop = 200;
  173. start_gnd = 0;
  174. stop_gnd = 100;
  175. wf_len = 200;
  176. Vset = 0;
  177. Vlearn = 2000;
  178. step = 50;
  179. step_max = 100;
  180. Gain = 1;
  181. transf = 0;
  182. trigg_cnt = 0;
  183. wf_cnt = 0;
  184. v_cnt = 0;
  185. cnt_N = 0;
  186. enab_gnd = 0;
  187. remote_trigg = 0;
  188. auto_set_pga = 0;
  189. mode = 0; //read only
  190. out_of_lock = 0;
  191. coarse_fine_ratio = 20; //As per circuit design; can be tuned by Pi
  192. valid_data = 0;
  193. // SPI configuration
  194. GP1CON = 0x22220022; // configure SPI such the P1.0 and P1.1 are set for I2C0
  195. // P1.2 and P1.3 are set for GPIO (connected on 50Ohms driver TTL)
  196. // P1.4-7 on SPI
  197. SPIDIV = 0xCC; // set SPI clock 40960000/(2x(1+SPIDIV))
  198. // 0xCC = 100kHz
  199. SPICON = 0x1043; // enable SPI master in continuous transfer mode
  200. // slave select will stay low during the all transmission
  201. IRQ = My_IRQ_Handler;
  202. IRQEN = 0x200; // I2C0 Slave Interupt
  203. I2C0CFG = 0x04001;
  204. // Slave ID
  205. I2C0ID0 = (0x50) << 1; //(0x50 + (((GP0DAT&0x000000FF)>>5)&0x1)+(((GP0DAT&0x000000FF)>>7)&0x1)*2)<<1;
  206. I2C0STX = 0x00;
  207. I2C0STX = 0x00;
  208. // assignation of the different pointers for the I2C exchange of data
  209. for (k = 0; k < 16; k++) {
  210. plist[k] = (unsigned char * )(BigDat + k * 16);
  211. plist[k + 50] = (unsigned char * )(text + k * 32);
  212. }
  213. for (i = 0; i < BIGDAT_SZ; i++)
  214. BigDat[i] = 0;
  215. sprintf(text, "pulse stabilization v2.0 => %s\ncompiled: %s\nbecause we can!", __func__, __DATE__);
  216. for (k = 0; k < 4; k++) {
  217. plist[100 + k] = (unsigned char * )(Vout + k);
  218. }
  219. // 104 to execute the function get_DACs
  220. // 105 to execute the function set_DACs
  221. plist[110] = (unsigned char * ) & Vlearn;
  222. plist[111] = (unsigned char * ) & Vin;
  223. plist[112] = (unsigned char * ) & Vin_gnd;
  224. plist[113] = (unsigned char * ) & wf_cnt;
  225. plist[114] = (unsigned char * ) & v_cnt;
  226. plist[115] = (unsigned char * ) & remote_trigg;
  227. plist[120] = (unsigned char * ) & I2C0ID0;
  228. plist[121] = (unsigned char * ) & ADCCP;
  229. plist[122] = (unsigned char * ) & transf;
  230. plist[123] = (unsigned char * ) & wf_len;
  231. plist[124] = (unsigned char * ) & trigg_cnt;
  232. plist[125] = (unsigned char * ) & Vset;
  233. plist[126] = (unsigned char * ) & N;
  234. plist[127] = (unsigned char * ) & start;
  235. plist[128] = (unsigned char * ) & stop;
  236. //plist[129] = (unsigned char*)&start2; //not in use
  237. //plist[130] = (unsigned char*)&stop2; //not in use
  238. plist[129] = (unsigned char * ) & auto_set_pga;
  239. plist[130] = (unsigned char * ) & coarse_fine_ratio;
  240. plist[131] = (unsigned char * ) & start_gnd;
  241. plist[132] = (unsigned char * ) & stop_gnd;
  242. plist[133] = (unsigned char * ) & enab_gnd;
  243. plist[134] = (unsigned char * ) & Gain;
  244. plist[135] = (unsigned char * ) & step_max;
  245. plist[136] = (unsigned char * ) & pga_state;
  246. // 137; 138 for running set_pga and get_pga commands
  247. plist[139] = (unsigned char * ) & mode;
  248. plist[140] = (unsigned char * ) & coarse_fine_ratio;
  249. plist[141] = (unsigned char * ) & out_of_lock;
  250. // Dummy DAC initialization
  251. DAC0DAT = DATtoADC(10);
  252. DAC1DAT = DATtoADC(20);
  253. DAC2DAT = DATtoADC(2000);
  254. DAC3DAT = DATtoADC(40);
  255. Vout[3] = 111;
  256. set_DACs();
  257. // LOOP FOR LEARNING AND LOCKING //////////////////////
  258. while (1) {
  259. // trigg in is on p0.3 => we check that it is low first (rising edge detection)
  260. if ((((GP0DAT & 0x000000FF) >> 3) & 0x1) == 0) {
  261. armed = 1;
  262. }
  263. // now p0.3 is high => this is our rising edge
  264. if (((((GP0DAT & 0x000000FF) >> 3) & 0x1) == 1 && armed == 1) || remote_trigg) {
  265. armed = 0;
  266. trigg_cnt++;
  267. // Measure signal
  268. for (k = 0; k < wf_len; k++) {
  269. while (!ADCSTA) {} // wait for the end of ADC conversion
  270. Data[k] = (unsigned short)(ADCDAT >> 16); // read voltage from ADC0
  271. }
  272. if (busy == 0) { // supposed to guaranty that no i2c transfer has been performed during the wf acquisition
  273. //*** copy for the i2c ***
  274. memcpy(BigDat, Data, 256 * sizeof(short)); // Takes around 20 microseconds
  275. wf_cnt++;
  276. cnt_N++;
  277. //sum of the data
  278. for (k = start; k < stop; k++) {
  279. sum += Data[k];
  280. }
  281. for (k = start_gnd; k < stop_gnd; k++) {
  282. sum_gnd += Data[k];
  283. }
  284. // If we have already measured the N waveforms we need, find
  285. if (cnt_N >= N) { // Can take up to 80 microseconds
  286. Vin = ((double) sum) / (cnt_N * (stop - start)); // calculate signal average value
  287. Vin_gnd = ((double) sum_gnd) / (cnt_N * (stop_gnd - start_gnd)); // calculate background average value
  288. valid_data = 1;
  289. v_cnt++;
  290. sum = 0; // re-initialization of the measurement
  291. sum_gnd = 0;
  292. cnt_N = 0;
  293. }
  294. } else busy = 0;
  295. //*** feedback *** (mode is on pin p0.6)
  296. // LOCK MODE
  297. if ((((GP0DAT & 0x000000FF) >> 6) & 0x1) == 1) {
  298. mode = 1; // Locking
  299. if (valid_data == 1) {
  300. valid_data = 0; // Restart measurements
  301. cnt_N = 0;
  302. // Calculate necessary step and update fine output
  303. step = (Vset - Vin + Vin_gnd * enab_gnd) * Gain;
  304. if (step > step_max)
  305. step = step_max;
  306. else if (step < -step_max)
  307. step = -step_max;
  308. Vout2 = Vout2 + step;
  309. // Adjust coarse output if necessary
  310. if (Vout2 < 2000 || Vout2 > 4000) {
  311. Vout1 = Vout1 + (Vout2 - 3000) / coarse_fine_ratio;
  312. Vout2 = 3000;
  313. }
  314. // Check if we're out of range
  315. if (Vout1 > 4095) {
  316. out_of_lock = 1;
  317. Write_Digital(0, 1);
  318. Vout1 = 4095;
  319. } else {
  320. out_of_lock = 0;
  321. Write_Digital(0, 0);
  322. }
  323. // Set output
  324. DAC1DAT = DATtoADC(Vout1); // output voltage, coarse
  325. DAC2DAT = DATtoADC(Vout2); // output voltage, fine
  326. }
  327. }
  328. // LEARN MODE
  329. else {
  330. mode = 0; // Learning
  331. // Save the current input level as the set point of the next locking
  332. if (valid_data == 1) {
  333. valid_data = 0;
  334. Vset = Vin - Vin_gnd * enab_gnd;
  335. cnt_N = 0;
  336. }
  337. Vout1 = Vlearn; // Coarse output = Vlearn, fine output is free.
  338. // Automatically find input gain and offset
  339. if (auto_set_pga == 1) {
  340. get_DACs();
  341. Vout0 = Vout[0];
  342. if (Vin_gnd < 30 && Vout0 < 4095) { //may clip, shift up
  343. Vout0++;
  344. DAC0DAT = DATtoADC(Vout0);
  345. } else if (Vin_gnd > 100 && Vout0 > 0) { //shift down
  346. Vout0--;
  347. DAC0DAT = DATtoADC(Vout0);
  348. } else if (Vin > 4000) { //too big, may clip
  349. if ((pga_state - 8) / 16 > 0) pga_state -= 16;
  350. set_pga();
  351. //else: too big even with no gain?
  352. } else if (Vin < 2000) { //too small
  353. if ((pga_state - 8) / 16 < 7) pga_state += 16;
  354. set_pga();
  355. }
  356. }
  357. // Set output
  358. DAC1DAT = DATtoADC(Vout1);
  359. // Do not set Vout2 so that we can scan it
  360. }
  361. }
  362. }
  363. }
  364. int main(void) {
  365. lock_StabPulse_i2c();
  366. return 0;
  367. }
  368. ///////////////////////////////////////
  369. // IRQ Service Routine
  370. ///////////////////////////////////////
  371. void My_IRQ_Handler() {
  372. int status = I2C0SSTA;
  373. busy = 1;
  374. // Slave Recieve
  375. if ((status & 0x08) == 0x08) {
  376. if (first == 1) {
  377. first = 0;
  378. Byte_addr = I2C0SRX;
  379. I2C0FSTA |= 1 << 8;
  380. i2c_cnt = 0;
  381. if (Byte_addr == 122)
  382. transf = 1;
  383. if (Byte_addr == 104)
  384. get_DACs();
  385. if (Byte_addr == 105)
  386. set_DACs();
  387. if (Byte_addr == 137)
  388. set_pga();
  389. if (Byte_addr == 138)
  390. get_pga();
  391. //Write_Digital(2, 0);
  392. pbuff = plist[Byte_addr];
  393. I2C0STX = pbuff[0];
  394. } else {
  395. pbuff[i2c_cnt] = I2C0SRX;
  396. i2c_cnt++;
  397. }
  398. }
  399. // Slave Transmit
  400. else if ((status & 0x04) == 0x04) // Slave Transmit IRQ
  401. {
  402. i2c_cnt++;
  403. I2C0STX = pbuff[i2c_cnt];
  404. I2C0ADR = 0xA1;
  405. //if(Byte_addr>=110 && Byte_addr<=113 && i2c_cnt==1)
  406. //set_DACs();
  407. } else if ((status & 0x0400) == 0x0400) //
  408. {
  409. first = 1;
  410. //Write_Digital(2,1);
  411. }
  412. busy = 1;
  413. }