Commit | Line | Data |
---|---|---|
bba33fe1 JM |
1 | /******************************************************************************/ |
2 | /* Files to Include */ | |
3 | /******************************************************************************/ | |
4 | ||
5 | #if defined(__XC) | |
6 | #include <xc.h> /* XC8 General Include File */ | |
7 | #elif defined(HI_TECH_C) | |
8 | #include <htc.h> /* HiTech General Include File */ | |
9 | #endif | |
10 | ||
11 | #include <stdio.h> | |
12 | ||
13 | #include <stdint.h> /* For uint8_t definition */ | |
14 | #include <stdbool.h> /* For true/false definition */ | |
15 | ||
16 | #include "system.h" /* System funct/params, like osc/peripheral config */ | |
17 | #include "user.h" /* User funct/params, such as InitApp */ | |
18 | ||
19 | #include "onewire.h" /* 1-wire bus functions */ | |
20 | ||
21 | /******************************************************************************/ | |
22 | /* User Global Variable Declaration */ | |
23 | /******************************************************************************/ | |
24 | ||
25 | #define LED1 PORTAbits.RA4 | |
26 | ||
27 | /* i.e. uint8_t <variable_name>; */ | |
28 | ||
29 | char outbuff[100]; | |
30 | char * outp = 0; | |
31 | uint8_t outlen = 0; | |
32 | ||
33 | char inbuff[10]; | |
34 | uint8_t inlen = 0; | |
35 | ||
36 | /******************************************************************************/ | |
37 | /* Main Program */ | |
38 | /******************************************************************************/ | |
39 | ||
40 | char prompt[9]; | |
41 | ||
42 | // long time period counter, 572 steps is 5 minutes | |
43 | char automode = 0; | |
44 | uint16_t auto_counter = 0; | |
45 | ||
46 | void timer_rollover() | |
47 | { | |
48 | if (automode) auto_counter++; | |
49 | PIR1bits.TMR1IF = 0; | |
50 | } | |
51 | void timer_enable() { | |
52 | auto_counter = 0; | |
53 | automode = 1; | |
54 | T1CONbits.TMR1ON = 1; | |
55 | } | |
56 | ||
57 | void timer_disable() { | |
58 | automode = 0; | |
59 | T1CONbits.TMR1ON = 0; | |
60 | } | |
61 | ||
62 | const char * banner = "\r\n\n\nPIC 1-Wire Bridge system. Press 'H' for help.\r\n"; | |
63 | ||
64 | void main(void) | |
65 | { | |
66 | prompt[0] = 'c'; | |
67 | prompt[1] = 'm'; | |
68 | prompt[2] = 'd'; | |
69 | prompt[3] = ' '; | |
70 | prompt[4] = '?'; | |
71 | prompt[5] = '?'; | |
72 | prompt[6] = '>'; | |
73 | prompt[7] = ' '; | |
74 | prompt[8] = 0; | |
75 | ||
76 | bool usermode = false; | |
77 | ||
78 | /* Configure the oscillator for the device */ | |
79 | ConfigureOscillator(); | |
80 | ||
81 | /* Initialize I/O and Peripherals for application */ | |
82 | InitApp(); | |
83 | ||
84 | OW_start(); | |
85 | msg_write(banner); | |
86 | //msg_write(prompt); | |
87 | ||
88 | LED1 = 0; | |
89 | ||
90 | while(1) | |
91 | { | |
92 | CLRWDT(); | |
93 | ||
94 | if (TRISAbits.TRISA5 == 1) { | |
95 | prompt[4] = 'i'; | |
96 | prompt[5] = PORTAbits.RA5 ? '1':'0'; | |
97 | } else { | |
98 | prompt[4] = 'o'; | |
99 | prompt[5] = PORTAbits.RA5 ? '1':'0'; | |
100 | } | |
101 | ||
102 | ||
103 | if (!msg_empty()) continue; | |
104 | ||
105 | if (automode) { | |
106 | if (auto_counter >= 572) { | |
107 | inbuff[inlen++] = 't'; | |
108 | auto_counter = 0; | |
109 | } | |
110 | } | |
111 | ||
112 | if (!msg_recvready()) continue; | |
113 | ||
114 | char cmd = msg_recv(); | |
115 | ||
116 | if (cmd == '\r' || cmd == '\n') { | |
117 | if (usermode) msg_write("\r\n"); | |
118 | }else | |
119 | if (cmd == 'h' || cmd == 'H') { | |
120 | msg_write(banner); | |
121 | msg_write("\nHelp:\r\n"); | |
122 | while (!msg_empty()); | |
123 | msg_write("E - Enumerate the Bus\r\n"); | |
124 | msg_write("R - Reset Bus\r\n"); | |
125 | while (!msg_empty()); | |
126 | msg_write("0,1,3 - bus to Low, High, Tristate\r\n"); | |
127 | msg_write("I - Read (one) Device ID\r\n"); | |
128 | while (!msg_empty()); | |
129 | msg_write("P - Any device parasitic powered?\r\n"); | |
130 | msg_write("S - Read scratchpad memory\r\n"); | |
131 | while (!msg_empty()); | |
132 | msg_write("T - read temperature of all devices\r\n"); | |
133 | msg_write("A - Auto-mode. read every 5 mins.\r\n"); | |
134 | while (!msg_empty()); | |
135 | msg_write("M - Manual mode.\r\n"); | |
136 | msg_write("B - Test battery voltage\r\n"); | |
137 | while (!msg_empty()); | |
138 | usermode = true; | |
139 | } else | |
140 | if (cmd == 'a' || cmd == 'A') { | |
141 | if (usermode) | |
142 | msg_write("\rAUTO mode enabled. 5 minute timer.\r\n"); | |
143 | else | |
144 | msg_write("AUTO ON\n"); | |
145 | timer_enable(); | |
146 | } else | |
147 | if (cmd == 'm' || cmd == 'M') { | |
148 | if (usermode) | |
149 | msg_write("\rAUTO mode disabled.\r\n"); | |
150 | else | |
151 | msg_write("AUTO OFF\n"); | |
152 | timer_disable(); | |
153 | }else | |
154 | if (cmd == 'r' || cmd == 'R') { | |
155 | int_disable(); | |
156 | bool present = OW_reset(); | |
157 | int_enable(); | |
158 | if (usermode) msg_write("\r"); | |
159 | if (present) | |
160 | msg_write("RESET Device detected.\r\n"); | |
161 | else | |
162 | msg_write("RESET No Devices detected.\r\n"); | |
163 | } else | |
164 | if (cmd == 'e' || cmd == 'E') | |
165 | { | |
166 | char count = 0; | |
167 | if (usermode) msg_write("\r"); | |
168 | OW_search_init(); | |
169 | while (OW_search()) | |
170 | { | |
171 | char val[3]; | |
172 | if (usermode) msg_write("ENUM "); | |
173 | for (char j=0; j<8; j++) { | |
174 | tohex(val, romid[j]); | |
175 | msg_write(val); | |
176 | } | |
177 | if (usermode) msg_write("\r\n"); else msg_write("\n"); | |
178 | count++; | |
179 | } | |
180 | if (usermode) { | |
181 | if (count==0) msg_write("ERROR No devices found\r\n"); | |
182 | } else { | |
183 | msg_write("END\n"); | |
184 | } | |
185 | }else | |
186 | if (cmd == 'i' || cmd == 'I') { | |
187 | OW_identify(); | |
188 | char val[3]; | |
189 | if (usermode) msg_write("\rID "); | |
190 | for (char j=0; j<8; j++) { | |
191 | tohex(val, romid[j]); | |
192 | msg_write(val); | |
193 | } | |
194 | if (usermode) msg_write("\r\n"); else msg_write("\n"); | |
195 | }else | |
196 | if (cmd == 'p' || cmd == 'P') { | |
197 | if (usermode) msg_write("\r"); | |
198 | bool para = OW_parasite(); | |
199 | if (usermode) { | |
200 | if (para) | |
201 | msg_write("PARA Yes\r\n"); | |
202 | else | |
203 | msg_write("PARA No\r\n"); | |
204 | } else { | |
205 | if (para) msg_write("PARA\n"); else msg_write("DIRECT\n"); | |
206 | } | |
207 | }else | |
208 | if (cmd == 's' || cmd =='S') { | |
209 | uint8_t scratch[9]; | |
210 | romid[0] = 0; // select all devices | |
211 | OW_read_block(0xBE, scratch, 9); | |
212 | if (usermode) msg_write("\rSCRATCH"); | |
213 | for (char j=0; j<9; j++) { | |
214 | char val[3]; | |
215 | tohex(val, scratch[j]); | |
216 | msg_write(" "); | |
217 | msg_write(val); | |
218 | } | |
219 | if (usermode) msg_write("\r\n"); else msg_write("\n"); | |
220 | }else | |
221 | if (cmd == 't' || cmd == 'T') { | |
222 | char val[3]; | |
223 | uint8_t scratch[9]; | |
224 | ||
225 | // oddly, cant do a mass-convert with parasitic | |
226 | // they seem to all reset when you try | |
227 | ||
228 | LED1 = 1; | |
229 | ||
230 | // now step through every unit and read the value | |
231 | OW_search_init(); | |
232 | while (OW_search()) | |
233 | { | |
234 | // convert takes along time, dont trip watchdog | |
235 | CLRWDT(); | |
236 | // ask device to do conversion | |
237 | OW_convert(); | |
238 | CLRWDT(); | |
239 | ||
240 | // empty the scratch pad | |
241 | for (char j=0; j<9; j++) scratch[j]=0; | |
242 | ||
243 | // read this devices scratch pad | |
244 | OW_read_block(0xBE, scratch, 9); | |
245 | ||
246 | // print rom id and temperature | |
247 | if (usermode) msg_write("\r"); | |
248 | msg_write("TEMP "); | |
249 | for (char j=0;j<8;j++) { | |
250 | tohex(val, romid[j]); | |
251 | msg_write(val); | |
252 | } | |
253 | msg_write(" "); | |
254 | tohex(val, scratch[1]); | |
255 | msg_write(val); | |
256 | tohex(val, scratch[0]); | |
257 | msg_write(val); | |
258 | if (usermode) msg_write("\r\n"); else msg_write("\n"); | |
259 | } | |
260 | ||
261 | LED1 = 0; | |
262 | if (!usermode) msg_write("END\n"); | |
263 | ||
264 | }else | |
265 | if (cmd == '0') | |
266 | { | |
267 | drive_OW_low(); | |
268 | if (usermode) | |
269 | msg_write("\rBUS low\r\n"); | |
270 | else | |
271 | msg_write("LOW\n"); | |
272 | }else | |
273 | if (cmd == '1') | |
274 | { | |
275 | drive_OW_high(); | |
276 | if (usermode) | |
277 | msg_write("\rBUS high\r\n"); | |
278 | else | |
279 | msg_write("HIGH\n"); | |
280 | }else | |
281 | if (cmd == '3') | |
282 | { | |
283 | float_OW(); | |
284 | if (usermode) | |
285 | msg_write("\rBUS to tri-state\r\n"); | |
286 | else | |
287 | msg_write("TRISTATE\n"); | |
288 | }else | |
289 | if (cmd == '!') | |
290 | { | |
291 | // this is to test that the watchdog actually works | |
292 | msg_write("Play dead.\r\n"); | |
293 | while (1) { NOP(); } | |
294 | }else | |
295 | if (cmd == '?') | |
296 | { | |
297 | bool line = read_OW(); | |
298 | if (line) { | |
299 | if (usermode) msg_write("\rBUS HIGH\r\n"); | |
300 | else | |
301 | msg_write("HIGH\n"); | |
302 | } else { | |
303 | if (usermode) msg_write("\rBUS LOW\r\n"); | |
304 | else msg_write("LOW\n"); | |
305 | } | |
306 | }else | |
307 | if (cmd == 'b' || cmd == 'B') | |
308 | { | |
309 | // Read Vdd by sampling FVR | |
310 | FVRCONbits.ADFVR = 0b10; // 2.048v // 1.024v | |
311 | FVRCONbits.FVREN = 1; // enable | |
312 | while (!FVRCONbits.FVRRDY) {}; | |
313 | ADCON1bits.ADFM = 1; // right justify | |
314 | ADCON0bits.CHS = 0b11111; // FVR input | |
315 | ADCON1bits.ADPREF = 0b00; // +ve ref Vdd | |
316 | ADCON0bits.ADON = 1; // enable ADC | |
317 | ||
318 | ADCON0bits.GO = 1; // start conversion | |
319 | while (ADCON0bits.GO) {}; // wait til finished | |
320 | ||
321 | uint16_t volt = 0; | |
322 | volt = (ADRESH << 8) | ADRESL; | |
323 | uint16_t mv = (8192 / volt) * 1024; | |
324 | mv /= 8; | |
325 | ||
326 | msg_write("VOLTAGE "); | |
327 | char val[3]; | |
328 | tohex(val, ADRESH); | |
329 | msg_write(val); | |
330 | tohex(val, ADRESL); | |
331 | msg_write(val); | |
332 | msg_write("\n"); | |
333 | ||
334 | ADCON0bits.ADON = 0; // turn off ADC | |
335 | FVRCONbits.FVREN = 0; // turn of FVR | |
336 | }else | |
337 | { | |
338 | if (usermode) { | |
339 | msg_write("ERROR Press H for Help\n"); | |
340 | } else { | |
341 | msg_write("\rERROR Unknown command '"); | |
342 | msg_writebyte(cmd); | |
343 | msg_write("' Press 'H' for help.\r\n"); | |
344 | } | |
345 | } | |
346 | ||
347 | if (usermode) msg_write(prompt); | |
348 | } | |
349 | } | |
350 | ||
351 | /* make a hex string from a value | |
352 | * expect 3 char array */ | |
353 | void tohex(char val[], uint8_t i) | |
354 | { | |
355 | char bt = i >> 4; | |
356 | if (bt > 9) | |
357 | val[0] = 'A' + (bt - 10); | |
358 | else | |
359 | val[0] = '0' + bt; | |
360 | bt = i & 0x0F; | |
361 | if (bt > 9) | |
362 | val[1] = 'A' + (bt - 10); | |
363 | else | |
364 | val[1] = '0' + bt; | |
365 | val[2] = 0; | |
366 | } | |
367 | ||
368 | ||
369 | /* is the queue empty yet */ | |
370 | bool msg_empty(void) | |
371 | { | |
372 | if (outp == 0) return 1; | |
373 | return 0; | |
374 | } | |
375 | ||
376 | /* new message in the queue */ | |
377 | void msg_write(const char *msg) | |
378 | { | |
379 | char * p = outbuff + outlen; | |
380 | while (outlen < sizeof(outbuff) && *msg != 0) { | |
381 | *(p++) = *(msg++); | |
382 | outlen++; | |
383 | } | |
384 | *p = 0; | |
385 | if (outp == 0) { | |
386 | outp = outbuff; | |
387 | PIE1bits.TXIE = 1; | |
388 | } | |
389 | } | |
390 | ||
391 | void msg_writebyte(const char msg) | |
392 | { | |
393 | if (outlen+1 >= (uint8_t)sizeof(outbuff)) return; | |
394 | outbuff[outlen++] = msg; | |
395 | outbuff[outlen] = 0; | |
396 | if (outp == 0) { | |
397 | outp = outbuff; | |
398 | PIE1bits.TXIE = 1; | |
399 | } | |
400 | } | |
401 | ||
402 | void putch(char data) | |
403 | { | |
404 | msg_writebyte(data); | |
405 | } | |
406 | ||
407 | /* called from interrupt routine to send next char */ | |
408 | void msg_sendnext(void) | |
409 | { | |
410 | /* we have finished, turn off the iterrupt */ | |
411 | if (outp == 0 || *outp == 0) { | |
412 | PIE1bits.TXIE = 0; | |
413 | outp = 0; | |
414 | outlen = 0; | |
415 | return; | |
416 | } | |
417 | TXREG = *outp; | |
418 | outp++; | |
419 | } | |
420 | ||
421 | /* called from interrupt routine to receive next byte */ | |
422 | void msg_recvnext(void) | |
423 | { | |
424 | while (PIR1bits.RCIF) { | |
425 | bool err = RCSTAbits.FERR; | |
426 | char new = RCREG; | |
427 | ||
428 | /* bad char, skip it */ | |
429 | if (err) continue; | |
430 | ||
431 | /* our input buffer has overflowed */ | |
432 | if (inlen > sizeof(inbuff)) return; | |
433 | ||
434 | /* keep this one */ | |
435 | inbuff[inlen++] = new; | |
436 | } | |
437 | } | |
438 | ||
439 | bool msg_recvready(void) | |
440 | { | |
441 | if (inlen > 0) return 1; | |
442 | return 0; | |
443 | } | |
444 | ||
445 | char msg_recv(void) | |
446 | { | |
447 | if (inlen == 0) return 0; | |
448 | ||
449 | /* record and disable the interupt */ | |
450 | bool in = PIE1bits.RCIE; | |
451 | PIE1bits.RCIE = 0; | |
452 | ||
453 | char new = inbuff[0]; | |
454 | inlen--; | |
455 | ||
456 | /* shuffle them down one */ | |
457 | for (char i=0;i<inlen;i++) | |
458 | inbuff[i] = inbuff[i+1]; | |
459 | ||
460 | /* restore the interupt */ | |
461 | PIE1bits.RCIE = in; | |
462 | return new; | |
463 | } | |
464 | ||
465 | ||
466 | void int_disable(void) | |
467 | { | |
468 | INTCONbits.GIE = 0; | |
469 | } | |
470 | ||
471 | void int_enable(void) | |
472 | { | |
473 | INTCONbits.GIE = 1; | |
474 | } |