Initial import of onewire-to-usb bridge
[onewire] / main.c
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 }