Implementation of 1-Wire with added Alarm Search Functionality
Dependents: Max32630_One_Wire_Interface
Diff: Bridge/DS28E17/DS28E17.cpp
- Revision:
- 73:2cecc1372acc
- Parent:
- 27:d5aaefa252f1
- Child:
- 74:23be10c32fa3
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Bridge/DS28E17/DS28E17.cpp Thu May 12 14:38:16 2016 -0500 @@ -0,0 +1,631 @@ +/******************************************************************//** +* 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" +#include "Masters/OneWireMaster.h" + +using OneWire::Bridge::DS28E17; +using OneWire::Masters::OneWireMaster; + +const uint16_t DS28E17::_oddparity[] = { 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0 }; + + +//********************************************************************* +DS28E17::DS28E17(OneWireMaster &owm) +: _owm(owm) +{ + +} + + +//********************************************************************* +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]; + + OneWireMaster::CmdResult ow_result = _owm.OWMatchROM(romId); + + if(ow_result == OneWireMaster::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]; + + OneWireMaster::CmdResult ow_result = _owm.OWMatchROM(romId); + + if(ow_result == OneWireMaster::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]; + + OneWireMaster::CmdResult ow_result = _owm.OWMatchROM(romId); + + if(ow_result == OneWireMaster::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]; + + OneWireMaster::CmdResult ow_result = _owm.OWMatchROM(romId); + + if(ow_result == OneWireMaster::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]; + + OneWireMaster::CmdResult ow_result = _owm.OWMatchROM(romId); + + if(ow_result == OneWireMaster::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 == OneWireMaster::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]; + + OneWireMaster::CmdResult ow_result = _owm.OWMatchROM(romId); + + if(ow_result == OneWireMaster::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 == OneWireMaster::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; + + OneWireMaster::CmdResult ow_result = _owm.OWMatchROM(romId); + + if(ow_result == OneWireMaster::Success) + { + // Send CMD and Data + uint8_t send_block[] = {CMD_WRITE_CONFIG_REG, data}; + + ow_result = _owm.OWWriteBlock(send_block, 2); + if(ow_result == OneWireMaster::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; + + OneWireMaster::CmdResult ow_result = _owm.OWMatchROM(romId); + + if(ow_result == OneWireMaster::Success) + { + // Send CMD and receive Data + ow_result = _owm.OWWriteByte(CMD_READ_CONFIG_REG); + if(ow_result == OneWireMaster::Success) + { + ow_result = _owm.OWReadByte(config); + if(ow_result == OneWireMaster::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; + + OneWireMaster::CmdResult ow_result = _owm.OWMatchROM(romId); + + if(ow_result == OneWireMaster::Success) + { + // Send CMD + ow_result = _owm.OWWriteByte(CMD_DISABLE_OW_MODE); + if(ow_result == OneWireMaster::Success) + { + bridge_result = DS28E17::Success; + } + else + { + bridge_result = DS28E17::CommsWriteByteError; + } + } + + return bridge_result; +} + + +//********************************************************************* +DS28E17::CmdResult DS28E17::EnableSleepMode() +{ + DS28E17::CmdResult bridge_result = DS28E17::OperationFailure; + + OneWireMaster::CmdResult ow_result = _owm.OWMatchROM(romId); + + if(ow_result == OneWireMaster::Success) + { + // Send CMD + ow_result = _owm.OWWriteByte(CMD_ENABLE_SLEEP_MODE); + if(ow_result == OneWireMaster::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; + + OneWireMaster::CmdResult ow_result = _owm.OWMatchROM(romId); + + if(ow_result == OneWireMaster::Success) + { + // Send CMD and receive Data + ow_result = _owm.OWWriteByte(CMD_READ_DEVICE_REV); + if(ow_result == OneWireMaster::Success) + { + ow_result = _owm.OWReadByte(rev); + if(ow_result == OneWireMaster::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; + + OneWireMaster::CmdResult ow_result = _owm.OWWriteBlock(data, data_length); + + if(ow_result == OneWireMaster::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 == OneWireMaster::Success)); + + if(ow_result == OneWireMaster::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 == OneWireMaster::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; + + OneWireMaster::CmdResult ow_result = _owm.OWWriteBlock(data, data_length); + + if(ow_result == OneWireMaster::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 == OneWireMaster::Success)); + + if(ow_result == OneWireMaster::Success) + { + if(poll_count < POLL_LIMIT) + { + //Read Status + ow_result = _owm.OWReadByte(status); + if(ow_result == OneWireMaster::Success) + { + bridge_result = DS28E17::Success; + } + else + { + bridge_result = DS28E17::CommsReadByteError; + } + } + else + { + bridge_result = DS28E17::TimeoutError; + } + } + else + { + bridge_result = DS28E17::CommsReadBitError; + } + } + + return bridge_result; +} +