one wire driver

Dependents:   09_PT1000 10_PT1000 11_PT1000

DS2482.cpp

Committer:
rs27
Date:
2014-07-26
Revision:
5:d94037eb31ed
Parent:
4:c29e67d55f86

File content as of revision 5:d94037eb31ed:



#include "mbed.h"
#include "DS2482.h"
#include "monitor.h"

extern Serial pc;

//-----------------------------------------------------------------------------
// 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;
}

uint8_t DS2482::crc_calc_buffer(uint8_t *pbuffer, uint8_t count)
{
  uint8_t n;

  crc_value = 0;

  for (n = 0; n < count; n++)
  {
    crc_value = crc_table[crc_value ^ *pbuffer++];
  }

  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
            pc.printf("\r\n--- DS2482 bus0 reset not executed \n");
            wait(0.1);
        #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
            pc.printf("\r\n--- DS2482 configuration failure \n");
            wait(0.1);
        #endif

        return false;
    }

    #if OW_MASTER_START
        pc.printf("\r\n*** DS2482 detect OK \n");
        wait(0.1);
    #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;
    // pc.printf("\nreset write");
    i2c.write(addr, cmd, 1);
    // pc.printf("\nreset read");
    i2c.read(addr, cmd, 1);
    // pc.printf("  cmd = %02x \n",cmd[0]);
    wait(0.1);
    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
            pc.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 poll_count = 0;
    char cmd[2];
    
    cmd[0] = DS2482_CMD_1WRS;
    i2c.write(addr,cmd,1);

    #if OW_MASTER_DEBUG
        pc.printf("\r\n*** Reset all devices on the 1-Wire Net\r\n");
    #endif
    
    do
    {
       i2c.read(addr,cmd,1);
       // pc.printf("\n read %04x",cmd[0]);
    }
    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
            pc.printf("\r\n---poll limit reached");
        #endif

        reset();
        return false;
    }

    // check for short condition
    if (cmd[0] & DS2482_STATUS_SD)
    {
        #if OW_MASTER_DEBUG     
            pc.printf("\r\n---1-Wire Net short detected %04x",cmd[0]);
        #endif

        short_detected = true;
    }
    else
    {
        #if OW_MASTER_DEBUG
            pc.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         
            pc.printf("\r\n*** 1-Wire Device detected");
        #endif
                
        return true;
    }
    else
    {
        #if OW_MASTER_DEBUG     
            pc.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
        pc.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
            pc.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
        pc.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
            pc.printf("\r\n---handle error OW Write Byte");
        #endif

        reset();
    }
    
    #if OW_MASTER_DEBUG
        pc.printf(" done");
    #endif
}

//--------------------------------------------------------------------------
// 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 poll_count = 0;
    char cmd[2];
    
    #if OW_MASTER_DEBUG
        pc.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(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
            pc.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
        pc.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
        pc.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 
        pc.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 OW_MASTER_DEBUG
        pc.printf("\r\n*** one wire search");
    #endif
    
    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
            //pc.printf("\n *** preform triplet operation ");
            status = search_triplet(search_direction);
            //pc.printf("%04x",status);
            
            // 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;
    }

    #if OW_MASTER_DEBUG
        pc.printf(" pass ");
    #endif
    
    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)
{
    char cmd[2];
    uint8_t status, poll_count = 0;

    cmd[0] = DS2482_CMD_1WT;
    cmd[1] = (search_direction ? 0x80 : 0x00);
    i2c.write(addr,cmd,2);
    
    do
    {
        i2c.read(addr,cmd,1);
        status = cmd[0];
    }
    while ((status & DS2482_STATUS_1WB) && (poll_count++ < POLL_LIMIT));

    // 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
            pc.printf("\r\nSPU off");
        #endif

        return FALSE;
    }

    // perform write byte
    OWWriteByte(sendbyte);

    return TRUE;
}


// end I2C DS2482
//======================================================================

//---------------------------------------------------------------------------
//-------------------------DS18XX OPERATIONS---------------------------------
//---------------------------------------------------------------------------
// find ALL devices on bus 1
//
void DS2482::DS18XX_Read_Address(void)
{
    uint8_t status, i, j;  
    
    //--------------------------------------------------------------
    // Device Tabele für bus 1 und bus 2 löschen

    for (i = 0; i < OW_MAX_DEVICES; i++)
    {
        for (j = 0; j < 8; j++)
        {
            ow.device_table[i].rom[j] = 0;
        }
    }
    
    // pc.printf("\n --- DS18xx_Read_Address --- ");
    // wait(0.1); 
    
    ow.devices = 0;
    
    //--------------------------------------------------------------
    // die Bausteine am Bus suchen
    
    //pc.printf("\n -- detect -- \n");
    //wait(0.5);    
    detect();    // reset and init the 1-wire master
    
    //pc.printf("\n -- OWFirst --\n");
    //wait(0.1);
    status = OWFirst();

    if(status == 0)
    {
        #if OW_MASTER_START
            pc.printf("\r\nno 1-Wire slaves found");
        #endif
    }

    while(status)
    {
        // TODO hier ins eeprom schreiben
        #if OW_MASTER_START
            pc.printf("\n*** #%02d ROM_NO= ",ow.devices);
            wait(0.1);
        #endif

        for (uint8_t i = 0; i < 8; i++)
        {
            ow.device_table[ow.devices].rom[i] = ROM_NO[i]; 
            
            #if OW_MASTER_START
                pc.printf(" 0x%02x",ROM_NO[i]);
                wait (0.1);          
            #endif
        }
        ow.device_table[ow.devices].status = 0x01; // Wandler gefunden

        status = OWNext();
        ow.devices++;      // Zeiger auf den nächsten freien Baustein

        // maximal 16 Bausteine
        if (ow.devices >= OW_MAX_DEVICES) 
        {
            ow.devices--; // zeiget auf den letzten gültigen Baustein
            return;
        }
    }
        
    #if OW_MASTER_START
        pc.printf("\r\n");
    #endif
                
    return;
}

//---------------------------------------------------------------------------
//
void DS2482::start_conversion(void)
{
    //--------------------------------------------------------------
    // alle Bausteine an bus 0 starten

    // find a DS18S20
    OWFirst();
    OWReset();

    // address all devices
    OWWriteByte(OW_SKIP_ROM);

    //  Start Conversion and Config Strong Pull-Up
    if (!OWWriteBytePower(OW_CONVERT_TEMP))
    {
        #if OW_MASTER_DEBUG
            pc.printf("Fail convert command\r\n");
        #endif
    }
    
    //--------------------------------------------------------------
    // alle Bausteine an bus 1 starten
    
    // find a DS18S20
    OWFirst();
    OWReset();

    // address all devices
    OWWriteByte(OW_SKIP_ROM);

    //  Start Conversion and Config Strong Pull-Up
    if (!OWWriteBytePower(OW_CONVERT_TEMP))
    {
        #if OW_MASTER_DEBUG
            pc.printf("Fail convert command\r\n");
        #endif
    }

}

//-----------------------------------------------------------------------------

bool DS2482::ow_read_rom(void)
{
  uint8_t n;

  // Write Read ROM Code command
  OWWriteByte(OW_CMD_READ_ROM);

  // Read 8 bytes of ROM code
  for (n = 0; n < 8; n++)
  {
    ow_rom_code[n] = OWReadByte();
  }

  // Do Cyclic Redundancy Check
  if (crc_calc_buffer(&ow_rom_code[0],7) != ow_rom_code[7])
  {
    ow_flags |= OW_CRC_ERROR;

    return false;
  }

  return true;
}

//-----------------------------------------------------------------------------

bool DS2482::ow_read_scratchpad(void)
{
    uint8_t i, crc;

    ow_flags = 0;

    if (!OWReset()) return false;

    // select the device
    // den Baustein wird über den ROM Code adressiert
    OWWriteByte(OW_CMD_MATCH_ROM); // 0x55 match command

    for (i = 0; i < 8; i++)
    {
        OWWriteByte(ow.device_table[ow.device_table_index].rom[i]);
    }
 
    OWWriteByte(OW_CMD_READ_SCRATCHPAD);    // Read Scratch pad 0xBE

    // Read 9 bytes of scratchpad memory
    for (i = 0; i < OW_SCRATCHPAD_BYTES; i++)
    {
        crc = OWReadByte();
        ow_scratchpad[i] = crc;
    }

    #if OW_MASTER_DEBUG

        pc.printf("\n*** Scratch_Val ");

        for (i = 1; i < OW_SCRATCHPAD_BYTES; i++)
        {
            pc.printf(":0x%02x",ow_scratchpad[i]);
        }

        pc.printf("\r\n");

    #endif  

    
    return true;
}

//-----------------------------------------------------------------------------

bool DS2482::ow_read_scratchpad_ds2438(uint8_t page)
{
    uint8_t n, crc;

    ow_flags = 0;

    if (!OWReset()) return false;

    // select the device
    // den Baustein wird über den ROM Code adressiert
    OWWriteByte(OW_CMD_MATCH_ROM); // 0x55 match command

    for (n = 0; n < 8; n++)
    {
        OWWriteByte(ow.device_table[ow.device_table_index].rom[n]);
    }
  
    // Write command to read scratchpad memory
    OWWriteByte(0xbe);                      // 0xBE
    OWWriteByte(page);                      // 0x03

    // Read 9 bytes of scratchpad memory
    for (n = 0; n < OW_SCRATCHPAD_BYTES; n++)
    {
        crc = OWReadByte();
        ow_scratchpad[n] = crc;
        // printf_P(PSTR("%02x "),crc);
    }

    crc = crc_calc_buffer(ow_scratchpad,8);
  
    // Calculate CRC
    if (crc != ow_scratchpad[8])
    {
        ow_flags |= OW_CRC_ERROR;
        // Read 9 bytes of scratchpad memory
        pc.printf("\now_read_scratchpad: ");
        for (n = 0; n < OW_SCRATCHPAD_BYTES; n++)
        {
            pc.printf("%02x ",ow_scratchpad[n]);
        }       
        pc.printf(": CRC error %02x",crc);
        return false;
    }   
    return true;
}

//----------------------------------------------------------------------------

bool DS2482::ow_write_scratchpad_ds18x20 (uint8_t th, uint8_t tl)
{
    uint8_t i;
            
    // Do bus reset
    if (!OWReset()) return false;

    // select the device
    // den Baustein wird über den ROM Code adressiert
    OWWriteByte(OW_CMD_MATCH_ROM); // 0x55 match command

    for (i = 0; i < 8; i++)
    {
        OWWriteByte(ow.device_table[ow.device_table_index].rom[i]);
    }


    // Write command to read scratchpad memory
    OWWriteByte(OW_CMD_WRITE_SCRATCHPAD);

    // Write 1 byte at scratchpad memory
    OWWriteByte(th);    // Th
    wait_us(8);         // ist für das Timing der 8 MHZ CPU notwendig

    // Write 1 byte at scratchpad memory
    OWWriteByte(tl);    // Th
    wait_us(8);       // ist für das Timing der 8 MHZ CPU notwendig

    // Write 1 byte at scratchpad memory
    OWWriteByte(0x7F);  // 12 Bit Auflösung
    wait_us(8);       // ist für das Timing der 8 MHZ CPU notwendig

    return true;
}

//----------------------------------------------------------------------------
bool DS2482::ow_write_scratchpad_ds2438 (uint8_t th, uint8_t tl)
{

    uint8_t i;
            
    // Do bus reset
    if (!OWReset()) return false;

    // select the device
    // den Baustein wird über den ROM Code adressiert
    OWWriteByte(OW_CMD_MATCH_ROM); // 0x55 match command

    for (i = 0; i < 8; i++)
    {
        OWWriteByte(ow.device_table[ow.device_table_index].rom[i]);
    }

    // Write command to read scratchpad memory
    OWWriteByte(0x4E);
    OWWriteByte(0x03);

    // Write 3 bytes to scratchpad memory
    OWWriteByte(th); // Th
    wait_us(8);  

    OWWriteByte(tl); // Tl
    wait_us(8);  

    return true;
}

//----------------------------------------------------------------------------
bool DS2482::ow_write_eeprom_ds18x20 (void)
{

    uint8_t i;                
                              
    // Do bus reset
    if (!OWReset()) return false;

    // select the device
    // den Baustein wird über den ROM Code adressiert
    OWWriteByte(OW_CMD_MATCH_ROM); // 0x55 match command

    for (i = 0; i < 8; i++)
    {
        OWWriteByte(ow.device_table[ow.device_table_index].rom[i]);
    }

    // Write command to write eeprom
    OWWriteByte(0x48);

    return true;

}

//----------------------------------------------------------------------------
bool DS2482::ow_write_eeprom_ds2438 (void)
{
    uint8_t i;
    
    // Do bus reset
    if (!OWReset()) return false;

    // select the device
    // den Baustein wird über den ROM Code adressiert
    OWWriteByte(OW_CMD_MATCH_ROM); // 0x55 match command

    for (i = 0; i < 8; i++)
    {
        OWWriteByte(ow.device_table[ow.device_table_index].rom[i]);
    }

    // Write command to read scratchpad memory
    OWWriteByte(0x48);
    OWWriteByte(0x03);  

    return true;
}


//----------------------------------------------------------------------------

void DS2482::ow_read_address (void)
{
    uint8_t n;

    // ow Adressen aus den Bausteinen lesen
    for (n = 0; n < OW_MAX_DEVICES; n++)
    {           
        if ((ow.device_table[n].status & 0x0f) == 1)
        {   
            // printf_P(PSTR("\n device table %d"),n);
            ow.device_table_index = n; 

            if ((ow.device_table[n].rom[0] == 0x10) || (ow.device_table[n].rom[0] == 0x28))
            {
                if (ow_read_scratchpad())
                {
                    if(ow_scratchpad[2] == ow_scratchpad[3]) ow.device_table[n].adr = ow_scratchpad[3];
                }
            }
            
            if ((ow.device_table[n].rom[0] == 0xa6) || (ow.device_table[n].rom[0] == 0x26))
            {
                if (ow_read_scratchpad_ds2438(0x03))
                {
                    if(ow_scratchpad[0] == ow_scratchpad[1]) ow.device_table[n].adr = ow_scratchpad[0];

                }
            }
            
        }

    } // end for(...
}

//-----------------------------------------------------------------------------

bool DS2482::ds1820_start_conversion(uint8_t command)
{
    uint8_t i;

    // Do bus reset
    if (!OWReset()) return false;

    // Check if a match ROM code must be done or just skip ROM code (0xFF)
    if (command > 0xFE)
    {
        OWWriteByte(OW_CMD_SKIP_ROM); // Send Skip ROM Code command
    }
    else
    {
        // select the device
        // den Baustein wird über den ROM Code adressiert
        OWWriteByte(OW_CMD_MATCH_ROM); // 0x55 match command

        for (i = 0; i < 8; i++)
        {
            OWWriteByte(ow.device_table[ow.device_table_index].rom[i]);
        }
    }

    // Send the "Convert T" command to start conversion
    OWWriteByte(OW_CMD_CONVERT_T);
    
    // Set flag to mark a measurement in progress
    ds1820_request_pending = true;

    return TRUE;
}


//-----------------------------------------------------------------------------

bool DS2482::ds18B20_read_hrtemp(void)
{
  
    union ds18B20_temp_union
    {
        int16_t word;
        uint8_t  byte[2];
    } ds18B20_temp;
    
    // uint8_t temp_lo;
    // uint8_t temp_hi;
    // int8_t digit;
    float ds1820_float_result; 

    // Preset float result to zero in case of function termination (return false)
    //ds1820_float_result = 0.0;
    ow.device_table[ow.device_table_index].result = 0;

    // Return false if reading scratchpad memory fails
    if (!ow_read_scratchpad())
    {
        ow.device_table[ow.device_table_index].status &= 0xf0;
        ow.device_table[ow.device_table_index].status |= 4;
        return FALSE;
    }
    
    ds18B20_temp.byte[0] = ow_scratchpad[DS1820_LSB];
    ds18B20_temp.byte[1] = ow_scratchpad[DS1820_MSB];

    //ds18B20_temp.word <<= 4;  // Vorzeichenbit auf MSB Bit schieben
    //ds18B20_temp.word /= 16;  // die letzten 4 Stellen wieder löschen

    ds1820_float_result = ds18B20_temp.word * 0.0625;
    
    //pc.printf("\nDS18B20 T-Kanal: %d = %2.2f ",ow.device_table_index,ds1820_float_result);
    
    ow.device_table[ow.device_table_index].result = (int16_t)(ds1820_float_result * 100);  
  
    // Clear flag to mark that no measurement is in progress
    ds1820_request_pending = false;
  
    // Flag für erfolgreiches Lesen setzen
    ow.device_table[ow.device_table_index].status &= 0xf0;
    ow.device_table[ow.device_table_index].status |= 3;
  
    return true;
}


//-----------------------------------------------------------------------------