/// <summary> Read a Universal Data Packet. /// /// The Universal Data Packet always starts on page boundaries but /// can end anywhere in the page. The structure specifies the length of /// data bytes not including the length byte and the CRC16 bytes. /// There is one length byte. The CRC16 is first initialized to /// the page number. This provides a check to verify the page that /// was intended is being read. The CRC16 is then calculated over /// the length and data bytes. The CRC16 is then inverted and stored /// low byte first followed by the high byte. This is structure is /// used by this method to verify the data but is not returned, only /// the data payload is returned. /// /// </summary> /// <param name="page"> page number to read packet from /// </param> /// <param name="readContinue"> if 'true' then device read is continued without /// re-selecting. This can only be used if the new /// readPagePacket() continious where the last one /// stopped and it is inside a /// 'beginExclusive/endExclusive' block. /// </param> /// <param name="readBuf"> byte array to put data read. Must have at least /// 'getMaxPacketDataLength()' elements. /// </param> /// <param name="offset"> offset into readBuf to place data /// /// </param> /// <returns> number of data bytes read from the device and written to /// readBuf at the offset. /// /// </returns> /// <throws> OneWireIOException </throws> /// <throws> OneWireException </throws> public virtual int readPagePacket(int page, bool readContinue, byte[] readBuf, int offset) { byte[] raw_buf = new byte[PAGE_LENGTH]; // attempt to put device at speed checkSpeed(); // read the scratchpad, discard extra information readPage(page, readContinue, raw_buf, 0); // check if length is realistic if (raw_buf[0] > (PAGE_LENGTH - 3)) { forceVerify(); throw new OneWireIOException("Invalid length in packet"); } // verify the CRC is correct if (CRC16.compute(raw_buf, 0, raw_buf[0] + 3, page) == 0x0000B001) { // extract the data out of the packet Array.Copy(raw_buf, 1, readBuf, offset, (byte)raw_buf[0]); // return the length return(raw_buf[0]); } else { forceVerify(); throw new OneWireIOException("Invalid CRC16 in packet read"); } }
/// <summary> Read a Universal Data Packet and extra information. See the /// method 'readPagePacket()' for a description of the packet structure. /// See the method 'hasExtraInfo()' for a description of the optional /// extra information some devices have. /// /// </summary> /// <param name="page"> page number to read packet from /// </param> /// <param name="readContinue"> if 'true' then device read is continued without /// re-selecting. This can only be used if the new /// readPagePacket() continious where the last one /// stopped and it is inside a /// 'beginExclusive/endExclusive' block. /// </param> /// <param name="readBuf"> byte array to put data read. Must have at least /// 'getMaxPacketDataLength()' elements. /// </param> /// <param name="offset"> offset into readBuf to place data /// </param> /// <param name="extraInfo"> byte array to put extra info read into /// /// </param> /// <returns> number of data bytes written to readBuf at the offset. /// /// </returns> /// <throws> OneWireIOException </throws> /// <throws> OneWireException </throws> public override int readPagePacket(int page, bool readContinue, byte[] readBuf, int offset, byte[] extraInfo) { byte[] raw_buf = new byte[pageLength]; // read entire page with read page CRC readPageCRC(page, readContinue, raw_buf, 0, extraInfo, extraInfoLength); // check if length is realistic if (raw_buf[0] > maxPacketDataLength) { sp.forceVerify(); throw new OneWireIOException("Invalid length in packet"); } // verify the CRC is correct int abs_page = (startPhysicalAddress / pageLength) + page; if (CRC16.compute(raw_buf, 0, raw_buf[0] + 3, abs_page) == 0x0000B001) { // extract the data out of the packet Array.Copy(raw_buf, 1, readBuf, offset, (byte)raw_buf[0]); // return the length return(raw_buf[0]); } else { sp.forceVerify(); throw new OneWireIOException("Invalid CRC16 in packet read"); } }
//-------- //-------- Information methods //-------- //-------- //-------- Custom Methods for this 1-Wire Device Type //-------- /// <summary> Read the counter value associated with a page on this /// 1-Wire Device. /// /// </summary> /// <param name="counterPage"> page number of the counter to read /// /// </param> /// <returns> 4 byte value counter stored in a long integer /// /// </returns> /// <throws> OneWireIOException on a 1-Wire communication error such as </throws> /// <summary> no 1-Wire device present. This could be /// caused by a physical interruption in the 1-Wire Network due to /// shorts or a newly arriving 1-Wire device issuing a 'presence pulse'. /// </summary> /// <throws> OneWireException on a communication or setup error with the 1-Wire </throws> /// <summary> adapter /// </summary> public virtual long readCounter(int counterPage) { // check if counter page provided is valid if ((counterPage < 12) || (counterPage > 15)) { throw new OneWireException("OneWireContainer1D-invalid counter page"); } // select the device if (adapter.select(this.address)) { int crc16; // read memory command buffer[0] = READ_MEMORY_COMMAND; crc16 = CRC16.compute(READ_MEMORY_COMMAND); // address of last data byte before counter int address = (counterPage << 5) + 31; // append the address buffer[1] = (byte)address; crc16 = CRC16.compute(buffer[1], crc16); buffer[2] = (byte)(SupportClass.URShift(address, 8)); crc16 = CRC16.compute(buffer[2], crc16); // now add the read bytes for data byte,counter,zero bits, crc16 for (int i = 3; i < 14; i++) { buffer[i] = (byte)SupportClass.Identity(0xFF); } // send the block adapter.dataBlock(buffer, 0, 14); // calculate the CRC16 on the result and check if correct if (CRC16.compute(buffer, 3, 11, crc16) == 0xB001) { // extract the counter out of this verified packet ulong return_count = 0; for (int i = 4; i >= 1; i--) { return_count <<= 8; return_count |= (byte)(buffer[i + 3] & (byte)0xFF); } // return the result count return((long)return_count); } } // device must not have been present throw new OneWireIOException("OneWireContainer1D-device not present"); }
/// <summary> Read a complete memory page with CRC verification provided by the /// device. Not supported by all devices. See the method /// 'hasPageAutoCRC()'. /// /// </summary> /// <param name="page"> page number to read /// </param> /// <param name="readContinue"> if 'true' then device read is continued without /// re-selecting. This can only be used if the new /// readPagePacket() continious where the last one /// stopped and it is inside a /// 'beginExclusive/endExclusive' block. /// </param> /// <param name="readBuf"> byte array to put data read. Must have at least /// 'getMaxPacketDataLength()' elements. /// </param> /// <param name="offset"> offset into readBuf to place data /// /// </param> /// <throws> OneWireIOException </throws> /// <throws> OneWireException </throws> public virtual void readPageCRC(int page, bool readContinue, byte[] readBuf, int offset) { byte[] raw_buf = new byte[5 + PAGE_LENGTH]; int len; // attempt to put device at max desired speed if (!readContinue) { checkSpeed(); } // see if need to access the device if (!readContinue) { // select the device if (!ib.adapter.select(ib.address)) { forceVerify(); throw new OneWireIOException("Device select failed"); } // build start reading memory block with: command, address len = raw_buf.Length; Array.Copy(ffBlock, 0, raw_buf, 0, len); raw_buf[0] = READ_MEMORY_COMMAND; int addr = page * PAGE_LENGTH + startPhysicalAddress; raw_buf[1] = (byte)(addr & 0xFF); raw_buf[2] = (byte)((SupportClass.URShift((addr & 0xFFFF), 8)) & 0xFF); } else { len = PAGE_LENGTH + 2; Array.Copy(ffBlock, 0, raw_buf, 0, len); } // do the block ib.adapter.dataBlock(raw_buf, 0, len); // check the CRC if (CRC16.compute(raw_buf, 0, len, 0) != 0x0000B001) { forceVerify(); throw new OneWireIOException("Invalid CRC16 read from device"); } // extract the data to return Array.Copy(raw_buf, len - 2 - PAGE_LENGTH, readBuf, offset, PAGE_LENGTH); }
//-------- //-------- ScratchPad methods //-------- /// <summary> Write to the scratchpad page of memory a NVRAM device. /// /// </summary> /// <param name="startAddr"> starting address /// </param> /// <param name="writeBuf"> byte array containing data to write /// </param> /// <param name="offset"> offset into readBuf to place data /// </param> /// <param name="len"> length in bytes to write /// /// </param> /// <throws> OneWireIOException </throws> /// <throws> OneWireException </throws> public override void writeScratchpad(int startAddr, byte[] writeBuf, int offset, int len) { bool calcCRC = false; if (len > pageLength) { throw new OneWireException("Write exceeds memory bank end"); } // select the device if (!ib.adapter.select(ib.address)) { forceVerify(); throw new OneWireIOException("Device select failed"); } // build block to send byte[] raw_buf = new byte[pageLength + 5]; //[37]; raw_buf[0] = WRITE_SCRATCHPAD_COMMAND; raw_buf[1] = (byte)(startAddr & 0xFF); raw_buf[2] = (byte)((SupportClass.URShift((startAddr & 0xFFFF), 8)) & 0xFF); Array.Copy(writeBuf, offset, raw_buf, 3, len); // check if full page (can utilize CRC) if (((startAddr + len) % pageLength) == 0) { Array.Copy(ffBlock, 0, raw_buf, len + 3, 2); calcCRC = true; } // send block, return result ib.adapter.dataBlock(raw_buf, 0, len + 3 + ((calcCRC)?2:0)); //System.out.println("WriteScratchpad: " + com.dalsemi.onewire.utils.Convert.toHexString(raw_buf)); // check crc if (calcCRC) { if (CRC16.compute(raw_buf, 0, len + 5, 0) != 0x0000B001) { forceVerify(); throw new OneWireIOException("Invalid CRC16 read from device"); } } }
//-------- //-------- ScratchPad methods //-------- /// <summary> Read the scratchpad page of memory from a NVRAM device /// This method reads and returns the entire scratchpad after the byte /// offset regardless of the actual ending offset /// /// </summary> /// <param name="readBuf"> byte array to place read data into /// length of array is always pageLength. /// </param> /// <param name="offset"> offset into readBuf to pug data /// </param> /// <param name="len"> length in bytes to read /// </param> /// <param name="extraInfo"> byte array to put extra info read into /// (TA1, TA2, e/s byte) /// length of array is always extraInfoLength. /// Can be 'null' if extra info is not needed. /// /// </param> /// <throws> OneWireIOException </throws> /// <throws> OneWireException </throws> public override void readScratchpad(byte[] readBuf, int offset, int len, byte[] extraInfo) { // select the device if (!ib.adapter.select(ib.address)) { forceVerify(); throw new OneWireIOException("Device select failed"); } // build block byte[] raw_buf = new byte[extraInfoLength + pageLength + 3]; raw_buf[0] = READ_SCRATCHPAD_COMMAND; Array.Copy(ffBlock, 0, raw_buf, 1, raw_buf.Length - 1); // send block, command + (extra) + page data + CRC ib.adapter.dataBlock(raw_buf, 0, raw_buf.Length); // get the starting offset to see when the crc will show up int addr = raw_buf[1]; addr = (addr | ((raw_buf[2] << 8) & 0xFF00)) & 0xFFFF; int num_crc = 35 - (addr & 0x001F) + extraInfoLength; // check crc of entire block if (CRC16.compute(raw_buf, 0, num_crc, 0) != 0x0000B001) { forceVerify(); throw new OneWireIOException("Invalid CRC16 read from device"); } // optionally extract the extra info if (extraInfo != null) { Array.Copy(raw_buf, 1, extraInfo, 0, extraInfoLength); } // extract the page data Array.Copy(raw_buf, extraInfoLength + 1, readBuf, 0, pageLength); }
/// <summary> Write a Universal Data Packet. See the method 'readPagePacket()' /// for a description of the packet structure. /// /// </summary> /// <param name="page"> page number to write packet to /// </param> /// <param name="writeBuf"> data byte array to write /// </param> /// <param name="offset"> offset into writeBuf where data to write is /// </param> /// <param name="len"> number of bytes to write /// /// </param> /// <throws> OneWireIOException </throws> /// <throws> OneWireException </throws> public virtual void writePagePacket(int page, byte[] writeBuf, int offset, int len) { // make sure length does not exceed max if (len > (PAGE_LENGTH - 3)) { throw new OneWireIOException("Length of packet requested exceeds page size"); } // construct the packet to write byte[] raw_buf = new byte[len + 3]; raw_buf[0] = (byte)len; Array.Copy(writeBuf, offset, raw_buf, 1, len); int crc = CRC16.compute(raw_buf, 0, len + 1, page); raw_buf[len + 1] = (byte)(~crc & 0xFF); raw_buf[len + 2] = (byte)((SupportClass.URShift((~crc & 0xFFFF), 8)) & 0xFF); // write the packet, return result write(page * PAGE_LENGTH, raw_buf, 0, len + 3); }
/// <summary> Read a complete memory page with CRC verification provided by the /// device with extra information. Not supported by all devices. /// If not extra information available then just call with extraLength=0. /// /// </summary> /// <param name="page"> page number to read /// </param> /// <param name="readContinue"> if 'true' then device read is continued without /// re-selecting. This can only be used if the new /// readPagePacket() continious where the last one /// stopped and it is inside a /// 'beginExclusive/endExclusive' block. /// </param> /// <param name="readBuf"> byte array to put data read. Must have at least /// 'getMaxPacketDataLength()' elements. /// </param> /// <param name="offset"> offset into readBuf to place data /// </param> /// <param name="extraInfo"> byte array to put extra info read into /// </param> /// <param name="extraLength"> length of extra information /// /// </param> /// <throws> OneWireIOException </throws> /// <throws> OneWireException </throws> protected internal virtual void readPageCRC(int page, bool readContinue, byte[] readBuf, int offset, byte[] extraInfo, int extraLength) { int last_crc = 0; byte[] raw_buf; // only needs to be implemented if supported by hardware if (!pageAutoCRC) { throw new OneWireException("Read page with CRC not supported in this memory bank"); } // attempt to put device at max desired speed if (!readContinue) { sp.checkSpeed(); } // check if read exceeds memory if (page > numberPages) { throw new OneWireException("Read exceeds memory bank end"); } // see if need to access the device if (!readContinue || !readContinuePossible) { // select the device if (!ib.adapter.select(ib.address)) { sp.forceVerify(); throw new OneWireIOException("Device select failed"); } // build start reading memory block raw_buf = new byte[3]; raw_buf[0] = READ_PAGE_WITH_CRC; int addr = page * pageLength + startPhysicalAddress; raw_buf[1] = (byte)(addr & 0xFF); raw_buf[2] = (byte)((SupportClass.URShift((addr & 0xFFFF), 8)) & 0xFF); // perform CRC16 on first part last_crc = CRC16.compute(raw_buf, 0, raw_buf.Length, last_crc); // do the first block for command, TA1, TA2 ib.adapter.dataBlock(raw_buf, 0, 3); } // pre-fill with 0xFF raw_buf = new byte[pageLength + extraLength + 2 + numVerifyBytes]; Array.Copy(ffBlock, 0, raw_buf, 0, raw_buf.Length); // send block to read data + extra info? + crc ib.adapter.dataBlock(raw_buf, 0, raw_buf.Length); // check the CRC if (CRC16.compute(raw_buf, 0, raw_buf.Length - numVerifyBytes, last_crc) != 0x0000B001) { sp.forceVerify(); throw new OneWireIOException("Invalid CRC16 read from device"); } // extract the page data Array.Copy(raw_buf, 0, readBuf, offset, pageLength); // optional extract the extra info if (extraInfo != null) { Array.Copy(raw_buf, pageLength, extraInfo, 0, extraLength); } }
/// <summary> Read a complete memory page with CRC verification provided by the /// device with extra information. Not supported by all devices. /// If not extra information available then just call with extraLength=0. /// /// </summary> /// <param name="page"> page number to read /// </param> /// <param name="readContinue"> if 'true' then device read is continued without /// re-selecting. This can only be used if the new /// readPagePacket() continious where the last one /// stopped and it is inside a /// 'beginExclusive/endExclusive' block. /// </param> /// <param name="readBuf"> byte array to put data read. Must have at least /// 'getMaxPacketDataLength()' elements. /// </param> /// <param name="offset"> offset into readBuf to place data /// </param> /// <param name="extraInfo"> byte array to put extra info read into /// </param> /// <param name="extraLength"> length of extra information /// /// </param> /// <throws> OneWireIOException </throws> /// <throws> OneWireException </throws> protected internal override void readPageCRC(int page, bool readContinue, byte[] readBuf, int offset, byte[] extraInfo, int extraLength) { int last_crc = 0; byte[] raw_buf; byte temp; // only needs to be implemented if supported by hardware if (!pageAutoCRC) { throw new OneWireException("Read page with CRC not supported in this memory bank"); } // attempt to put device at max desired speed if (!readContinue) { sp.checkSpeed(); } // check if read exceeds memory if (page > numberPages) { throw new OneWireException("Read exceeds memory bank end"); } // see if need to access the device if (!readContinue || !readContinuePossible) { // select the device if (!ib.adapter.select(ib.address)) { sp.forceVerify(); throw new OneWireIOException("Device select failed"); } // build start reading memory block raw_buf = new byte[11]; raw_buf[0] = READ_MEMORY_CRC_PW_COMMAND; int addr = page * pageLength + startPhysicalAddress; raw_buf[1] = (byte)(addr & 0xFF); raw_buf[2] = (byte)((SupportClass.URShift((addr & 0xFFFF), 8)) & 0xFF); if (ibPass.ContainerReadWritePasswordSet) { ibPass.getContainerReadWritePassword(raw_buf, 3); } else { ibPass.getContainerReadOnlyPassword(raw_buf, 3); } // perform CRC16 on first part (without the password) last_crc = CRC16.compute(raw_buf, 0, 3, last_crc); // do the first block for command, TA1, TA2, and password if (enablePower) { ib.adapter.dataBlock(raw_buf, 0, 10); ib.adapter.startPowerDelivery(DSPortAdapter.CONDITION_AFTER_BYTE); ib.adapter.putByte(raw_buf[10]); } else { ib.adapter.dataBlock(raw_buf, 0, 11); } } else { if (enablePower) { ib.adapter.startPowerDelivery(DSPortAdapter.CONDITION_AFTER_BYTE); temp = (byte)ib.adapter.Byte; } } if (enablePower) { msWait(3); ib.adapter.setPowerNormal(); } // pre-fill with 0xFF raw_buf = new byte[pageLength + extraLength + 2 + numVerifyBytes]; Array.Copy(ffBlock, 0, raw_buf, 0, raw_buf.Length); // send block to read data + extra info? + crc if (enablePower) { ib.adapter.dataBlock(raw_buf, 0, (raw_buf.Length - 1)); last_crc = CRC16.compute(raw_buf, 0, raw_buf.Length - numVerifyBytes - 2, last_crc); if ((last_crc & 0x0FF) != ((~raw_buf[raw_buf.Length - 2]) & 0x0FF)) { sp.forceVerify(); throw new OneWireIOException("Invalid CRC16 read from device. Password may be incorrect."); } } else { ib.adapter.dataBlock(raw_buf, 0, raw_buf.Length); // check the CRC if (CRC16.compute(raw_buf, 0, raw_buf.Length - numVerifyBytes, last_crc) != 0x0000B001) { sp.forceVerify(); throw new OneWireIOException("Invalid CRC16 read from device. Password may be incorrect."); } } // extract the page data Array.Copy(raw_buf, 0, readBuf, offset, pageLength); // optional extract the extra info if (extraInfo != null) { Array.Copy(raw_buf, pageLength, extraInfo, 0, extraLength); } }
/// <summary> Write memory in the current bank. It is recommended that /// when writing data that some structure in the data is created /// to provide error free reading back with read(). Or the /// method 'writePagePacket()' could be used which automatically /// wraps the data in a length and CRC. /// /// When using on Write-Once devices care must be taken to write into /// into empty space. If write() is used to write over an unlocked /// page on a Write-Once device it will fail. If write verification /// is turned off with the method 'setWriteVerification(false)' then /// the result will be an 'AND' of the existing data and the new data. /// /// </summary> /// <param name="startAddr"> starting address /// </param> /// <param name="writeBuf"> byte array containing data to write /// </param> /// <param name="offset"> offset into writeBuf to get data /// </param> /// <param name="len"> length in bytes to write /// /// </param> /// <throws> OneWireIOException </throws> /// <throws> OneWireException </throws> public virtual void write(int startAddr, byte[] writeBuf, int offset, int len) { byte[] raw_buf = new byte[7]; int cnt = 0, start_addr, addr, end_addr, lastcrc; // return if nothing to do if (len == 0) { return; } // attempt to put device at max desired speed checkSpeed(); // select the device if (!ib.adapter.select(ib.address)) { forceVerify(); throw new OneWireIOException("Device select failed"); } // build packet raw_buf[cnt++] = WRITE_MEMORY_COMMAND; start_addr = startAddr + startPhysicalAddress; end_addr = start_addr + len; raw_buf[cnt++] = (byte)(start_addr & 0xFF); raw_buf[cnt++] = (byte)((SupportClass.URShift((start_addr & 0xFFFF), 8)) & 0xFF); // loop for each byte to write for (addr = start_addr; addr < end_addr; addr++) { // add the byte to write to buffer raw_buf[cnt++] = writeBuf[offset + addr - start_addr]; // initialize crc16 lastcrc = CRC16.compute(raw_buf, 0, cnt, (addr == start_addr)?0:addr); // add the read crc and echo byte to block Array.Copy(ffBlock, 0, raw_buf, cnt, 3); // perform the block ib.adapter.dataBlock(raw_buf, 0, cnt + 3); // check the CRC if (CRC16.compute(raw_buf, cnt, 2, lastcrc) != 0x0000B001) { forceVerify(); throw new OneWireIOException("Invalid CRC16 read from device"); } // check echo if (raw_buf[cnt + 2] != writeBuf[offset + addr - start_addr]) { forceVerify(); throw new OneWireIOException("Write byte echo was invalid"); } // reset the buffer and loop cnt = 0; } }
//-------- //-------- ScratchPad methods //-------- /// <summary> Write to the scratchpad page of memory a NVRAM device. /// /// </summary> /// <param name="startAddr"> starting address /// </param> /// <param name="writeBuf"> byte array containing data to write /// </param> /// <param name="offset"> offset into readBuf to place data /// </param> /// <param name="len"> length in bytes to write /// /// </param> /// <throws> OneWireIOException </throws> /// <throws> OneWireException </throws> public override void writeScratchpad(int startAddr, byte[] writeBuf, int offset, int len) { bool calcCRC = false; byte[] raw_buf = new byte[37]; // select the device if (!ib.adapter.select(ib.address)) { forceVerify(); throw new OneWireIOException("Device select failed"); } // erase the scratchpad raw_buf[0] = ERASE_SCRATCHPAD_COMMAND; Array.Copy(ffBlock, 0, raw_buf, 1, 8); ib.adapter.dataBlock(raw_buf, 0, 9); if (((byte)(raw_buf[8] & 0x0F0) != (byte)SupportClass.Identity(0xA0)) && ((byte)(raw_buf[8] & 0x0F0) != (byte)0x50)) { forceVerify(); throw new OneWireIOException("Erase scratchpad complete not found"); } // select the device if (!ib.adapter.select(ib.address)) { forceVerify(); throw new OneWireIOException("Device select failed"); } // build block to send raw_buf[0] = WRITE_SCRATCHPAD_COMMAND; raw_buf[1] = (byte)(startAddr & 0xFF); raw_buf[2] = (byte)((SupportClass.URShift((startAddr & 0xFFFF), 8)) & 0xFF); Array.Copy(writeBuf, offset, raw_buf, 3, len); // check if full page (can utilize CRC) if (((startAddr + len) % pageLength) == 0) { Array.Copy(ffBlock, 0, raw_buf, len + 3, 2); calcCRC = true; } // send block, return result ib.adapter.dataBlock(raw_buf, 0, len + 3 + ((calcCRC)?2:0)); // check crc if (calcCRC) { if (CRC16.compute(raw_buf, 0, len + 5, 0) != 0x0000B001) { forceVerify(); throw new OneWireIOException("Invalid CRC16 read from device"); } } }