/******************************************************************************/ /* Files to Include */ /******************************************************************************/ #if defined(__XC) #include /* XC8 General Include File */ #elif defined(HI_TECH_C) #include /* HiTech General Include File */ #endif #include #include /* For uint8_t definition */ #include /* For true/false definition */ #include "system.h" /* System funct/params, like osc/peripheral config */ #include "user.h" /* User funct/params, such as InitApp */ #include "onewire.h" /* 1-wire bus functions */ /******************************************************************************/ /* User Global Variable Declaration */ /******************************************************************************/ #define LED1 PORTAbits.RA4 /* i.e. uint8_t ; */ char outbuff[100]; char * outp = 0; uint8_t outlen = 0; char inbuff[10]; uint8_t inlen = 0; /******************************************************************************/ /* Main Program */ /******************************************************************************/ char prompt[9]; // long time period counter, 572 steps is 5 minutes char automode = 0; uint16_t auto_counter = 0; void timer_rollover() { if (automode) auto_counter++; PIR1bits.TMR1IF = 0; } void timer_enable() { auto_counter = 0; automode = 1; T1CONbits.TMR1ON = 1; } void timer_disable() { automode = 0; T1CONbits.TMR1ON = 0; } const char * banner = "\r\n\n\nPIC 1-Wire Bridge system. Press 'H' for help.\r\n"; void main(void) { prompt[0] = 'c'; prompt[1] = 'm'; prompt[2] = 'd'; prompt[3] = ' '; prompt[4] = '?'; prompt[5] = '?'; prompt[6] = '>'; prompt[7] = ' '; prompt[8] = 0; bool usermode = false; /* Configure the oscillator for the device */ ConfigureOscillator(); /* Initialize I/O and Peripherals for application */ InitApp(); OW_start(); msg_write(banner); //msg_write(prompt); LED1 = 0; while(1) { CLRWDT(); if (TRISAbits.TRISA5 == 1) { prompt[4] = 'i'; prompt[5] = PORTAbits.RA5 ? '1':'0'; } else { prompt[4] = 'o'; prompt[5] = PORTAbits.RA5 ? '1':'0'; } if (!msg_empty()) continue; if (automode) { if (auto_counter >= 572) { inbuff[inlen++] = 't'; auto_counter = 0; } } if (!msg_recvready()) continue; char cmd = msg_recv(); if (cmd == '\r' || cmd == '\n') { if (usermode) msg_write("\r\n"); }else if (cmd == 'h' || cmd == 'H') { msg_write(banner); msg_write("\nHelp:\r\n"); while (!msg_empty()); msg_write("E - Enumerate the Bus\r\n"); msg_write("R - Reset Bus\r\n"); while (!msg_empty()); msg_write("0,1,3 - bus to Low, High, Tristate\r\n"); msg_write("I - Read (one) Device ID\r\n"); while (!msg_empty()); msg_write("P - Any device parasitic powered?\r\n"); msg_write("S - Read scratchpad memory\r\n"); while (!msg_empty()); msg_write("T - read temperature of all devices\r\n"); msg_write("A - Auto-mode. read every 5 mins.\r\n"); while (!msg_empty()); msg_write("M - Manual mode.\r\n"); msg_write("B - Test battery voltage\r\n"); while (!msg_empty()); usermode = true; } else if (cmd == 'a' || cmd == 'A') { if (usermode) msg_write("\rAUTO mode enabled. 5 minute timer.\r\n"); else msg_write("AUTO ON\n"); timer_enable(); } else if (cmd == 'm' || cmd == 'M') { if (usermode) msg_write("\rAUTO mode disabled.\r\n"); else msg_write("AUTO OFF\n"); timer_disable(); }else if (cmd == 'r' || cmd == 'R') { int_disable(); bool present = OW_reset(); int_enable(); if (usermode) msg_write("\r"); if (present) msg_write("RESET Device detected.\r\n"); else msg_write("RESET No Devices detected.\r\n"); } else if (cmd == 'e' || cmd == 'E') { char count = 0; if (usermode) msg_write("\r"); OW_search_init(); while (OW_search()) { char val[3]; if (usermode) msg_write("ENUM "); for (char j=0; j<8; j++) { tohex(val, romid[j]); msg_write(val); } if (usermode) msg_write("\r\n"); else msg_write("\n"); count++; } if (usermode) { if (count==0) msg_write("ERROR No devices found\r\n"); } else { msg_write("END\n"); } }else if (cmd == 'i' || cmd == 'I') { OW_identify(); char val[3]; if (usermode) msg_write("\rID "); for (char j=0; j<8; j++) { tohex(val, romid[j]); msg_write(val); } if (usermode) msg_write("\r\n"); else msg_write("\n"); }else if (cmd == 'p' || cmd == 'P') { if (usermode) msg_write("\r"); bool para = OW_parasite(); if (usermode) { if (para) msg_write("PARA Yes\r\n"); else msg_write("PARA No\r\n"); } else { if (para) msg_write("PARA\n"); else msg_write("DIRECT\n"); } }else if (cmd == 's' || cmd =='S') { uint8_t scratch[9]; romid[0] = 0; // select all devices OW_read_block(0xBE, scratch, 9); if (usermode) msg_write("\rSCRATCH"); for (char j=0; j<9; j++) { char val[3]; tohex(val, scratch[j]); msg_write(" "); msg_write(val); } if (usermode) msg_write("\r\n"); else msg_write("\n"); }else if (cmd == 't' || cmd == 'T') { char val[3]; uint8_t scratch[9]; // oddly, cant do a mass-convert with parasitic // they seem to all reset when you try LED1 = 1; // now step through every unit and read the value OW_search_init(); while (OW_search()) { // convert takes along time, dont trip watchdog CLRWDT(); // ask device to do conversion OW_convert(); CLRWDT(); // empty the scratch pad for (char j=0; j<9; j++) scratch[j]=0; // read this devices scratch pad OW_read_block(0xBE, scratch, 9); // print rom id and temperature if (usermode) msg_write("\r"); msg_write("TEMP "); for (char j=0;j<8;j++) { tohex(val, romid[j]); msg_write(val); } msg_write(" "); tohex(val, scratch[1]); msg_write(val); tohex(val, scratch[0]); msg_write(val); if (usermode) msg_write("\r\n"); else msg_write("\n"); } LED1 = 0; if (!usermode) msg_write("END\n"); }else if (cmd == '0') { drive_OW_low(); if (usermode) msg_write("\rBUS low\r\n"); else msg_write("LOW\n"); }else if (cmd == '1') { drive_OW_high(); if (usermode) msg_write("\rBUS high\r\n"); else msg_write("HIGH\n"); }else if (cmd == '3') { float_OW(); if (usermode) msg_write("\rBUS to tri-state\r\n"); else msg_write("TRISTATE\n"); }else if (cmd == '!') { // this is to test that the watchdog actually works msg_write("Play dead.\r\n"); while (1) { NOP(); } }else if (cmd == '?') { bool line = read_OW(); if (line) { if (usermode) msg_write("\rBUS HIGH\r\n"); else msg_write("HIGH\n"); } else { if (usermode) msg_write("\rBUS LOW\r\n"); else msg_write("LOW\n"); } }else if (cmd == 'b' || cmd == 'B') { // Read Vdd by sampling FVR FVRCONbits.ADFVR = 0b10; // 2.048v // 1.024v FVRCONbits.FVREN = 1; // enable while (!FVRCONbits.FVRRDY) {}; ADCON1bits.ADFM = 1; // right justify ADCON0bits.CHS = 0b11111; // FVR input ADCON1bits.ADPREF = 0b00; // +ve ref Vdd ADCON0bits.ADON = 1; // enable ADC ADCON0bits.GO = 1; // start conversion while (ADCON0bits.GO) {}; // wait til finished uint16_t volt = 0; volt = (ADRESH << 8) | ADRESL; uint16_t mv = (8192 / volt) * 1024; mv /= 8; msg_write("VOLTAGE "); char val[3]; tohex(val, ADRESH); msg_write(val); tohex(val, ADRESL); msg_write(val); msg_write("\n"); ADCON0bits.ADON = 0; // turn off ADC FVRCONbits.FVREN = 0; // turn of FVR }else { if (usermode) { msg_write("ERROR Press H for Help\n"); } else { msg_write("\rERROR Unknown command '"); msg_writebyte(cmd); msg_write("' Press 'H' for help.\r\n"); } } if (usermode) msg_write(prompt); } } /* make a hex string from a value * expect 3 char array */ void tohex(char val[], uint8_t i) { char bt = i >> 4; if (bt > 9) val[0] = 'A' + (bt - 10); else val[0] = '0' + bt; bt = i & 0x0F; if (bt > 9) val[1] = 'A' + (bt - 10); else val[1] = '0' + bt; val[2] = 0; } /* is the queue empty yet */ bool msg_empty(void) { if (outp == 0) return 1; return 0; } /* new message in the queue */ void msg_write(const char *msg) { char * p = outbuff + outlen; while (outlen < sizeof(outbuff) && *msg != 0) { *(p++) = *(msg++); outlen++; } *p = 0; if (outp == 0) { outp = outbuff; PIE1bits.TXIE = 1; } } void msg_writebyte(const char msg) { if (outlen+1 >= (uint8_t)sizeof(outbuff)) return; outbuff[outlen++] = msg; outbuff[outlen] = 0; if (outp == 0) { outp = outbuff; PIE1bits.TXIE = 1; } } void putch(char data) { msg_writebyte(data); } /* called from interrupt routine to send next char */ void msg_sendnext(void) { /* we have finished, turn off the iterrupt */ if (outp == 0 || *outp == 0) { PIE1bits.TXIE = 0; outp = 0; outlen = 0; return; } TXREG = *outp; outp++; } /* called from interrupt routine to receive next byte */ void msg_recvnext(void) { while (PIR1bits.RCIF) { bool err = RCSTAbits.FERR; char new = RCREG; /* bad char, skip it */ if (err) continue; /* our input buffer has overflowed */ if (inlen > sizeof(inbuff)) return; /* keep this one */ inbuff[inlen++] = new; } } bool msg_recvready(void) { if (inlen > 0) return 1; return 0; } char msg_recv(void) { if (inlen == 0) return 0; /* record and disable the interupt */ bool in = PIE1bits.RCIE; PIE1bits.RCIE = 0; char new = inbuff[0]; inlen--; /* shuffle them down one */ for (char i=0;i