Scott Roy / OneWire
Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers Transport.cpp Source File

Transport.cpp

00001 #include "Transport.h"
00002 
00003 /* This table helps with the compution of the CRC8 used in OneWire ROM
00004  *
00005  * The theory is that it precomputes all possible states that an eight bit shift register
00006  * can go to from a certain state when given a certain byte. Computationally and array
00007  * lookup should be considerably faster than simulating the shift register a bit at a time.
00008  *
00009  * Table was sourced from maxim document AN937 that describes the standard.
00010  */
00011 const unsigned char crc8table[256] = {
00012     0, 94, 188, 226, 97, 63, 221, 131, 194, 156, 126, 32, 163, 253, 31, 65,
00013     157, 195, 33, 127, 252, 162, 64, 30, 95, 1, 227, 189, 62, 96, 130, 220,
00014     35, 125, 159, 193, 66, 28, 254, 160, 225, 191, 93, 3, 128, 222, 60, 98,
00015     190, 224, 2, 92, 223, 129, 99, 61, 124, 34, 192, 158, 29, 67, 161, 255,
00016     70, 24, 250, 164, 39, 121, 155, 197, 132, 218, 56, 102, 229, 187, 89, 7,
00017     219, 133, 103, 57, 186, 228, 6, 88, 25, 71, 165, 251, 120, 38, 196, 154,
00018     101, 59, 217, 135, 4, 90, 184, 230, 167, 249, 27, 69, 198, 152, 122, 36,
00019     248, 166, 68, 26, 153, 199, 37, 123, 58, 100, 134, 216, 91, 5, 231, 185,
00020     140, 210, 48, 110, 237, 179, 81, 15, 78, 16, 242, 172, 47, 113, 147, 205,
00021     17, 79, 173, 243, 112, 46, 204, 146, 211, 141, 111, 49, 178, 236, 14, 80,
00022     175, 241, 19, 77, 206, 144, 114, 44, 109, 51, 209, 143, 12, 82, 176, 238,
00023     50, 108, 142, 208, 83, 13, 239, 177, 240, 174, 76, 18, 145, 207, 45, 115,
00024     202, 148, 118, 40, 171, 245, 23, 73, 8, 86, 180, 234, 105, 55, 213, 139,
00025     87, 9, 235, 181, 54, 104, 138, 212, 149, 203, 41, 119, 244, 170, 72, 22,
00026     233, 183, 85, 11, 136, 214, 52, 106, 43, 117, 151, 201, 74, 20, 246, 168,
00027     116, 42, 200, 150, 21, 75, 169, 247, 182, 232, 10, 84, 215, 137, 107, 53};
00028     
00029 // read command
00030 
00031 void OWTransport::read(OneWire_Instruction * inst, OneWire_ROM * out){
00032     inst->network.code = READ_ROM;
00033     inst->network.inst = &OWTransport::_inst_readsetup;
00034     inst->network.args = out;
00035     *out = 0; // clear rom to a valid value (0 does pass CRC8 but is impossible to get as a device)
00036 }
00037 
00038 void OWTransport::_inst_readsetup(OneWire * which){
00039     // setup register
00040     ((TransportRead *)(which->registers))->read = 0;
00041     ((TransportRead *)(which->registers))->crc8 = 0;
00042     
00043     // setup command
00044     which->readhandle = &OWTransport::_inst_readhandler;
00045     which->execute.inst = &OWTransport::_inst_read;
00046     
00047     // execute command
00048     OWTransport::_inst_read(which);
00049 }
00050 
00051 void OWTransport::_inst_read(OneWire * which){
00052     if(((TransportRead *)(which->registers))->read < 64){
00053         which->op_read();
00054     }else{
00055         // check if crc8 check passed (remainder 0), failure is not recoverable
00056         if(((TransportRead *)(which->registers))->crc8) which->abort(CRC_ERROR);
00057         else which->endInstruction();
00058     }
00059 }
00060 
00061 void OWTransport::_inst_readhandler(OneWire * which, char bit){
00062     // store bit
00063     *((unsigned char *)(which->execute.args))|= bit<<(((TransportRead *)(which->registers))->read++%8);
00064     
00065     // every 8 bits (byte) compute CRC8 and move to next byte
00066     if(!(((TransportRead *)(which->registers))->read % 8)){
00067         ((TransportRead *)(which->registers))->crc8 = crc8table[((TransportRead *)(which->registers))->crc8 ^ (*((unsigned char *)(which->execute.args)))];
00068         which->execute.args = (void *)(((unsigned char *)(which->execute.args))+1);
00069     }
00070 }
00071 
00072 // search command
00073 
00074 void TransportSearchPersist::clear(){
00075     rom = 0;
00076     last = -1;
00077     done = false;
00078 }
00079 
00080 void OWTransport::search(OneWire_Instruction * inst, TransportSearchPersist * search){
00081     inst->network.code = SEARCH_ROM;
00082     inst->network.inst = &OWTransport::_inst_searchsetup;
00083     inst->network.args = search;
00084 }
00085 
00086 void OWTransport::_inst_searchsetup(OneWire * which){
00087     if(((TransportSearchPersist *)(which->execute.args))->done){
00088         // the search had completed, there is nothing more to do
00089         which->abort(SUCCESS);
00090         return;
00091     }
00092 
00093     // setup register
00094     ((TransportSearch *)(which->registers))->read = 0;
00095     ((TransportSearch *)(which->registers))->crc8 = 0;
00096     ((TransportSearch *)(which->registers))->marker = -1;
00097     ((TransportSearch *)(which->registers))->bit = 0;
00098     
00099     // setup command
00100     which->readhandle = &OWTransport::_inst_searchhandler;
00101     which->execute.inst = &OWTransport::_inst_search;
00102     
00103     // execute command
00104     OWTransport::_inst_search(which);
00105 }
00106 
00107 void OWTransport::_inst_search(OneWire * which){
00108     if(((TransportSearch *)(which->registers))->read < 64){
00109         // state machine, read bit 1 -> read bit 2 and make choice -> send choice -> repeat up to 64 times
00110         if(((TransportSearch *)(which->registers))->bit>>3 & 0x01){
00111             // send choosen bit and advance
00112             if(((unsigned char *)&(((TransportSearchPersist *)(which->execute.args))->rom))[((TransportSearch *)(which->registers))->read/8]>>(((TransportSearch *)(which->registers))->read%8) &0x01){
00113                 which->op_send1();
00114             }else{
00115                 which->op_send0();
00116             }
00117             // compute crc8
00118             if(((TransportSearch *)(which->registers))->read % 8 == 7){
00119                 ((TransportSearch *)(which->registers))->crc8 = crc8table[((TransportSearch *)(which->registers))->crc8 ^ ((unsigned char *)&(((TransportSearchPersist *)(which->execute.args))->rom))[((TransportSearch *)(which->registers))->read/8]];
00120             }
00121             
00122             // prepare for next cycle (reset state machine)
00123             ((TransportSearch *)(which->registers))->read+= 1;
00124             ((TransportSearch *)(which->registers))->bit = 0;
00125         }else{
00126             // read bit 1 and 2 (read function advances state machine)
00127             which->op_read();
00128         }
00129     }else{
00130         ((TransportSearchPersist *)(which->execute.args))->last = ((TransportSearch *)(which->registers))->marker;
00131         if(((TransportSearchPersist *)(which->execute.args))->last == -1) ((TransportSearchPersist *)(which->execute.args))->done = true;
00132         
00133         // check if crc8 check passed (remainder 0), failure is not recoverable
00134         if(((TransportSearch *)(which->registers))->crc8) which->abort(CRC_ERROR);
00135         else which->endInstruction();
00136     }
00137 }
00138 
00139 void OWTransport::_inst_searchhandler(OneWire * which, char bit){
00140     // store bit
00141     ((TransportSearch *)(which->registers))->bit|= bit<<(((TransportSearch *)(which->registers))->bit>>2 & 0x01);
00142     
00143     // advance state
00144     if(((TransportSearch *)(which->registers))->bit>>2 & 0x01){
00145         if((((TransportSearch *)(which->registers))->bit & 0x03) == 3){
00146             // all slaves were removed or broke?
00147             ((TransportSearchPersist *)(which->execute.args))->done = true; // any search results that were obtained could be invalid so end search
00148             which->abort(NO_PRESENCE);
00149             return;
00150         }else if((((TransportSearch *)(which->registers))->bit & 0x03) == 0){
00151             // a conflict bit
00152             if(((TransportSearch *)(which->registers))->read == ((TransportSearchPersist *)(which->execute.args))->last){
00153                 // already searched 0 bit path, this time send a 1
00154                 ((unsigned char *)&(((TransportSearchPersist *)(which->execute.args))->rom))[((TransportSearch *)(which->registers))->read/8]|= 0x01<<(((TransportSearch *)(which->registers))->read%8);
00155             }else if(((TransportSearch *)(which->registers))->read > ((TransportSearchPersist *)(which->execute.args))->last){
00156                 // a new branch to search
00157                 ((unsigned char *)&(((TransportSearchPersist *)(which->execute.args))->rom))[((TransportSearch *)(which->registers))->read/8]&= ~(0x01<<(((TransportSearch *)(which->registers))->read%8));
00158                 ((TransportSearch *)(which->registers))->marker = ((TransportSearch *)(which->registers))->read;
00159             }else if( !(((unsigned char *)&(((TransportSearchPersist *)(which->execute.args))->rom))[((TransportSearch *)(which->registers))->read/8]>>(((TransportSearch *)(which->registers))->read%8) &0x01) ){
00160                 // a previous branch decision
00161                 ((TransportSearch *)(which->registers))->marker = ((TransportSearch *)(which->registers))->read;
00162             }
00163         }else{
00164             // no conflict so write the bit
00165             if(((TransportSearch *)(which->registers))->bit & 0x01){
00166                 ((unsigned char *)&(((TransportSearchPersist *)(which->execute.args))->rom))[((TransportSearch *)(which->registers))->read/8]|= 0x01<<(((TransportSearch *)(which->registers))->read%8);
00167             }else{
00168                 ((unsigned char *)&(((TransportSearchPersist *)(which->execute.args))->rom))[((TransportSearch *)(which->registers))->read/8]&= ~(0x01<<(((TransportSearch *)(which->registers))->read%8));
00169             }
00170         }
00171         
00172         // tell next call to send the choice
00173         ((TransportSearch *)(which->registers))->bit|= 0x08;
00174     }else{
00175         // we need to read another bit
00176         ((TransportSearch *)(which->registers))->bit|= 0x04;
00177     }
00178 }