📄 onewirecontainer12.java
字号:
* <code>readInitially</code> is <code>false</code> (and you only * have one channel communication), 8 bits will be written to channel * A and then 8 bits will be read from channel A. * * @param CRCMode The 2406/7 supports 4 CRC generation modes for error detection * when performing channel access. This argument should have one * of the following values: * <pre><code> * CRC_DISABLE Never generate a CRC * CRC_EVERY_BYTE Generate a CRC after every byte transmission. * CRC_EVERY_8_BYTES Generate a CRC after every 8 bytes. * CRC_EVERY_32_BYTES Generate a CRC after every 32 bytes. * </code></pre> * Invalid values will be masked to valid values. The CRC is 16 bits, * and does not get passed back with the output. This method returns * <code>null</code> on a CRC failure. * * @param channelMode The 2406/7 supports 3 modes of channel communication. This * argument should take one of the following values: * <pre><code> * CHANNEL_A_ONLY Only communicate with PIO A * CHANNEL_B_ONLY Only communicate with PIO B * CHANNEL_BOTH Communicate with both PIO's * </code></pre> * If <code>CHANNEL_BOTH</code> is selected, data is written and read * from the input buffer to the two channels. * See the datasheet for a description of operation in this * mode. If communicating with both channels, it is up to the * caller to format the data correctly in the input buffer * so the correct channel gets the correct data. Similarly, * any return data must be parsed by the user. * * @param clearActivity <code>true</code> to reset the activity latch * * @param interleave The value for the Interleave Control bit. * If <code>true</code>, operates in synchronous mode. * If <code>false</code>, operates in asynchronous mode. * See the datasheet for a discussion of asynchronous and * synchronous mode. This argument only matters if communicating * with both channels. * * @return If any bytes were read, this returns a byte array of data * read from the channel access. If no bytes were read, it * will return the input buffer that was to be written. * * @throws OneWireIOException on a 1-Wire communication error such as * reading an incorrect CRC from a 1-Wire device. 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'. * @throws OneWireException on a communication or setup error with the 1-Wire * adapter * * @see #CHANNEL_A_ONLY * @see #CHANNEL_B_ONLY * @see #CHANNEL_BOTH * @see #CRC_DISABLE * @see #CRC_EVERY_BYTE * @see #CRC_EVERY_8_BYTES * @see #CRC_EVERY_32_BYTES */ public byte[] channelAccess (byte[] inbuffer, boolean toggleRW, boolean readInitially, int CRCMode, int channelMode, boolean clearActivity, boolean interleave) throws OneWireException, OneWireIOException { CRCMode = CRCMode & 0x03; //MASK THIS TO ACCEPTABLE VALUE channelMode = channelMode & 0x0c; //MASK THIS TO ACCEPTABLE VALUE if (channelMode == 0) channelMode = 0x04; //CHANNELMODE CANNOT BE 0 if (interleave && (channelMode != CHANNEL_BOTH)) //CANNOT INTERLEAVE WITH ONLY 1 CHANNEL interleave = false; if (doSpeedEnable) doSpeed(); if (adapter.select(address)) { int crc16; int i; //now figure out how many bytes my output buffer needs to be int inlength = inbuffer.length; if (toggleRW) inlength = (inlength << 1); //= inlength * 2 switch (CRCMode) { case CRC_EVERY_BYTE : //we need to allow for 2 CRC bytes for every byte of the length inlength = inlength * 3; //length + 2*length break; case CRC_EVERY_8_BYTES : //we need to allow for 2 CRC bytes for every 8 bytes of length inlength = inlength + ((inlength >> 3) << 1); //(length DIV 8) * 2 break; case CRC_EVERY_32_BYTES : //we need to allow for 2 CRC bytes for every 32 bytes of length inlength = inlength + ((inlength >> 5) << 1); //(length DIV 32) * 2 break; } byte[] outputbuffer = new byte [inlength + 3 + 1]; //3 control bytes + 1 information byte outputbuffer [0] = CHANNEL_ACCESS_COMMAND; crc16 = CRC16.compute(CHANNEL_ACCESS_COMMAND & 0x0FF); // send the control bytes outputbuffer [1] = ( byte ) (CRCMode | channelMode | (clearActivity ? 0x80 : 0x00) | (interleave ? 0x10 : 0x00) | (toggleRW ? 0x20 : 0x00) | (readInitially ? 0x40 : 0x00)); outputbuffer [2] = ( byte ) 0xFF; crc16 = CRC16.compute(outputbuffer, 1, 2, crc16); for (i = 3; i < outputbuffer.length; i++) outputbuffer [i] = ( byte ) 0xff; //now for the hard part: putting the right outputbuffer into the array //first lets see if we can skip this stage, ie on just a read /* At this point we have 16 options: Initial Toggle CRC Description 0 write off 0 Only write these bytes, CRC disabled 1 write off 1 Write these bytes, CRC for every byte 2 write off 8 Write these bytes, CRC for every 8 bytes 3 write off 32 Write these bytes, CRC for every 32 bytes 4 write on 0 Write a byte, read a byte, no CRC 5 write on 1 Write a byte, CRC, read a byte, CRC 6 write on 8 Write a byte, read a byte X 4 then a CRC 7 write on 32 Write a byte, read a byte X 16 then a CRC 8 read off 0 Read this many bytes, CRC disabled 9 read off 1 Read this many bytes, CRC for every byte a read off 8 Read this many bytes, CRC for every 8 bytes b read off 32 Read this many bytes, CRC for every 32 bytes c read on 0 Read a byte, write a byte, no CRC d read on 1 Read a byte, CRC, write a byte, CRC e read on 8 Read a byte, write a byte X 4 then a CRC f read on 32 Read a byte, write a byte X 16 then a CRC Options 0-3 require that we space the input buffer for the CRCs. Options 8-b require no extra work, since we have already loaded the buffer with FF's for reads. Options 4 and c require that we interleave the write bytes and the read FF's Options 5 and d require that we interleace write byte, CRC space, read byte, CRC space Other options are really messy ...Brain */ int j = 4; //outputbuffer 0-2 is command bytes, outputbuffer[3] is return info int option = outputbuffer [1] & 0x63; //get the bits out we want for toggle, initial, and CRC option = ((option >> 3) | option) & 0x0f; //now lets make it a number 0-15 /*switch (option) { case 0 : case 1 : case 2 : case 3 : for (i=0;i<inbuffer.length;i++) { outputbuffer[j] = inbuffer[i]; j = j + fixJ(i+1,option); } break; case 4 : case 5 : case 6 : case 7 : for (i=0;i<inbuffer.length;i++) { outputbuffer[j] = inbuffer[i]; j = j + fixJ((i*2)+1,option); //then we plug in a read space j = j + fixJ((i*2)+2,option); } break; case 8 : case 9 : case 0x0a : case 0x0b : break; //nothing needs to be done case 0x0c : case 0x0d : case 0x0e : case 0x0f : for (i=0;i<inbuffer.length;i++) { //first we plug in a read space j = j + fixJ((i*2)+1,option); outputbuffer[j] = inbuffer[i]; j = j + fixJ((i*2)+2,option); } break; }*/ /* this next section of code replaces the previous section to reduce redundant code. here we are formatting the output buffer so it has FF's in the right places for reading the CRC's and reading the data from the channels. the previous code is left because it makes a little more sense in that form. at least i think so. ...Pinky */ if ((option < 8) || (option > 0x0b)) //if this is not a read-only (which we need do nothing for) { for (i = 0; i < inbuffer.length; i++) { if (option > 0x0b) //then we are reading first j = j + fixJ((i * 2) + 1, option); // leave a space for a read, and the CRC if need be outputbuffer [j] = inbuffer [i]; //write this data if (option < 0x04) //if this is only a write j = j + fixJ(i + 1, option); // leave a space for CRC if needed, else just increment else //else we are toggling { if (option < 0x08) //this is a write-first toggle j = j + fixJ((i * 2) + 1, option); // so leave a space for a read j = j + fixJ((i * 2) + 2, option); //now leave a space for the CRC } } } // now our output buffer should be set correctly // send the block Pinky! adapter.dataBlock(outputbuffer, 0, outputbuffer.length); // calculate the CRC16 within the resulting buffer for integrity //start at offset 3 for the information byte crc16 = CRC16.compute(outputbuffer [3], crc16); j = 0; //j will be how many bytes we are into the buffer - CRC bytes read int k = 0; //index into the return buffer boolean fresh = false; //whether or not we need to reinitialize the CRC calculation byte[] returnbuffer = new byte [inbuffer.length]; for (i = 4; i < outputbuffer.length; i++) { if (CRCMode != CRC_DISABLE) { if (fresh) { crc16 = CRC16.compute(outputbuffer [i]); fresh = false; } else crc16 = CRC16.compute(outputbuffer [i], crc16); } if ((!toggleRW && readInitially) || (toggleRW && readInitially && ((j & 0x01) == 0x00)) || (toggleRW &&!readInitially && ((j & 0x01) == 0x01))) { returnbuffer [k] = outputbuffer [i]; k++; } j++; if ((fixJ(j, option) > 1) && (CRCMode != CRC_DISABLE)) //means that we should look for a CRC { crc16 = CRC16.compute(outputbuffer, i + 1, 2, crc16); i += 2; if (crc16 != 0xb001) throw new OneWireIOException(address, "Invalid CRC"); fresh = true; } } //now that we got the right bytes out of the array return returnbuffer; } // device must not have been present throw new OneWireIOException(address, "OneWireContainer12-device not present"); } //-------- //-------- Private //-------- /* * This method returns how much we should increment the index variable into * our output buffer. should be called after every setting of a value. * * @param current_index current index into the channel access array * @param option_mask contains data on CRC generation * * @return amount to increment the index variable */ private int fixJ (int current_index, int option_mask) { //assume that current_index started at 0, but this function is never called at 0 switch (option_mask & 0x03) { case 0x00 : return 1; //no crc case 0x01 : return 3; //2-byte CRC after every byte default : //must be 0x02 (after 8 bytes) or 0x03 (after 32 bytes) if ((current_index & (8 + (24 * (option_mask & 0x01)) - 1)) == 0) return 3; /* OK let me explain that last piece of code: The only return values are going to be 1 and 3, 1 for a normal increment and 3 if we want to leave space to recieve a CRC. So the mask gets the bits out that are concerned with the CRC. When its 0 it means that the CRC is disabled, so the next location into our destination array we need to copy into is just the next available location. When it is 1, it means we will recieve a CRC after each transmission, so we should leave a 2 byte space for it (thus increament by 3). When it is 2, it means that after every 8 bytes we want to recieve a CRC byte pair. When it is a 3, it means that every 32 bytes we want the CRC pair. So what we want to check is if the current_index is divisible by 8 or 32 (we do not call this method with current_index==0). Since 8 and 32 are powers of 2 we do it with the '&' operator and 7 or 31 as the other value (2^n - 1). The (8+(24 * option_mask&0x01)) bit just returns me 8 or 32. */ } return 1; }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -