/*********************************************************************************************************************** MMBasic Onewire.c Handles all the commands and functions related to One Wire support. The one wire support is based on code from Dallas Semiconductor Corporation: Copyright 2012 Gerard Sexton This file is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Copyright (C) 1999-2006 Dallas Semiconductor Corporation, All Rights Reserved. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL DALLAS SEMICONDUCTOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ************************************************************************************************************************/ /** * @file Onewire.c * @author Geoff Graham, Peter Mather * @brief Source for GPS MMBasic function */ /** * @cond * The following section will be excluded from the documentation. */ #define _SUPPRESS_PLIB_WARNING // required for XC1.33 Later compiler versions will need PLIB to be installed #include "MMBasic_Includes.h" #include "Hardware_Includes.h" #define FALSE 0 #define TRUE 1 #define PinRead(a) gpio_get(PinDef[a].GPno) void owReset(unsigned char *p); void owWrite(unsigned char *p); void owRead(unsigned char *p); #ifdef INCLUDE_1WIRE_SEARCH static int LastDiscrepancy; static int LastFamilyDiscrepancy; static int LastDeviceFlag; static unsigned char SerialNum[8]; #endif #ifdef INCLUDE_CRC static unsigned short utilcrc16; static unsigned char utilcrc8; static const unsigned char dscrc_table[] = { 0, 94,188,226, 97, 63,221,131,194,156,126, 32,163,253, 31, 65, 157,195, 33,127,252,162, 64, 30, 95, 1,227,189, 62, 96,130,220, 35,125,159,193, 66, 28,254,160,225,191, 93, 3,128,222, 60, 98, 190,224, 2, 92,223,129, 99, 61,124, 34,192,158, 29, 67,161,255, 70, 24,250,164, 39,121,155,197,132,218, 56,102,229,187, 89, 7, 219,133,103, 57,186,228, 6, 88, 25, 71,165,251,120, 38,196,154, 101, 59,217,135, 4, 90,184,230,167,249, 27, 69,198,152,122, 36, 248,166, 68, 26,153,199, 37,123, 58,100,134,216, 91, 5,231,185, 140,210, 48,110,237,179, 81, 15, 78, 16,242,172, 47,113,147,205, 17, 79,173,243,112, 46,204,146,211,141,111, 49,178,236, 14, 80, 175,241, 19, 77,206,144,114, 44,109, 51,209,143, 12, 82,176,238, 50,108,142,208, 83, 13,239,177,240,174, 76, 18,145,207, 45,115, 202,148,118, 40,171,245, 23, 73, 8, 86,180,234,105, 55,213,139, 87, 9,235,181, 54,104,138,212,149,203, 41,119,244,170, 72, 22, 233,183, 85, 11,136,214, 52,106, 43,117,151,201, 74, 20,246,168, 116, 42,200,150, 21, 75,169,247,182,232, 10, 84,215,137,107, 53}; static const unsigned short oddparity[16] = { 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0 }; #endif int mmOWvalue; // value of MM.OW void ow_pinChk(int pin); int ow_reset(int pin); void ow_writeByte(int pin, int data); int ow_readByte(int pin); int ow_verifyByte(int pin, int data); int ow_touchByte(int pin, int data); int ow_touchBit(int pin, int ); void ow_writeBit(int pin, int ); int ow_readBit(int pin); void setcrc16(unsigned short reset); unsigned short docrc16(unsigned short cdata); void setcrc8(unsigned char reset); unsigned char docrc8(unsigned char cdata); int ow_first(int pin, int do_reset, int alarm_only); int ow_next(int pin, int do_reset, int alarm_only); int ow_verify(int pin, int alarm_only); void ow_serialNum(unsigned char *serialnum_buf, int do_read); void ow_familySearchSetup(int search_family); void ow_skipFamily(void); /* @endcond */ // the main OneWire command void cmd_onewire(void) { unsigned char *p; if((p = checkstring(cmdline, (unsigned char *)"RESET")) != NULL) owReset(p); else if((p = checkstring(cmdline, (unsigned char *)"WRITE")) != NULL) owWrite(p); else if((p = checkstring(cmdline, (unsigned char *)"READ")) != NULL) owRead(p); #ifdef INCLUDE_1WIRE_SEARCH // else if((p = checkstring(cmdline, "SEARCH")) != NULL) // owSearch(p); #endif else error("Unknown command"); } /* * @cond * The following section will be excluded from the documentation. */ /**************************************************************************************************************************** The DS18B20 command and function *****************************************************************************************************************************/ // this holds an array of 64-bit ints (one for each pin on the chip) // each number is zero if not being used for temperature measurement // or the timeout value if a temperature measurement is underway long long int *ds18b20Timers; void Init_ds18b20(int pin, int precision) { // set up initial pin status (open drain, output, high) ow_pinChk(pin); ExtCfg(pin, EXT_NOT_CONFIG, 0); // set pin to unconfigured gpio_init(PinDef[pin].GPno); ow_reset(pin); disable_interrupts_pico(); ow_writeByte(pin, 0xcc); // command skip the ROM ow_writeByte(pin, 0x4E); // write to the scratchpad ow_writeByte(pin, 0x00); // dummy data to TH ow_writeByte(pin, 0x00); // dummy data to TL ow_writeByte(pin, precision << 5); // select the resolution ow_reset(pin); ow_writeByte(pin, 0xcc); // skip the ROM ow_writeByte(pin, 0x44); // command start the conversion enable_interrupts_pico(); PinSetBit(pin, LATSET); gpio_set_dir(PinDef[pin].GPno, GPIO_OUT); gpio_put(PinDef[pin].GPno,GPIO_PIN_SET); ExtCfg(pin, EXT_DS18B20_RESERVED, 0); } /* @endcond */ void cmd_ds18b20(void) { int pin, precision; getargs(&cmdline, 5,(unsigned char *)","); if(argc < 1) error("Argument count"); char code; if(!(code=codecheck(argv[0])))argv[0]+=2; pin = getinteger(argv[0]); if(!code)pin=codemap(pin); precision = 1; if(argc >= 3 && *argv[2]) precision = getint(argv[2], 0, 3); int timeout=(100 << precision); if(argc==5)timeout=getint(argv[4],100,2000); Init_ds18b20(pin, precision); if(ds18b20Timers == NULL) ds18b20Timers = GetMemory(NBRPINS*sizeof(long long int)); // if this is the first time allocate memory for the timer array ds18b20Timers[pin] = ds18b20Timer + timeout; // set the timer count to wait for the conversion } void fun_ds18b20(void) { int pin, b1, b2; getargs(&ep,3,(unsigned char *)","); if(!(argc==1 || argc==3))error("Syntax"); char code; int timeout=200000; if(!(code=codecheck(argv[0])))argv[0]+=2; pin = getinteger(argv[0]); if(!code)pin=codemap(pin); if(argc==3)timeout=getint(argv[2],100,2000)*1000; if(ds18b20Timers == NULL || ds18b20Timers[pin] == 0) { // the TIMR command has not used Init_ds18b20(pin, 1); // the default is 10 bits uSec(timeout); // and 200mS conversion } else { // the TIMR command has been used while(ds18b20Timer < ds18b20Timers[pin]); // wait for the conversion ds18b20Timers[pin] = 0; } if(!ow_readBit(pin)) { fret = 1000.0; } else { ow_reset(pin); disable_interrupts_pico(); ow_writeByte(pin, 0xcc); // skip the ROM (again) ow_writeByte(pin, 0xBE); // command read data b1 = ow_readByte(pin); b2 = ow_readByte(pin); enable_interrupts_pico(); ow_reset(pin); if(b1 == 255 && b2 == 255){ fret = 1000.0; } else fret = (MMFLOAT)((short)(((unsigned short)b2 << 8) | (unsigned short)b1)) / 16.0; } ExtCfg(pin, EXT_NOT_CONFIG, 0); targ = T_NBR; } /* * @cond * The following section will be excluded from the documentation. */ /**************************************************************************************************************************** General functions *****************************************************************************************************************************/ // send one wire reset and optionally return presence response void owReset(unsigned char *p) { int pin; char code; if(!(code=codecheck(p)))p+=2; pin = getinteger(p); if(!code)pin=codemap( pin); ow_pinChk(pin); // set up initial pin status (open drain, output, high) ExtCfg(pin, EXT_NOT_CONFIG, 0); // set pin to unconfigured gpio_init(PinDef[pin].GPno); PinSetBit(pin, LATSET); PinSetBit(pin, ODCSET); ow_reset(pin); ExtCurrentConfig[pin] = EXT_NOT_CONFIG; } void owWriteCore(int pin, int * buf, int len, int flag){ disable_interrupts_pico(); for (int i = 0; i < len; i++) { if (flag & 0x04) { if (buf[i]) { // Write '1' bit PinSetBit(pin, LATCLR); // drive pin low uSec(6); PinSetBit(pin, LATSET); // release the bus uSec(64); // wait 64Sec } else { // Write '0' bit PinSetBit(pin, LATCLR); // drive pin low uSec(60); // wait 60uSec PinSetBit(pin, LATSET); // release the bus uSec(10); } } else { ow_writeByte(pin, buf[i]); } } enable_interrupts_pico(); } // send one wire data void owWrite(unsigned char *p) { int pin, flag, len, i, buf[255]; unsigned char *cp; getargs(&p, MAX_ARG_COUNT*2,(unsigned char *)","); if (!(argc & 0x01) || (argc < 7)) error("Argument count"); char code; if(!(code=codecheck(argv[0])))argv[0]+=2; pin = getinteger(argv[0]); if(!code)pin=codemap(pin); ow_pinChk(pin); flag = getint(argv[2], 0, 15); len = getint(argv[4], 1, 255); // check the first char for a legal variable name cp = argv[6]; skipspace(cp); //if (argc > 7 || (len == 1 && type == 0)) { // numeric expressions for data if (len != ((argc - 5) >> 1)) error("Argument count"); for (i = 0; i < len; i++) { buf[i] = getinteger(argv[i + i + 6]); } // set up initial pin status (open drain, output, high) ExtCfg(pin, EXT_NOT_CONFIG, 0); // set pin to unconfigured gpio_init(PinDef[pin].GPno); PinSetBit(pin, LATSET); PinSetBit(pin, ODCSET); PinSetBit(pin, TRISCLR); // this line added by JH if (flag & 0x01) ow_reset(pin); owWriteCore(pin, buf, len, flag); if (flag & 0x02) ow_reset(pin); if (flag & 0x08) { // strong pullup required? gpio_set_dir(PinDef[pin].GPno, GPIO_OUT); gpio_put(PinDef[pin].GPno,GPIO_PIN_SET); } ExtCurrentConfig[pin] = EXT_NOT_CONFIG; return; } void owReadCore(int pin, int * buf, int len, int flag){ disable_interrupts_pico(); PinSetBit(pin, TRISCLR); // set as output *** added this line for (int i = 0; i < len; i++) { if (flag & 0x04) { buf[i] = ow_readBit(pin); } else { buf[i] = ow_readByte(pin); } } enable_interrupts_pico(); } // read one wire data void owRead(unsigned char *p) { int pin, flag, len, i, buf[255]; void *ptr = NULL; getargs(&p, MAX_ARG_COUNT*2,(unsigned char *)","); if (!(argc & 0x01) || (argc < 7)) error("Argument count"); char code; if(!(code=codecheck(argv[0])))argv[0]+=2; pin = getinteger(argv[0]); if(!code)pin=codemap( pin); ow_pinChk(pin); flag = getint(argv[2], 0, 15); len = getint(argv[4], 1, 255); // check the validity of the argument list if (len != ((argc - 5) >> 1)) error("Argument count"); for (i = 0; i < len; i++) { ptr = findvar(argv[i + i + 6], V_FIND); if(g_vartbl[g_VarIndex].type & T_CONST) error("Cannot change a constant"); if (!(g_vartbl[g_VarIndex].type & (T_NBR | T_INT)) || g_vartbl[g_VarIndex].dims[0] != 0) error("Invalid variable"); } // set up initial pin status (open drain, output, high) ExtCfg(pin, EXT_NOT_CONFIG, 0); // set pin to unconfigured gpio_init(PinDef[pin].GPno); PinSetBit(pin, LATSET); PinSetBit(pin, ODCSET); if (flag & 0x01) ow_reset(pin); owReadCore(pin, buf, len, flag); if (flag & 0x02) ow_reset(pin); if (flag & 0x08) { // strong pullup required? PinSetBit(pin, LATSET); PinSetBit(pin, TRISCLR); } for (i = 0; i < len; i++) { ptr = findvar(argv[i + i + 6], V_FIND); if(g_vartbl[g_VarIndex].type & T_NBR) *((MMFLOAT *)ptr) = buf[i]; else *((long long int *)ptr) = buf[i]; } ExtCurrentConfig[pin] = EXT_NOT_CONFIG; return; } #ifdef INCLUDE_1WIRE_SEARCH // One wire search // flag: 1 = reset search // 2 = alarm set // 4 = family search // 8 = skip current family // 16 = verify // /* @endcond */ void fun_owSearch(void) { int pin, flag, alarm, i; union map { unsigned char serbytes[8]; unsigned long long int ser; } buf,inp; unsigned char filter=0; getargs(&ep, MAX_ARG_COUNT*2,(unsigned char *)","); if (!(argc & 0x01) || (argc < 3)) error("Argument count"); char code; if(!(code=codecheck(argv[0])))argv[0]+=2; pin = getinteger(argv[0]); if(!code)pin=codemap( pin); ow_pinChk(pin); flag = getinteger(argv[2]); if (flag < 0 || flag > 31) error("Number out of bounds"); if (((flag & 0x01) && flag > 7) || ((flag & 0x04) && flag > 7) || ((flag & 0x08) && flag > 15)) error("Invalid flag combination"); if ((flag & 0x04) || (flag & 0x10)) { if(argc < 3) error("Argument count"); inp.ser=getinteger(argv[4]); for (i = 0; i < 8; i++) { buf.serbytes[7-i] = inp.serbytes[i]; } filter=buf.serbytes[0]; } if (flag & 0x02) alarm = 1; else alarm = 0; // set up initial pin status (open drain, output, high) ExtCfg(pin, EXT_NOT_CONFIG, 0); // set pin to unconfigured gpio_init(PinDef[pin].GPno); PinSetBit(pin, LATSET); PinSetBit(pin, ODCSET); if (flag & 0x01) { mmOWvalue = ow_first(pin, 1, alarm); } else if (flag & 0x08) { ow_skipFamily(); mmOWvalue = ow_next(pin, 1, alarm); } else if (flag & 0x10) { ow_serialNum(buf.serbytes, 0); mmOWvalue = ow_verify(pin, alarm); } else { mmOWvalue = ow_next(pin, 1, alarm); } if(flag & 0x04){ while(SerialNum[0]!=filter && mmOWvalue){ mmOWvalue = ow_next(pin, 1, alarm); } } for (i = 0; i < 8; i++) { buf.serbytes[7-i] = SerialNum[i]; } if(!mmOWvalue)buf.ser=0; iret=buf.ser; targ = T_INT; return; } #endif /* * @cond * The following section will be excluded from the documentation. */ #if defined(INCLUDE_CRC) void fun_owCRC8(void){ int len, i, x; unsigned char buf[255], uc = 0; getargs(&ep, MAX_ARG_COUNT*2,","); // this is a macro and must be the first executable stmt in a block if (!(argc & 0x01) || (argc < 3)) error("Argument count"); len = getinteger(argv[0]); if ((len < 1) || (len > 255)) error("Number out of bounds"); if (len != ((argc - 1) >> 1)) error("Argument count"); for (i = 0; i < len; i++) { x = getinteger(argv[i + i + 6]); if (x < 0 || x > 255) error("Number out of bounds"); buf[i] = (unsigned char)x; } setcrc8(0); for (i = 0; i < len; i++) { uc = docrc8(buf[i]); } fret = (MMFLOAT)uc; } void fun_owCRC16(void){ int len, i, x; unsigned short buf[255], us = 0; getargs(&ep, MAX_ARG_COUNT*2,","); // this is a macro and must be the first executable stmt in a block if (!(argc & 0x01) || (argc < 3)) error("Argument count"); len = getinteger(argv[0]); if ((len < 1) || (len > 255)) error("Number out of bounds"); if (len != ((argc - 1) >> 1)) error("Argument count"); for (i = 0; i < len; i++) { x = getinteger(argv[i + i + 6]); if (x < 0 || x > 65535) error("Number out of bounds"); buf[i] = (unsigned short)x; } setcrc16(0); for (i = 0; i < len; i++) { us = docrc16(buf[i]); } fret = (MMFLOAT)us; } #endif /* @endcond */ void fun_mmOW(void) { iret = mmOWvalue; targ = T_INT; } /* * @cond * The following section will be excluded from the documentation. */ void ow_pinChk(int pin) { // if(ClockSpeed < 10000000) error("CPU speed too low"); CheckPin(pin, CP_CHECKALL); return; } // send one wire reset and detect presence response - returns 1 if found else 0 int ow_reset(int pin) { PinSetBit(pin, LATSET); PinSetBit(pin, TRISCLR); PinSetBit(pin, LATCLR); // drive pin low uSec(481); // wait 481uSec PinSetBit(pin, TRISSET); // set as input PinSetBit(pin, LATSET); // release the bus uSec(70); // wait 70uSec mmOWvalue = PinRead(pin) ^ 0x01; // read pin and invert response PinSetBit(pin, TRISCLR); // set as output uSec(411); // wait 411uSec return mmOWvalue; } void __not_in_flash_func(ow_writeByte)(int pin, int data) { int loop; for (loop = 0; loop < 8; loop++) { ow_writeBit(pin, data & 0x01); data >>= 1; } return; } int __not_in_flash_func(ow_readByte)(int pin) { int loop, result = 0; for (loop = 0; loop < 8; loop++) { result >>= 1; if (ow_readBit(pin)) result |= 0x80; } return result; } int ow_touchByte(int pin, int data) { int loop, result = 0; for (loop = 0; loop < 8; loop++) { result >>= 1; if (data & 0x01) { // if sending a '1' then read a bit else write a '0' if (ow_readBit(pin)) result |= 0x80; } else { ow_writeBit(pin, 0x00); } data >>= 1; } return result; } int ow_touchBit(int pin, int bit) { int result = 0; if (bit & 0x01) { // if sending a '1' then read a bit else write a '0' if (ow_readBit(pin)) result = 1; } else { ow_writeBit(pin, 0x00); } return result; } // note that the uSec() function will not time short delays at low clock speeds // so we directly use the core timer for short delays void __not_in_flash_func(ow_writeBit)(int pin, int bit) { if (bit) { // Write '1' bit PinSetBit(pin, LATCLR); // drive pin low uSec(6); PinSetBit(pin, LATSET); // release the bus uSec(64); // wait 64Sec } else { // Write '0' bit PinSetBit(pin, LATCLR); // drive pin low uSec(60); // wait 60uSec PinSetBit(pin, LATSET); // release the bus uSec(10); } return; } // note that the uSec() function will not time short delays at low clock speeds // so we directly use the core timer for short delays int ow_readBit(int pin) { int result; PinSetBit(pin, TRISCLR); // set as output *** JH PinSetBit(pin, LATCLR); // drive pin low uSec(3); PinSetBit(pin, TRISSET); // set as input PinSetBit(pin, LATSET); // release the bus uSec(10); result = PinRead(pin); // read pin // PinSetBit(pin, TRISCLR); uSec(53); // wait 56uSec return result; } #ifdef INCLUDE_1WIRE_SEARCH int ow_verifyByte(int pin, int data) { return (ow_touchByte(pin, data) == data) ? 1 : 0; } //-------------------------------------------------------------------------- // The 'ow_first' finds the first device on the 1-Wire Net // // When 'alarm_only' is TRUE (1) the find alarm command 0xEC is // sent instead of the normal search command 0xF0. // Using the find alarm command 0xEC will limit the search to only // 1-Wire devices that are in an 'alarm' state. // // 'pin' - I/O Pin. // 'do_reset' - TRUE (1) perform reset before search, FALSE (0) do not // perform reset before search. // 'alarm_only' - TRUE (1) the find alarm command 0xEC is // sent instead of the normal search command 0xF0 // // Returns: TRUE (1) : when a 1-Wire device was found and it's // Serial Number placed in the global SerialNum[portnum] // FALSE (0): There are no devices on the 1-Wire Net. // int ow_first(int pin, int do_reset, int alarm_only) { // reset the search state LastDiscrepancy = 0; LastDeviceFlag = FALSE; LastFamilyDiscrepancy = 0; return ow_next(pin, do_reset, alarm_only); } //-------------------------------------------------------------------------- // The 'ow_next' function does a general search. This function // continues from the previos search state. The search state // can be reset by using the 'ow_first' function. // // When 'alarm_only' is TRUE (1) the find alarm command // 0xEC is sent instead of the normal search command 0xF0. // Using the find alarm command 0xEC will limit the search to only // 1-Wire devices that are in an 'alarm' state. // // 'pin' - I/O Pin. // 'do_reset' - TRUE (1) perform reset before search, FALSE (0) do not // perform reset before search. // 'alarm_only' - TRUE (1) the find alarm command 0xEC is // sent instead of the normal search command 0xF0 // // Returns: TRUE (1) : when a 1-Wire device was found and it's // Serial Number placed in the global SerialNum[portnum] // FALSE (0): when no new device was found. Either the // last search was the last device or there // are no devices on the 1-Wire Net. // int ow_next(int pin, int do_reset, int alarm_only) { int bit_test, search_direction, bit_number; int last_zero, serial_byte_number, next_result; unsigned char serial_byte_mask, lastcrc8; // initialize for search bit_number = 1; last_zero = 0; serial_byte_number = 0; serial_byte_mask = 1; next_result = 0; lastcrc8 = 0; setcrc8(0); // if the last call was not the last one if (!LastDeviceFlag) { // check if reset first is requested if (do_reset) { // reset the 1-wire // if there are no parts on 1-wire, return FALSE if (!ow_reset(pin)) { // reset the search LastDiscrepancy = 0; LastFamilyDiscrepancy = 0; return FALSE; } } // If finding alarming devices issue a different command if (alarm_only) { ow_writeByte(pin, 0xEC); // issue the alarming search command } else { ow_writeByte(pin, 0xF0); // issue the search command } // loop to do the search do { // read a bit and its compliment bit_test = ow_touchBit(pin, 1) << 1; bit_test |= ow_touchBit(pin, 1); // check for no devices on 1-wire if (bit_test == 3) break; else { // all devices coupled have 0 or 1 if (bit_test > 0) { search_direction = !(bit_test & 0x01); // bit write value for search } else { // if this discrepancy if before the Last Discrepancy // on a previous next then pick the same as last time if (bit_number < LastDiscrepancy) search_direction = ((SerialNum[serial_byte_number] & serial_byte_mask) > 0); else // if equal to last pick 1, if not then pick 0 search_direction = (bit_number == LastDiscrepancy); // if 0 was picked then record its position in LastZero if (search_direction == 0) { last_zero = bit_number; // check for Last discrepancy in family if (last_zero < 9) LastFamilyDiscrepancy = last_zero; } } // set or clear the bit in the SerialNum byte serial_byte_number // with mask serial_byte_mask if (search_direction == 1) SerialNum [serial_byte_number] |= serial_byte_mask; else SerialNum [serial_byte_number] &= ~serial_byte_mask; // serial number search direction write bit ow_touchBit(pin, search_direction); // increment the byte counter bit_number // and shift the mask serial_byte_mask bit_number++; serial_byte_mask <<= 1; // if the mask is 0 then go to new SerialNum byte serial_byte_number // and reset mask if (serial_byte_mask == 0) { // The below has been added to accomodate the valid CRC with the // possible changing serial number values of the DS28E04. if (((SerialNum[0] & 0x7F) == 0x1C) && (serial_byte_number == 1)) lastcrc8 = docrc8(0x7F); else lastcrc8 = docrc8(SerialNum[serial_byte_number]); // accumulate the CRC serial_byte_number++; serial_byte_mask = 1; } } } while(serial_byte_number < 8); // loop until through all SerialNum[portnum] bytes 0-7 // if the search was successful then if (!((bit_number < 65) || lastcrc8)) { // search successful so set LastDiscrepancy, LastDeviceFlag, next_result LastDiscrepancy = last_zero; LastDeviceFlag = (LastDiscrepancy == 0); next_result = TRUE; } } // if no device found then reset counters so next 'next' will be // like a first if (!next_result || !SerialNum[0]) { LastDiscrepancy = 0; LastDeviceFlag = FALSE; LastFamilyDiscrepancy = 0; next_result = FALSE; } return next_result; } //-------------------------------------------------------------------------- // The 'ow_verify' function checks that the device with the serial number // in the global SerialNum buffer is present. // // When 'alarm_only' is TRUE (1) the find alarm command // 0xEC is sent instead of the normal search command 0xF0. // Using the find alarm command 0xEC will limit the search to only // 1-Wire devices that are in an 'alarm' state. // // 'pin' - I/O Pin. // 'alarm_only' - TRUE (1) the find alarm command 0xEC is // sent instead of the normal search command 0xF0 // // Returns: TRUE (1) : device verified present. // FALSE (0): device not present. // int ow_verify(int pin, int alarm_only) { unsigned char serialNum_backup[8]; int i, rslt, ld_backup, ldf_backup, lfd_backup; // keep a backup copy of the current state for (i = 0; i < 8; i++) serialNum_backup[i] = SerialNum[i]; ld_backup = LastDiscrepancy; ldf_backup = LastDeviceFlag; lfd_backup = LastFamilyDiscrepancy; // set search to find the same device LastDiscrepancy = 64; LastDeviceFlag = FALSE; if (ow_next(pin, 1, alarm_only)) { // check if same device found rslt = TRUE; for (i = 0; i < 8; i++) { if (serialNum_backup[i] != SerialNum[i]) { rslt = FALSE; break; } } } else { rslt = FALSE; } // restore the search state for (i = 0; i < 8; i++) SerialNum[i] = serialNum_backup[i]; LastDiscrepancy = ld_backup; LastDeviceFlag = ldf_backup; LastFamilyDiscrepancy = lfd_backup; // return the result of the verify return rslt; } //-------------------------------------------------------------------------- // The 'ow_serialNum' function either reads or sets the SerialNum buffer // that is used in the search functions 'ow_first' and 'ow_next'. // This function contains two parameters, 'serialnum_buf' is a pointer // to a buffer provided by the caller. 'serialnum_buf' should point to // an array of 8 unsigned chars. The second parameter is a flag called // 'do_read' that is TRUE (1) if the operation is to read and FALSE // (0) if the operation is to set the internal SerialNum buffer from // the data in the provided buffer. // // 'serialnum_buf' - buffer to that contains the serial number to set // when do_read = FALSE (0) and buffer to get the serial // number when do_read = TRUE (1). // 'do_read' - flag to indicate reading (1) or setting (0) the current // serial number. // void ow_serialNum(unsigned char *serialnum_buf, int do_read) { unsigned char i; // read the internal buffer and place in 'serialnum_buf' if (do_read) { for (i = 0; i < 8; i++) serialnum_buf[i] = SerialNum[i]; } else { // set the internal buffer from the data in 'serialnum_buf' for (i = 0; i < 8; i++) SerialNum[i] = serialnum_buf[i]; } } //-------------------------------------------------------------------------- // Setup the search algorithm to find a certain family of devices // the next time a search function is called 'owNext'. // // 'search_family' - family code type to set the search algorithm to find // next. // void ow_familySearchSetup(int search_family) { int i; // set the search state to find SearchFamily type devices SerialNum[0] = search_family; for (i = 1; i < 8; i++) SerialNum[i] = 0; LastDiscrepancy = 64; LastDeviceFlag = FALSE; } //-------------------------------------------------------------------------- // Set the current search state to skip the current family code. // void ow_skipFamily(void) { // set the Last discrepancy to last family discrepancy LastDiscrepancy = LastFamilyDiscrepancy; LastFamilyDiscrepancy = 0; // check for end of list if (LastDiscrepancy == 0) LastDeviceFlag = TRUE; } #endif #if defined(INCLUDE_CRC) void setcrc16(unsigned short reset) { utilcrc16 = reset; return; } unsigned short docrc16(unsigned short cdata) { cdata = (cdata ^ (utilcrc16 & 0xff)) & 0xff; utilcrc16 >>= 8; if (oddparity[cdata & 0xf] ^ oddparity[cdata >> 4]) utilcrc16 ^= 0xc001; cdata <<= 6; utilcrc16 ^= cdata; cdata <<= 1; utilcrc16 ^= cdata; return utilcrc16; } void setcrc8(unsigned char reset) { utilcrc8 = reset; return; } unsigned char docrc8(unsigned char cdata) { utilcrc8 = dscrc_table[utilcrc8 ^ cdata]; return utilcrc8; } #endif /* @endcond */