//-------------------------------------------------------------------------- // Send 1 bit of communication to the 1-Wire Net and verify that the // bit read from the 1-Wire Net is the same (write operation). // Delay delay msec and return to normal // static GOOD_OR_BAD DS1WM_PowerBit(const BYTE byte, BYTE * resp, const UINT delay, const struct parsedname *pn) { GOOD_OR_BAD ret = gbBAD ; // default struct connection_in * in = pn->selected_connection ; uint8_t control_register ; // Set power, bitmode on control_register = DS1WM_control(in) ; UT_setbit( &control_register,e_ds1wm_stp_sply, 1 ) ; UT_setbit( &control_register,e_ds1wm_bit_ctl, 1 ) ; in->master.ds1wm.byte_mode = 0 ; DS1WM_control(in) = control_register ; if ( GOOD( DS1WM_sendback_byte( &byte, resp, in ) ) && GOOD( DS1WM_wait_for_write(in) ) ) { UT_delay(delay); ret = gbGOOD ; } // Set power, bitmode off control_register = DS1WM_control(in) ; UT_setbit( &control_register,e_ds1wm_stp_sply, 0 ) ; UT_setbit( &control_register,e_ds1wm_bit_ctl, 0 ) ; in->master.ds1wm.byte_mode = 1 ; DS1WM_control(in) = control_register ; return ret ; }
//-------------------------------------------------------------------------- // Reset all of the devices on the 1-Wire Net and return the result. // // This routine will not function correctly on some // Alarm reset types of the DS1994/DS1427/DS2404 with // Rev 1,2, and 3 of the DS2480/DS2480B. static RESET_TYPE K1WM_reset(const struct parsedname * pn) { LEVEL_DEBUG("[%s] BUS reset", __FUNCTION__); struct connection_in * in = pn->selected_connection ; if ( in->changed_bus_settings != 0) { in->changed_bus_settings = 0 ; K1WM_setup(in); // reset paramters } // select channel K1WM_select_channel(in, in->master.ds1wm.active_channel); // read interrupt register to clear all bits (void) DS1WM_interrupt(in); UT_setbit( &DS1WM_command(in), e_ds1wm_1wr, 1 ) ; switch( K1WM_wait_for_reset(in) ) { case BUS_RESET_SHORT: return BUS_RESET_SHORT ; case BUS_RESET_OK: return BUS_RESET_OK ; default: return K1WM_wait_for_reset(in) ; } }
static void SetupDiscrepancy(const struct device_search *ds, BYTE * discrepancy) { int i; /** Play LastDescrepancy games with bitstream */ memcpy(discrepancy, ds->sn, SERIAL_NUMBER_SIZE); /* set buffer to zeros */ if (ds->LastDiscrepancy > -1) { UT_setbit(discrepancy, ds->LastDiscrepancy, 1); } /* This could be more efficiently done than bit-setting, but probably wouldn't make a difference */ for (i = ds->LastDiscrepancy + 1; i < 64; i++) { UT_setbit(discrepancy, i, 0); } }
static ZERO_OR_ERROR FS_w_por(struct one_wire_query *owq) { struct parsedname *pn = PN(owq); BYTE data[6]; RETURN_ERROR_IF_BAD( OW_r_reg(data, pn) ); UT_setbit(&data[5], 3, OWQ_Y(owq)); return GB_to_Z_OR_E( OW_w_control(data[5], pn) ) ; }
// set control pins and frequency for defauts and global settings static GOOD_OR_BAD K1WM_setup( struct connection_in * in ) { uint8_t control_register = DS1WM_control(in) ; LEVEL_DEBUG("[%s] control_register before setup: 0x%x", __FUNCTION__, control_register); // Set to channel K1WM_channel(in) = in->master.ds1wm.active_channel ; // set some defaults: UT_setbit( &control_register, e_ds1wm_ppm, in->master.ds1wm.presence_mask ) ; // pulse presence masked UT_setbit( &control_register, e_ds1wm_en_fow, 0 ) ; // no bit banging UT_setbit( &control_register, e_ds1wm_stpen, 0 ) ; // strong pullup not supported in K1WM UT_setbit( &control_register, e_ds1wm_stp_sply, 0 ) ; // not in strong pullup state, too in->master.ds1wm.byte_mode = 1 ; // default UT_setbit( &control_register, e_ds1wm_bit_ctl, 0 ) ; // byte mode UT_setbit( &control_register, e_ds1wm_od, in->overdrive ) ; // not overdrive UT_setbit( &control_register, e_ds1wm_llm, in->master.ds1wm.longline ) ; // set long line flag DS1WM_control(in) = control_register ; LEVEL_DEBUG("[%s] control_register after setup: 0x%x", __FUNCTION__, DS1WM_control(in)); if ( DS1WM_control(in) != control_register ) { return gbBAD ; } return gbGOOD ; }
// set control pins and frequency for defauts and global settings static GOOD_OR_BAD DS1WM_setup( struct connection_in * in ) { uint8_t control_register = DS1WM_control(in) ; DS1WM_clock(in) = 0x00 ; // off (causes reset?) // set some defaults: UT_setbit( &control_register, e_ds1wm_ppm, in->master.ds1wm.presence_mask ) ; // pulse presence masked UT_setbit( &control_register, e_ds1wm_en_fow, 0 ) ; // no bit banging UT_setbit( &control_register, e_ds1wm_stpen, 1 ) ; // allow strong pullup UT_setbit( &control_register, e_ds1wm_stp_sply, 0 ) ; // not in strong pullup state, however in->master.ds1wm.byte_mode = 1 ; // default UT_setbit( &control_register, e_ds1wm_bit_ctl, 0 ) ; // byte mode UT_setbit( &control_register, e_ds1wm_od, in->overdrive ) ; // not overdrive UT_setbit( &control_register, e_ds1wm_llm, in->master.ds1wm.longline ) ; // set long line flag DS1WM_control(in) = control_register ; if ( DS1WM_control(in) != control_register ) { return gbBAD ; } DS1WM_clock(in) = DS1WM_freq( in->master.ds1wm.frequency ) ; return gbGOOD ; }
//-------------------------------------------------------------------------- // Send and receive 1 bit of communication to the 1-Wire // static GOOD_OR_BAD DS1WM_sendback_bits(const BYTE * databits, BYTE * respbits, const size_t len, const struct parsedname * pn) { struct connection_in * in = pn->selected_connection ; uint8_t control_register ; GOOD_OR_BAD ret ; // Set bitmode on control_register = DS1WM_control(in) ; UT_setbit( &control_register,e_ds1wm_bit_ctl, 1 ) ; in->master.ds1wm.byte_mode = 0 ; DS1WM_control(in) = control_register ; ret = DS1WM_sendback_data( databits, respbits, len, pn ) ; // Set bitmode off control_register = DS1WM_control(in) ; in->master.ds1wm.byte_mode = 1 ; UT_setbit( &control_register,e_ds1wm_bit_ctl, 0 ) ; DS1WM_control(in) = control_register ; return ret ; }
/* data[0] selection */ static ZERO_OR_ERROR FS_w_s_alarm(struct one_wire_query *owq) { BYTE data[3]; int i; UINT p; UINT U = OWQ_U(owq); for (i = 0, p = 1; i < 8; ++i, p *= 10) { UT_setbit(&data[1], i, ((int) (U / p) % 10) & 0x01); UT_setbit(&data[0], i, (((int) (U / p) % 10) & 0x02) >> 1); } data[2] = ((U / 100000000) % 10) & 0x03; return GB_to_Z_OR_E(OW_w_s_alarm(data, PN(owq))) ; }
// Handles: .n static ZERO_OR_ERROR FS_write_a_bit(struct one_wire_query *owq_bit) { struct one_wire_query * owq_byte = OWQ_create_separate( EXTENSION_BYTE, owq_bit ) ; ZERO_OR_ERROR z_or_e = -ENOENT ; if ( owq_byte != NO_ONE_WIRE_QUERY ) { if ( FS_read_local( owq_byte ) >= 0 ) { UT_setbit( (BYTE *) &OWQ_U( owq_byte ), OWQ_pn(owq_bit).extension, OWQ_Y(owq_bit) ) ; z_or_e = FS_write_owq( owq_byte ) ; } OWQ_destroy( owq_byte ) ; } return z_or_e ; }
//-------------------------------------------------------------------------- // Reset all of the devices on the 1-Wire Net and return the result. // // This routine will not function correctly on some // Alarm reset types of the DS1994/DS1427/DS2404 with // Rev 1,2, and 3 of the DS2480/DS2480B. static RESET_TYPE DS1WM_reset(const struct parsedname * pn) { struct connection_in * in = pn->selected_connection ; if ( in->changed_bus_settings != 0) { in->changed_bus_settings = 0 ; DS1WM_setup(in); // reset paramters } UT_setbit( &DS1WM_command(in), e_ds1wm_1wr, 1 ) ; switch( DS1WM_wait_for_reset(in) ) { case BUS_RESET_SHORT: return BUS_RESET_SHORT ; case BUS_RESET_OK: return BUS_RESET_OK ; default: return DS1WM_wait_for_reset(in) ; } }
/* search = normal and alarm */ static enum search_status K1WM_next_both(struct device_search *ds, const struct parsedname *pn) { LEVEL_DEBUG("[%s] BUS search", __FUNCTION__); int mismatched; BYTE sn[SERIAL_NUMBER_SIZE]; BYTE bitpairs[SERIAL_NUMBER_SIZE*2]; BYTE dummy ; struct connection_in * in = pn->selected_connection ; int i; LEVEL_DEBUG("[%s] ds->LastDevice == true ?", __FUNCTION__); if (ds->LastDevice) { LEVEL_DEBUG("[%s] ds->LastDevice == true -> search_done", __FUNCTION__); return search_done; } LEVEL_DEBUG("[%s] BUS_select failed ?", __FUNCTION__); if ( BAD( BUS_select(pn) ) ) { LEVEL_DEBUG("[%s] BUS_select failed -> search_error", __FUNCTION__); return search_error; } // Standard SEARCH ROM using SRA // need the reset done in BUS-select to set AnyDevices if ( in->AnyDevices == anydevices_no ) { LEVEL_DEBUG("[%s] in->AnyDevices == anydevices_no -> search_done", __FUNCTION__); ds->LastDevice = 1; return search_done; } // clear sn to satisfy static error checking (Coverity) memset( sn, 0, SERIAL_NUMBER_SIZE ) ; // build the command stream // call a function that may add the change mode command to the buff // check if correct mode // issue the search command // change back to command mode // search mode on // change back to data mode // set the temp Last Descrep to none mismatched = -1; // add the 16 bytes of the search memset(bitpairs, 0, SERIAL_NUMBER_SIZE*2); LEVEL_DEBUG("[%s] ds->LastDiscrepancy == %i", __FUNCTION__, ds->LastDiscrepancy); // set the bits in the added buffer for (i = 0; i < ds->LastDiscrepancy; i++) { // before last discrepancy UT_set2bit(bitpairs, i, UT_getbit(ds->sn, i) << 1); } // at last discrepancy if (ds->LastDiscrepancy > -1) { UT_set2bit(bitpairs, ds->LastDiscrepancy, 1 << 1); } // after last discrepancy so leave zeros // search ON // Send search rom or conditional search byte if ( BAD( K1WM_sendback_byte(&(ds->search), &dummy, in) ) ) { LEVEL_DEBUG("[%s] Sending SearchROM/SearchByte '0x%x' failed -> search_error", __FUNCTION__, ds->search); return search_error; } // Set search accelerator UT_setbit( &DS1WM_command(in), e_ds1wm_sra, 1 ) ; // send the packet // cannot use single-bit mode with search accerator // search OFF if ( BAD( K1WM_sendback_data(bitpairs, bitpairs, SERIAL_NUMBER_SIZE*2, pn) ) ) { LEVEL_DEBUG("[%s] Sending the packet (bitpairs) failed -> search_error", __FUNCTION__); return search_error; } // Turn off search accelerator UT_setbit( &DS1WM_command(in), e_ds1wm_sra, 0 ) ; // interpret the bit stream for (i = 0; i < SERIAL_NUMBER_BITS; i++) { // get the SerialNum bit UT_setbit(sn, i, UT_get2bit(bitpairs, i) >> 1); // check LastDiscrepancy if (UT_get2bit(bitpairs, i) == SEARCH_BIT_ON ) { mismatched = i; } } if ( sn[0]==0xFF && sn[1]==0xFF && sn[2]==0xFF && sn[3]==0xFF && sn[4]==0xFF && sn[5]==0xFF && sn[6]==0xFF && sn[7]==0xFF ) { // special case for no alarm present LEVEL_DEBUG("[%s] sn == 0xFFFFFFFFFFFFFFFF -> search_error", __FUNCTION__); return search_done ; } // CRC check if (CRC8(sn, SERIAL_NUMBER_SIZE) || (ds->LastDiscrepancy == SERIAL_NUMBER_BITS-1) || (sn[0] == 0)) { LEVEL_DEBUG("[%s] CRC check failed -> search_error", __FUNCTION__); return search_error; } // successful search // check for last one if ((mismatched == ds->LastDiscrepancy) || (mismatched == -1)) { ds->LastDevice = 1; } // copy the SerialNum to the buffer memcpy(ds->sn, sn, 8); // set the count ds->LastDiscrepancy = mismatched; LEVEL_DEBUG("SN found: " SNformat, SNvar(ds->sn)); return search_good; }
/* uses the "Triple" primative for faster search */ static enum search_status DS2482_next_both(struct device_search *ds, const struct parsedname *pn) { int search_direction = 0; /* initialization just to forestall incorrect compiler warning */ int bit_number; int last_zero = -1; FILE_DESCRIPTOR_OR_ERROR file_descriptor = pn->selected_connection->pown->file_descriptor; BYTE bits[3]; // initialize for search // if the last call was not the last one if (ds->LastDevice) { return search_done; } if ( BAD( BUS_select(pn) ) ) { return search_error ; } // need the reset done in BUS-select to set AnyDevices if ( pn->selected_connection->AnyDevices == anydevices_no ) { ds->LastDevice = 1; return search_done; } /* Make sure we're using the correct channel */ /* Appropriate search command */ if ( BAD(BUS_send_data(&(ds->search), 1, pn)) ) { return search_error; } // loop to do the search for (bit_number = 0; bit_number < 64; ++bit_number) { LEVEL_DEBUG("bit number %d", bit_number); /* Set the direction bit */ if (bit_number < ds->LastDiscrepancy) { search_direction = UT_getbit(ds->sn, bit_number); } else { search_direction = (bit_number == ds->LastDiscrepancy) ? 1 : 0; } /* Appropriate search command */ if ( BAD( DS2482_triple(bits, search_direction, file_descriptor) ) ) { return search_error; } if (bits[0] || bits[1] || bits[2]) { if (bits[0] && bits[1]) { /* 1,1 */ /* No devices respond */ ds->LastDevice = 1; return search_done; } } else { /* 0,0,0 */ last_zero = bit_number; } UT_setbit(ds->sn, bit_number, bits[2]); } // loop until through serial number bits if (CRC8(ds->sn, SERIAL_NUMBER_SIZE) || (bit_number < 64) || (ds->sn[0] == 0)) { /* Unsuccessful search or error -- possibly a device suddenly added */ return search_error; } // if the search was successful then ds->LastDiscrepancy = last_zero; ds->LastDevice = (last_zero < 0); LEVEL_DEBUG("SN found: " SNformat "", SNvar(ds->sn)); return search_good; }
/* Not used by more advanced adapters */ enum search_status BUS_next_both_bitbang(struct device_search *ds, const struct parsedname *pn) { if ( BAD( BUS_select(pn) ) ) { return search_error ; } else { int search_direction = 0; /* initialization just to forestall incorrect compiler warning */ int bit_number; int last_zero = -1; BYTE bits[3]; // initialize for search // if the last call was not the last one if (ds->LastDevice) { return search_done; } /* Appropriate search command */ if ( BAD( BUS_send_data(&(ds->search), 1, pn)) ) { return search_error ; } // Need data from a reset for AnyDevices -- obtained from BUS_data_send above if (pn->selected_connection->AnyDevices == anydevices_no) { ds->LastDevice = 1; return search_done; } // loop to do the search for (bit_number = 0;; ++bit_number) { bits[1] = bits[2] = 0xFF; if (bit_number == 0) { /* First bit */ /* get two bits (AND'ed bit and AND'ed complement) */ if ( BAD( BUS_sendback_bits(&bits[1], &bits[1], 2, pn) ) ) { return search_error; } } else { bits[0] = search_direction; if (bit_number < 64) { /* Send chosen bit path, then check match on next two */ if ( BAD( BUS_sendback_bits(bits, bits, 3, pn) ) ) { return search_error; } } else { /* last bit */ if ( BAD( BUS_sendback_bits(bits, bits, 1, pn) ) ) { return search_error; } break; } } if (bits[1]) { if (bits[2]) { /* 1,1 */ /* No devices respond */ ds->LastDevice = 1; return search_done; } else { /* 1,0 */ search_direction = 1; // bit write value for search } } else if (bits[2]) { /* 0,1 */ search_direction = 0; // bit write value for search } else if (bit_number > ds->LastDiscrepancy) { /* 0,0 looking for last discrepancy in this new branch */ // Past branch, select zeros for now search_direction = 0; last_zero = bit_number; } else if (bit_number == ds->LastDiscrepancy) { /* 0,0 -- new branch */ // at branch (again), select 1 this time search_direction = 1; // if equal to last pick 1, if not then pick 0 } else if (UT_getbit(ds->sn, bit_number)) { /* 0,0 -- old news, use previous "1" bit */ // this discrepancy is before the Last Discrepancy search_direction = 1; } else { /* 0,0 -- old news, use previous "0" bit */ // this discrepancy is before the Last Discrepancy search_direction = 0; last_zero = bit_number; } UT_setbit(ds->sn, bit_number, search_direction); } // loop until through serial number bits if ( (CRC8(ds->sn, SERIAL_NUMBER_SIZE)!=0) || (bit_number < 64) || (ds->sn[0] == 0)) { /* A minor "error" */ return search_error; } // if the search was successful then ds->LastDiscrepancy = last_zero; // printf("Post, lastdiscrep=%d\n",si->LastDiscrepancy) ; ds->LastDevice = (last_zero < 0); return search_good; } }