Implementation of 1-Wire with added Alarm Search Functionality

Dependents:   Max32630_One_Wire_Interface

OneWire_Bridge/DS28E17/ds28e17.cpp

Committer:
j3
Date:
2016-03-18
Revision:
17:b646b1e3970b
Parent:
13:d1bdb03703de
Child:
22:686273e55cdc

File content as of revision 17:b646b1e3970b:

/******************************************************************//**
* Copyright (C) 2016 Maxim Integrated Products, Inc., 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 MAXIM INTEGRATED 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.
*
* Except as contained in this notice, the name of Maxim Integrated
* Products, Inc. shall not be used except as stated in the Maxim Integrated
* Products, Inc. Branding Policy.
*
* The mere transfer of this software does not imply any licenses
* of trade secrets, proprietary technology, copyrights, patents,
* trademarks, maskwork rights, or any other form of intellectual
* property whatsoever. Maxim Integrated Products, Inc. retains all
* ownership rights.
**********************************************************************/


#include "ds28e17.h" 

const uint16_t Ds28e17::_oddparity[] = { 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0 };


//*********************************************************************
Ds28e17::Ds28e17(OneWireInterface &owm)
:_owm(owm)
{
    
}


//*********************************************************************
void Ds28e17::set_rom_id(const RomId &romId)
{
    _romId = romId;
}


//*********************************************************************
RomId Ds28e17::get_rom_id(void)
{
    return _romId;
}


//*********************************************************************
Ds28e17::CmdResult Ds28e17::I2C_WriteDataWithStop(uint8_t I2C_addr, uint8_t length, 
                                    uint8_t *data, uint8_t &status, 
                                    uint8_t &wr_status)
{
    Ds28e17::CmdResult bridge_result = Ds28e17::OperationFailure;
    
    size_t send_cnt = 0;
    uint8_t send_block[0xff];
    
    OneWireInterface::CmdResult ow_result = _owm.OWMatchROM(_romId);
    
    if(ow_result == OneWireInterface::Success)
    {
        //seed the crc
        _crc16 = 0;
        
        // Form the 1-Wire Packet 
        
        // I2C Write Data with Stop command
        send_block[send_cnt] = CMD_I2C_WRITE_W_STOP;
        docrc16(send_block[send_cnt++]);
        
        // I2C Address
        send_block[send_cnt] = I2C_addr;
        docrc16(send_block[send_cnt++]);
        
        // Length field
        send_block[send_cnt] = length;
        docrc16(send_block[send_cnt++]);
        
        // Form the write data  
        for (size_t idx = 0; idx < length; idx++) 
        {
            send_block[send_cnt] = data[idx];
            docrc16(send_block[send_cnt++]);
        }
        
        // Form the CRC16
        _crc16 = _crc16^0xFFFF;
        send_block[send_cnt++] = ((uint8_t)(_crc16 & 0xFF));
        send_block[send_cnt++] = ((uint8_t)((_crc16 >> 8) & 0xFF));
        
        // Send Packet
        bridge_result = send_packet(send_block, send_cnt, status, wr_status);
    }
    
    return bridge_result;
}


//*********************************************************************
Ds28e17::CmdResult Ds28e17::I2C_WriteDataNoStop(uint8_t I2C_addr, uint8_t length, 
                                  uint8_t *data, uint8_t &status, 
                                  uint8_t &wr_status)
{
    Ds28e17::CmdResult bridge_result = Ds28e17::OperationFailure;
    
    size_t send_cnt = 0;
    uint8_t send_block[0xff];
    
    OneWireInterface::CmdResult ow_result = _owm.OWMatchROM(_romId);
    
    if(ow_result == OneWireInterface::Success)
    {
        // seed the crc
        _crc16 = 0;
        
        // I2C Write Data with Stop command
        send_block[send_cnt] = CMD_I2C_WRITE_NO_STOP;
        docrc16(send_block[send_cnt++]);
        
        // I2C Address
        send_block[send_cnt] = I2C_addr;
        docrc16(send_block[send_cnt++]);
        
        // Length field
        send_block[send_cnt] = length;
        docrc16(send_block[send_cnt++]);
        
        // Form the write data
        for(size_t idx = 0; idx < length; idx++)
        {
            send_block[send_cnt] = data[idx];
            docrc16(send_block[send_cnt++]);
        }
        
        // Form the CRC16
        _crc16 = _crc16^0xFFFF;
        send_block[send_cnt++] = ((uint8_t)(_crc16 & 0xFF));
        send_block[send_cnt++] = ((uint8_t)((_crc16 >> 8) & 0xFF));
        
        // Send Packet
        bridge_result = send_packet(send_block, send_cnt, status, wr_status);
    }
    
    return bridge_result;
}


//*********************************************************************
Ds28e17::CmdResult Ds28e17::I2C_WriteDataOnly(uint8_t length, uint8_t *data, 
                                uint8_t &status, uint8_t &wr_status)
{
    Ds28e17::CmdResult bridge_result = Ds28e17::OperationFailure;
    
    size_t send_cnt = 0;
    uint8_t send_block[0xff];
    
    OneWireInterface::CmdResult ow_result = _owm.OWMatchROM(_romId);
    
    if(ow_result == OneWireInterface::Success)
    {
        // seed the crc
        _crc16 = 0;
        
        // Form the 1-Wire Packet
        
        // I2C Write Data with Stop command
        send_block[send_cnt] = CMD_I2C_WRITE_ONLY;
        docrc16(send_block[send_cnt++]);
        
        // Length field
        send_block[send_cnt] = length;
        docrc16(send_block[send_cnt++]);
        
        // Form the write data
        for (size_t idx = 0; idx < length; idx++) 
        {
            send_block[send_cnt] = data[idx];
            docrc16(send_block[send_cnt++]);
        }
        
        // Form the CRC16\
        _crc16 = _crc16^0xFFFF;
        send_block[send_cnt++] = (_crc16 & 0xFF);
        send_block[send_cnt++] = ((_crc16 >> 8) & 0xFF);
        
        // Send Packet
        bridge_result = send_packet(send_block, send_cnt, status, wr_status);
    }
    
    return bridge_result;
}


//*********************************************************************
Ds28e17::CmdResult Ds28e17::I2C_WriteDataOnlyWithStop(uint8_t length, uint8_t *data, 
                                        uint8_t &status, uint8_t &wr_status)
{
    Ds28e17::CmdResult bridge_result = Ds28e17::OperationFailure;
    
    size_t send_cnt = 0;
    uint8_t send_block[0xff];
    
    OneWireInterface::CmdResult ow_result = _owm.OWMatchROM(_romId);
    
    if(ow_result == OneWireInterface::Success)
    {
        //seed the crc
        _crc16 = 0;
    
        // Form the 1-Wire Packet
    
        // I2C Write Data with Stop command
        send_block[send_cnt] = CMD_I2C_WRITE_ONLY_W_STOP;
        docrc16(send_block[send_cnt++]);
    
        // Length field
        send_block[send_cnt] = length;
        docrc16(send_block[send_cnt++]);
    
        // Form the write data
        for (size_t idx = 0; idx < length; idx++) 
        {
            send_block[send_cnt] = data[idx];
            docrc16(send_block[send_cnt++]);
        }
    
        // Form the CRC16
        _crc16 = _crc16^0xFFFF;
        send_block[send_cnt++] = (_crc16 & 0xFF);
        send_block[send_cnt++] = ((_crc16 >> 8) & 0xFF);
    
        // Send Packet
        bridge_result = send_packet(send_block, send_cnt, status, wr_status);
    } 
    
    return bridge_result;
}


//*********************************************************************
Ds28e17::CmdResult Ds28e17::I2C_WriteReadDataWithStop(uint8_t I2C_addr, uint8_t length, 
                                        uint8_t *data, uint8_t nu_bytes_read, 
                                        uint8_t &status, uint8_t &wr_status, 
                                        uint8_t *read_data)
{
    Ds28e17::CmdResult bridge_result = Ds28e17::OperationFailure;
    
    size_t send_cnt = 0;
    size_t idx = 0;
    uint8_t send_block[0xff];
    
    OneWireInterface::CmdResult ow_result = _owm.OWMatchROM(_romId);
    
    if(ow_result == OneWireInterface::Success)
    {
        //seed the crc
        _crc16 = 0;
    
        // Form the 1-Wire Packet
    
        // I2C Write Data with Stop command
        send_block[send_cnt] = CMD_I2C_WRITE_READ_W_STOP;
        docrc16(send_block[send_cnt++]);
    
        // I2C Address
        send_block[send_cnt] = I2C_addr;
        docrc16(send_block[send_cnt++]);
    
        // Length field
        send_block[send_cnt] = length;
        docrc16(send_block[send_cnt++]);
    
        // Form the write data
        for (idx = 0; idx < length; idx++) 
        {
            send_block[send_cnt] = data[idx];
            docrc16(send_block[send_cnt++]);
        }
    
        // # of bytes to Read field
        send_block[send_cnt] = nu_bytes_read;
        docrc16(send_block[send_cnt++]);
    
        // Form the CRC16
        _crc16 = _crc16^0xFFFF;
        send_block[send_cnt++] = (_crc16 & 0xFF);
        send_block[send_cnt++] = ((_crc16 >> 8) & 0xFF);
    
        // Send Packet
        bridge_result = send_packet(send_block, send_cnt, status, wr_status);
        if(bridge_result == Ds28e17::Success)
        {
            ow_result = _owm.OWReadBlock(read_data, nu_bytes_read);
            if(ow_result == OneWireInterface::Success)
            {
                bridge_result = Ds28e17::Success;
            }
            else
            {
                bridge_result = Ds28e17::CommsReadBlockError;
            }
        }
    }
    
    return bridge_result;
}


//*********************************************************************
Ds28e17::CmdResult Ds28e17::I2C_ReadDataWithStop(uint8_t I2C_addr, uint8_t nu_bytes_read, 
                                   uint8_t &status, uint8_t *read_data)
{
    Ds28e17::CmdResult  bridge_result = Ds28e17::OperationFailure;
    
    size_t send_cnt = 0;
    uint8_t send_block[0xff];
    
    OneWireInterface::CmdResult ow_result = _owm.OWMatchROM(_romId);
    
    if(ow_result == OneWireInterface::Success)
    {
        //seed the crc for transmit bytes
        _crc16 = 0;
    
        // Form the 1-Wire Packet to send
    
        // I2C Write Data with Stop command
        send_block[send_cnt] = CMD_I2C_READ_W_STOP;
        docrc16(send_block[send_cnt++]);
    
        // I2C Address
        send_block[send_cnt] = I2C_addr;
        docrc16(send_block[send_cnt++]);
    
        // # of bytes to Read field
        send_block[send_cnt] = nu_bytes_read;
        docrc16(send_block[send_cnt++]);
    
        // Form the CRC16
        _crc16 = _crc16^0xFFFF;
        send_block[send_cnt++] = (_crc16 & 0xFF);
        send_block[send_cnt++] = ((_crc16 >> 8) & 0xFF);
    
        // Send Packet
        bridge_result = send_packet(send_block, send_cnt, status);
        if(bridge_result == Ds28e17::Success)
        {
            ow_result = _owm.OWReadBlock(read_data, nu_bytes_read);
            if(ow_result == OneWireInterface::Success)
            {
                bridge_result = Ds28e17::Success;
            }
            else
            {
                bridge_result = Ds28e17::CommsReadBlockError;
            }
        }
    }
    
    return bridge_result;
}


//*********************************************************************
Ds28e17::CmdResult Ds28e17::WriteConfigReg(uint8_t data)
{
    Ds28e17::CmdResult bridge_result = Ds28e17::OperationFailure;
    
    OneWireInterface::CmdResult ow_result = _owm.OWMatchROM(_romId);
    
    if(ow_result == OneWireInterface::Success)
    {
        // Send CMD and Data
        uint8_t send_block[] = {CMD_WRITE_CONFIG_REG, data};
        
        ow_result = _owm.OWWriteBlock(send_block, 2);
        if(ow_result == OneWireInterface::Success)
        {
            _i2c_speed = data & 0x03; // Save off _i2c_speed setting to be used by other functions
            bridge_result = Ds28e17::Success;
        }
        else
        {
            bridge_result = Ds28e17::CommsWriteBlockError;
        }
    }
    
    return bridge_result;
}


//*********************************************************************
Ds28e17::CmdResult Ds28e17::ReadConfigReg(uint8_t & config)
{
    Ds28e17::CmdResult bridge_result = Ds28e17::OperationFailure;
    
    OneWireInterface::CmdResult ow_result = _owm.OWMatchROM(_romId);
    
    if(ow_result == OneWireInterface::Success)
    {
        // Send CMD and receive Data
        ow_result = _owm.OWWriteByte(CMD_READ_CONFIG_REG);
        if(ow_result == OneWireInterface::Success)
        {
            ow_result = _owm.OWReadByte(config);
            if(ow_result == OneWireInterface::Success)
            {
                bridge_result = Ds28e17::Success;
            }
            else
            {
                bridge_result = Ds28e17::CommsReadByteError;
            }
        }
        else
        {
            bridge_result = Ds28e17::CommsWriteByteError;
        }
    }
    
    return bridge_result;
}


//*********************************************************************
Ds28e17::CmdResult Ds28e17::DisableOWMode()
{
    Ds28e17::CmdResult bridge_result = Ds28e17::OperationFailure;
    
    OneWireInterface::CmdResult ow_result = _owm.OWMatchROM(_romId);
    
    if(ow_result == OneWireInterface::Success)
    {
        // Send CMD
        ow_result = _owm.OWWriteByte(CMD_DISABLE_OW_MODE);
        if(ow_result == OneWireInterface::Success)
        {
            bridge_result = Ds28e17::Success;
        }
        else
        {
            bridge_result = Ds28e17::CommsWriteByteError;
        }
    }
    
    return bridge_result;
}


//*********************************************************************
Ds28e17::CmdResult Ds28e17::EnableSleepMode()
{
    Ds28e17::CmdResult bridge_result = Ds28e17::OperationFailure;
    
    OneWireInterface::CmdResult ow_result = _owm.OWMatchROM(_romId);
    
    if(ow_result == OneWireInterface::Success)
    {
        // Send CMD
        ow_result = _owm.OWWriteByte(CMD_ENABLE_SLEEP_MODE);
        if(ow_result == OneWireInterface::Success)
        {
            bridge_result = Ds28e17::Success;
        }
        else
        {
            bridge_result = Ds28e17::CommsWriteByteError;
        }
    }
    
    return bridge_result;
}


//*********************************************************************
Ds28e17::CmdResult Ds28e17::ReadDeviceRevision(uint8_t & rev)
{
    Ds28e17::CmdResult bridge_result = Ds28e17::OperationFailure;
    
    OneWireInterface::CmdResult ow_result = _owm.OWMatchROM(_romId);
    
    if(ow_result == OneWireInterface::Success)
    {
        // Send CMD and receive Data
        ow_result = _owm.OWWriteByte(CMD_READ_DEVICE_REV);
        if(ow_result == OneWireInterface::Success)
        {
            ow_result = _owm.OWReadByte(rev);
            if(ow_result == OneWireInterface::Success)
            {
                bridge_result = Ds28e17::Success;
            }
            else
            {
                bridge_result = Ds28e17::CommsReadByteError;
            }
        }
        else
        {
            bridge_result = Ds28e17::CommsWriteByteError;
        }
    }
    
    return bridge_result;
}


//*********************************************************************
uint16_t Ds28e17::docrc16(uint16_t data)
{
    data = ((data ^ (_crc16 & 0xff)) & 0xff);
    _crc16 >>= 8;

    if (Ds28e17::_oddparity[data & 0xf] ^ Ds28e17::_oddparity[data >> 4])
    {
        _crc16 ^= 0xc001;
    }

    data <<= 6;
    _crc16  ^= data;
    data <<= 1;
    _crc16   ^= data;

    return _crc16;
}


//*********************************************************************
Ds28e17::CmdResult Ds28e17::send_packet(const uint8_t * data, uint8_t data_length,
                                        uint8_t & status, uint8_t & wr_status)
{
    Ds28e17::CmdResult bridge_result = Ds28e17::CommsWriteBlockError;
    uint32_t poll_count = 0;
    
    OneWireInterface::CmdResult ow_result = _owm.OWWriteBlock(data, data_length);
    
    if(ow_result == OneWireInterface::Success) 
    {
        // Poll for Zero 1-Wire bit and return if an error occurs
        uint8_t recvbit = 0x01;
        do 
        {
            ow_result = _owm.OWReadBit(recvbit);
        } 
        while(recvbit && (poll_count++ < POLL_LIMIT) && (ow_result == OneWireInterface::Success));

        if(ow_result == OneWireInterface::Success) 
        {
            if(poll_count < POLL_LIMIT) 
            {
                //Read Status and write status
                uint8_t read_block[2];
                
                ow_result = _owm.OWReadBlock(read_block, 2);
                
                if(ow_result == OneWireInterface::Success) 
                {
                    status = read_block[0];
                    wr_status = read_block[1];
                    bridge_result = Ds28e17::Success;
                } 
                else
                {
                   bridge_result = Ds28e17::CommsReadBlockError;
                }
            } 
            else 
            {
                bridge_result = Ds28e17::TimeoutError;
            }
        } 
        else 
        {
            bridge_result = Ds28e17::CommsReadBitError;
        }
    } 
    
    return bridge_result;
}


//*********************************************************************
Ds28e17::CmdResult Ds28e17::send_packet(const uint8_t * data, uint8_t data_length, 
                                        uint8_t & status)
{
    Ds28e17::CmdResult bridge_result = Ds28e17::CommsWriteBlockError;
    uint32_t poll_count = 0;
    
    OneWireInterface::CmdResult ow_result = _owm.OWWriteBlock(data, data_length);
    
    if(ow_result == OneWireInterface::Success) 
    {
        // Poll for Zero 1-Wire bit and return if an error occurs
        uint8_t recvbit = 0x01;
        do 
        {
            ow_result = _owm.OWReadBit(recvbit);
        } 
        while(recvbit && (poll_count++ < POLL_LIMIT) && (ow_result == OneWireInterface::Success));

        if(ow_result == OneWireInterface::Success) 
        {
            if(poll_count < POLL_LIMIT) 
            {
                //Read Status 
                ow_result = _owm.OWReadByte(status);
                if(ow_result == OneWireInterface::Success) 
                {
                    bridge_result = Ds28e17::Success;
                } 
                else
                {
                    bridge_result = Ds28e17::CommsReadByteError;
                }
            } 
            else 
            {
                bridge_result = Ds28e17::TimeoutError;
            }
        } 
        else 
        {
            bridge_result = Ds28e17::CommsReadBitError;
        }
    } 
    
    return bridge_result;
}