one wire driver
Dependents: 09_PT1000 10_PT1000 11_PT1000
DS2482.cpp
- Committer:
- rs27
- Date:
- 2013-04-27
- Revision:
- 0:c57706d25cf0
- Child:
- 1:0950824b1ca3
File content as of revision 0:c57706d25cf0:
#include "mbed.h" #include "DS2482.h" //----------------------------------------------------------------------------- // CRC = X^8 + X^5 + X^4 + 1 #define CRC_TABLE_ITEMS 256 const uint8_t crc_table[CRC_TABLE_ITEMS] = { 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 }; //========================================================================== // destructor DS2482::DS2482(PinName sda, PinName scl, int address) : i2c(sda, scl) { addr = address; i2c.frequency(100000); } //----------------------------------------------------------------------------- // Calculate the CRC8 of the byte value provided with the current // global 'crc8' value. // Returns current global crc8 value // uint8_t DS2482::crc_calc(uint8_t x) { crc_value = crc_table[crc_value ^ x]; return crc_value; } //========================================================================== // I2C DS2482 // //-------------------------------------------------------------------------- // DS2482 Detect routine that sets the I2C address and then performs a // device reset followed by writing the configuration byte to default values: // 1-Wire speed (c1WS) = standard (0) // Strong pullup (cSPU) = off (0) // Presence pulse masking (cPPM) = off (0) // Active pullup (cAPU) = on (CONFIG_APU = 0x01) // // Returns: TRUE if device was detected and written // FALSE device not detected or failure to write configuration byte //uint8_t DS2482_detect(unsigned char addr) // uint8_t DS2482::detect(void) { if (!reset()) // reset the DS2482 ON selected address { #if OW_MASTER_START printf("\r\n--- DS2482 bus0 reset not executed"); #endif return false; } // default configuration c1WS = 0; cSPU = 0; cPPM = 0; cAPU = DS2482_CFG_APU; // write the default configuration setup if (!write_config(c1WS | cSPU | cPPM | cAPU)) { #if OW_MASTER_START printf("\r\n--- DS2482 configuration failure"); #endif return false; } #if OW_MASTER_START printf("\r\n*** DS2482 detect OK"); #endif return true; } //-------------------------------------------------------------------------- // Perform a device reset on the DS2482 // // Returns: TRUE if device was reset // FALSE device not detected or failure to perform reset // int DS2482::reset(void) { char cmd[2]; cmd[0] = DS2482_CMD_DRST; i2c.write(addr, cmd, 1); i2c.read(addr, cmd, 1); printf("\ncmd = %02x",cmd[0]); return ((cmd[0] & 0xF7) == 0x10); } //-------------------------------------------------------------------------- // Write the configuration register in the DS2482. The configuration // options are provided in the lower nibble of the provided config byte. // The uppper nibble in bitwise inverted when written to the DS2482. // // Returns: TRUE: config written and response correct // FALSE: response incorrect // uint8_t DS2482::write_config(uint8_t config) { char cmd[2]; char read_config; cmd[0] = DS2482_CMD_WCFG; cmd[1] = config | (~config << 4); i2c.write(addr, cmd, 2); i2c.read(addr, cmd, 1); read_config = cmd[0]; if (config != read_config) // check for failure due to incorrect read back { // handle error // ... #if OW_MASTER_START printf("\r\n---check for failure due to incorrect config read back"); #endif reset(); return false; } return true; } //-------------------------------------------------------------------------- // DS2482 1-Wire Operations //-------------------------------------------------------------------------- // //OWReset //-------------------------------------------------------------------------- // Reset all of the devices on the 1-Wire Net and return the result. // // Returns: TRUE(1): presence pulse(s) detected, device(s) reset // FALSE(0): no presence pulses detected // uint8_t DS2482::OWReset(void) { uint8_t status; uint8_t poll_count = 0; char cmd(2); cmd[0] = DS2482_CMD_1WRS; i2c.write(addr,cmd,1); #if OW_MASTER_DEBUG printf_P(PSTR("\r\n*** Reset all devices on the 1-Wire Net\r\n")); #endif do { i2c.read(addr,cmd,1); } while ((cmd[0] & DS2482_STATUS_1WB) && (poll_count++ < POLL_LIMIT)); // check for failure due to poll limit reached if (poll_count >= POLL_LIMIT) { // handle error // ... #if OW_MASTER_DEBUG printf("\r\n---poll limit reached"); #endif reset(); return FALSE; } // check for short condition if (cmd[0] & DS2482_STATUS_SD) { #if OW_MASTER_DEBUG printf("\r\n---1-Wire Net short detected"); #endif short_detected = true; } else { #if OW_MASTER_DEBUG printf("\r\n*** 1-Wire electrical net is OK"); #endif short_detected = false; } // check for presence detect if (cmd[0] & DS2482_STATUS_PPD) { #if OW_MASTER_DEBUG printf("\r\n*** 1-Wire Device detected"); #endif return true; } else { #if OW_MASTER_DEBUG printf("\r\n---No Device detected"); #endif return false; } } //-------------------------------------------------------------------------- // Send 1 bit of communication to the 1-Wire Net. // The parameter 'sendbit' least significant bit is used. // // 'sendbit' - 1 bit to send (least significant byte) // void DS2482::OWWriteBit(uint8_t sendbit) { OWTouchBit(sendbit); } //-------------------------------------------------------------------------- // Reads 1 bit of communication from the 1-Wire Net and returns the // result // // Returns: 1 bit read from 1-Wire Net // uint8_t DS2482::OWReadBit(void) { return OWTouchBit(0x01); } //-------------------------------------------------------------------------- // Send 1 bit of communication to the 1-Wire Net and return the // result 1 bit read from the 1-Wire Net. The parameter 'sendbit' // least significant bit is used and the least significant bit // of the result is the return bit. // // 'sendbit' - the least significant bit is the bit to send // // Returns: 0: 0 bit read from sendbit // 1: 1 bit read from sendbit // uint8_t DS2482::OWTouchBit(uint8_t sendbit) { char cmd[2]; uint8_t poll_count = 0; cmd[0] = DS2482_CMD_1WSB; cmd[1] = sendbit ? 0x80 : 0x00; i2c.write(addr, cmd, 2); // loop checking 1WB bit for completion of 1-Wire operation // abort if poll limit reached do { i2c.read(addr, cmd, 1); } while ((cmd[0] & DS2482_STATUS_1WB) && (poll_count++ < POLL_LIMIT)); #if OW_MASTER_DEBUG printf("\r\n*** Send 1 bit to the 1-Wire Net"); #endif // check for failure due to poll limit reached if (poll_count >= POLL_LIMIT) { // handle error // ... #if OW_MASTER_DEBUG printf("\r\n---handle error OW Write Bit"); #endif reset(); return 0; } // return bit state if (cmd[0] & DS2482_STATUS_SBR) { return 1; } else { return 0; } } //-------------------------------------------------------------------------- // Send 8 bits of communication to the 1-Wire Net and verify that the // 8 bits read from the 1-Wire Net are the same (write operation). // The parameter 'sendbyte' least significant 8 bits are used. // // 'sendbyte' - 8 bits to send (least significant byte) // // Returns: TRUE: bytes written and echo was the same // FALSE: echo was not the same // void DS2482::OWWriteByte(uint8_t sendbyte) { char cmd[2]; uint8_t poll_count = 0; #if OW_MASTER_DEBUG printf("\r\n*** Send 8 bits of WRITE to the 1-Wire Net"); #endif cmd[0] = DS2482_CMD_1WWB; cmd[1] = sendbyte; i2c.write(addr, cmd, 2); // loop checking 1WB bit for completion of 1-Wire operation // abort if poll limit reached do { i2c.read(addr, cmd, 1); } while ((cmd[0] & DS2482_STATUS_1WB) && (poll_count++ < POLL_LIMIT)); // check for failure due to poll limit reached if (poll_count >= POLL_LIMIT) { // handle error // ... #if OW_MASTER_DEBUG printf("\r\n---handle error OW Write Byte"); #endif reset(); } } //-------------------------------------------------------------------------- // Send 8 bits of read communication to the 1-Wire Net and return the // result 8 bits read from the 1-Wire Net. // // Returns: 8 bits read from 1-Wire Net // uint8_t DS2482::OWReadByte(void) { uint8_t data, status; uint8_t poll_count = 0; char cmd[2]; #if OW_MASTER_DEBUG printf("\r\n*** Read 8 bits from the 1-Wire Net"); #endif cmd[0] = DS2482_CMD_1WRB; // DS2482 1-Wire Read Byte i2c.write(addr, cmd, 1); // loop checking 1WB bit for completion of 1-Wire operation // abort if poll limit reached do { i2c.read(adr, cmd, 1); } while ((cmd[0] & DS2482_STATUS_1WB) && (poll_count++ < POLL_LIMIT)); // check for failure due to poll limit reached if (poll_count >= POLL_LIMIT) { // handle error // ... #if OW_MASTER_DEBUG printf("\r\n---handle error OW Read Byte"); #endif reset(); return 0; } cmd[0] = DS2482_CMD_SRP; // DS2482 Set Read Pointer cmd[1] = DS2482_READPTR_RDR; // DS2482 Read Data Register i2c.write[addr, cmd, 2); i2c.read(addr, cmd, 1)); return cmd[0]; } //-------------------------------------------------------------------------- // The 'OWBlock' transfers a block of data to and from the // 1-Wire Net. The result is returned in the same buffer. // // 'tran_buf' - pointer to a block of unsigned // chars of length 'tran_len' that will be sent // to the 1-Wire Net // 'tran_len' - length in bytes to transfer // void DS2482::OWBlock(uint8_t *tran_buf, uint8_t tran_len) { uint8_t i; for (i = 0; i < tran_len; i++) { tran_buf[i] = OWTouchByte(tran_buf[i]); } } //-------------------------------------------------------------------------- // Send 8 bits of communication to the 1-Wire Net and return the // result 8 bits read from the 1-Wire Net. The parameter 'sendbyte' // least significant 8 bits are used and the least significant 8 bits // of the result are the return byte. // // 'sendbyte' - 8 bits to send (least significant byte) // // Returns: 8 bits read from sendbyte // uint8_t DS2482::OWTouchByte(uint8_t sendbyte) { if (sendbyte == 0xFF) { return OWReadByte(); } else { OWWriteByte(sendbyte); return sendbyte; } } //-------------------------------------------------------------------------- // Search state //-------------------------------------------------------------------------- // Find the 'first' devices on the 1-Wire network // Return TRUE : device found, ROM number in ROM_NO buffer // FALSE : no device present // uint8_t DS2482::OWFirst(void) { // reset the search state LastDiscrepancy = 0; LastDeviceFlag = FALSE; LastFamilyDiscrepancy = 0; #if OW_MASTER_DEBUG printf("\r\n*** Find the 'first' device on the 1-Wire network"); #endif return OWSearch(); } //-------------------------------------------------------------------------- // Find the 'next' devices on the 1-Wire network // Return TRUE : device found, ROM number in ROM_NO buffer // FALSE : device not found, end of search // uint8_t DS2482::OWNext(void) { #if OW_MASTER_DEBUG printf("\r\n*** Find the 'next' device on the 1-Wire network"); #endif // leave the search state alone return OWSearch(); } //-------------------------------------------------------------------------- // Verify the device with the ROM number in ROM_NO buffer is present. // Return TRUE : device present // FALSE : device not present // int DS2482::OWVerify(void) { uint8_t rom_backup[8], status; int i,ld_backup,ldf_backup,lfd_backup; // keep a backup copy of the current state for (i = 0; i < 8; i++) { rom_backup[i] = ROM_NO[i]; } ld_backup = LastDiscrepancy; ldf_backup = LastDeviceFlag; lfd_backup = LastFamilyDiscrepancy; // set search to find the same device LastDiscrepancy = 64; LastDeviceFlag = FALSE; if (OWSearch()) { // check if same device found status = TRUE; for (i = 0; i < 8; i++) { if (rom_backup[i] != ROM_NO[i]) { status = FALSE; break; } } } else { status = FALSE; } // restore the search state for (i = 0; i < 8; i++) { ROM_NO[i] = rom_backup[i]; } LastDiscrepancy = ld_backup; LastDeviceFlag = ldf_backup; LastFamilyDiscrepancy = lfd_backup; // return the result of the verify #if OW_MASTER_DEBUG printf("\r\n*** 1-Wire Verify device with the ROM number in ROM_NO"); #endif return status; } //-------------------------------------------------------------------------- // Setup the search to find the device type 'family_code' on the next call // to OWNext() if it is present. // void DS2482::OWTargetSetup(uint8_t family_code) { uint8_t i; // set the search state to find SearchFamily type devices ROM_NO[0] = family_code; for (i = 1; i < 8; i++) { ROM_NO[i] = 0; } LastDiscrepancy = 64; LastFamilyDiscrepancy = 0; LastDeviceFlag = FALSE; } //-------------------------------------------------------------------------- // Setup the search to skip the current device type on the next call // to OWNext(). // void DS2482::OWFamilySkipSetup(void) { // set the Last discrepancy to last family discrepancy LastDiscrepancy = LastFamilyDiscrepancy; // clear the last family discrpepancy LastFamilyDiscrepancy = 0; // check for end of list if (LastDiscrepancy == 0) { LastDeviceFlag = TRUE; } } //-------------------------------------------------------------------------- // The 'OWSearch' function does a general search. This function // continues from the previous search state. The search state // can be reset by using the 'OWFirst' function. // This function contains one parameter 'alarm_only'. // 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. // // Returns: TRUE (1) : when a 1-Wire device was found and its // Serial Number placed in the global ROM // 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. // uint8_t DS2482::OWSearch() { int id_bit_number; int last_zero, rom_byte_number, search_result; int id_bit, cmp_id_bit; uint8_t rom_byte_mask, search_direction, status; // initialize for search id_bit_number = 1; last_zero = 0; rom_byte_number = 0; rom_byte_mask = 1; search_result = FALSE; crc_value = 0; if (!LastDeviceFlag) // if the last call was not the last one { // 1-Wire reset if (!OWReset()) { // reset the search LastDiscrepancy = 0; LastDeviceFlag = FALSE; LastFamilyDiscrepancy = 0; return FALSE; } // issue the search command OWWriteByte(OW_SEARCH_ROM); // loop to do the search do { // if this discrepancy if before the Last Discrepancy // on a previous next then pick the same as last time if (id_bit_number < LastDiscrepancy) { if ((ROM_NO[rom_byte_number] & rom_byte_mask) > 0) search_direction = 1; else search_direction = 0; } else { // if equal to last pick 1, if not then pick 0 if (id_bit_number == LastDiscrepancy) search_direction = 1; else search_direction = 0; } // Perform a triple operation on the DS2482 which will perform 2 read bits and 1 write bit status = search_triplet(search_direction); // check bit results in status byte id_bit = ((status & DS2482_STATUS_SBR) == DS2482_STATUS_SBR); cmp_id_bit = ((status & DS2482_STATUS_TSB) == DS2482_STATUS_TSB); search_direction = ((status & DS2482_STATUS_DIR) == DS2482_STATUS_DIR) ? 1 : 0; // check for no devices on 1-Wire if ((id_bit) && (cmp_id_bit)) { break; } else { if ((!id_bit) && (!cmp_id_bit) && (search_direction == 0)) { last_zero = id_bit_number; // check for Last discrepancy in family if (last_zero < 9) { LastFamilyDiscrepancy = last_zero; } } // set or clear the bit in the ROM byte rom_byte_number // with mask rom_byte_mask if (search_direction == 1) { ROM_NO[rom_byte_number] |= rom_byte_mask; } else { ROM_NO[rom_byte_number] &= ~rom_byte_mask; } // increment the byte counter id_bit_number // and shift the mask rom_byte_mask id_bit_number++; rom_byte_mask <<= 1; // if the mask is 0 then go to new SerialNum byte rom_byte_number and reset mask if (rom_byte_mask == 0) { crc_calc(ROM_NO[rom_byte_number]); // accumulate the CRC rom_byte_number++; rom_byte_mask = 1; } } } while(rom_byte_number < 8); // loop until through all ROM bytes 0-7 // if the search was successful then if (!((id_bit_number < 65) || (crc_value != 0))) { // search successful so set LastDiscrepancy,LastDeviceFlag,search_result LastDiscrepancy = last_zero; // check for last device if (LastDiscrepancy == 0) { LastDeviceFlag = TRUE; } search_result = TRUE; } } // if no device found then reset counters so next 'search' will be like a first if (!search_result || (ROM_NO[0] == 0)) { LastDiscrepancy = 0; LastDeviceFlag = FALSE; LastFamilyDiscrepancy = 0; search_result = FALSE; } return search_result; } //-------------------------------------------------------------------------- // Use the DS2482 help command '1-Wire triplet' to perform one bit of a // 1-Wire search. // This command does two read bits and one write bit. The write bit // is either the default direction (all device have same bit) or in case of // a discrepancy, the 'search_direction' parameter is used. // // Returns – The DS2482 status byte result from the triplet command // uint8_t DS2482::search_triplet(uint8_t search_direction) { uint8_t status; uint8_t poll_count = 0; i2c.start(); i2c.write(OW_I2C_DEVICE + I2C_WRITE); // set device address & write mode i2c.write(DS2482_CMD_1WT); i2c.write(search_direction ? 0x80 : 0x00); i2c.start(); i2c.write(OW_I2C_DEVICE + I2C_READ); // loop checking 1WB bit for completion of 1-Wire operation // abort if poll limit reached status = i2c.read(ACK); do { status = i2c.read(ACK); } while ((status & DS2482_STATUS_1WB) && (poll_count++ < POLL_LIMIT)); status = i2c.read(NAK); i2c.stop(); // check for failure due to poll limit reached if (poll_count >= POLL_LIMIT) { // handle error // ... reset(); return 0; } // return status byte return status; } //-------------------------------------------------------------------------- // Set the 1-Wire Net communication speed. // // 'new_speed' - new speed defined as // MODE_STANDARD 0x00 // MODE_OVERDRIVE 0x01 // // Returns: current 1-Wire Net speed // uint8_t DS2482::OWSpeed(uint8_t new_speed) { // set the speed if (new_speed == MODE_OVERDRIVE) { c1WS = DS2482_CFG_1WS; } else { c1WS = FALSE; } // write the new config write_config(c1WS | cSPU | cPPM | cAPU); return new_speed; } //-------------------------------------------------------------------------- // Set the 1-Wire Net line level pullup to normal. The DS2482 only // allows enabling strong pullup on a bit or byte event. // Consequently this function only allows the MODE_STANDARD argument. // To enable strong pullup // use OWWriteBytePower or OWReadBitPower. // // 'new_level' - new level defined as // MODE_STANDARD 0x00 // // Returns: current 1-Wire Net level // uint8_t DS2482::OWLevel(uint8_t new_level) { // function only will turn back to non-strong pullup if (new_level != MODE_STANDARD) { return MODE_STRONG; } // clear the strong pullup bit in the global config state cSPU = FALSE; // write the new config write_config(c1WS | cSPU | cPPM | cAPU); return MODE_STANDARD; } //-------------------------------------------------------------------------- // Send 1 bit of communication to the 1-Wire Net and verify that the // response matches the 'applyPowerResponse' bit and apply power delivery // to the 1-Wire net. Note that some implementations may apply the power // first and then turn it off if the response is incorrect. // // 'applyPowerResponse' - 1 bit response to check, if correct then start // power delivery // // Returns: TRUE: bit written and response correct, strong pullup now on // FALSE: response incorrect // uint8_t DS2482::OWReadBitPower(uint8_t applyPowerResponse) { uint8_t rdbit; // set strong pullup enable cSPU = DS2482_CFG_SPU; // write the new config if (!write_config(c1WS | cSPU | cPPM | cAPU)) { return FALSE; } // perform read bit rdbit = OWReadBit(); // check if response was correct, if not then turn off strong pullup if (rdbit != applyPowerResponse) { OWLevel(MODE_STANDARD); return FALSE; } return TRUE; } //-------------------------------------------------------------------------- // Send 8 bits of communication to the 1-Wire Net and verify that the // 8 bits read from the 1-Wire Net are the same (write operation). // The parameter 'sendbyte' least significant 8 bits are used. After the // 8 bits are sent change the level of the 1-Wire net. // // 'sendbyte' - 8 bits to send (least significant bit) // // Returns: TRUE: bytes written and echo was the same, strong pullup now on // FALSE: echo was not the same // uint8_t DS2482::OWWriteBytePower(uint8_t sendbyte) { // set strong pullup enable cSPU = DS2482_CFG_SPU; // write the new config if (!write_config(c1WS | cSPU | cPPM | cAPU)) { #if OW_MASTER_DEBUG printf("\r\nSPU off"); #endif return FALSE; } // perform write byte OWWriteByte(sendbyte); return TRUE; } // end I2C DS2482 //======================================================================