Поиск устройств на шине 1-wire
Posted on February 20, 2016 with tags: rust.
Поиск устройств на шине 1-wire считается делом не простым и замысловатым. Причиной этого является 64-битный размер идентификатора (на самом деле 8-бит это CRC, но в данном случае это не играет роли) и опросить все возможные идентификаторы на предмет их присутствия на шине за вменяемое время не представляется возможным.
// Пишем функции — затычки для взаимодействия с несуществующей у нас переферией.
fn one_wire_reset(){}
fn is_presance() -> bool { true }
fn one_wire_write( c: u8 ){}
fn read_bit() -> u8 { 1 }
fn read_unbit() -> u8 { 0 }
struct SearchState {
last_device_flag: u8,
last_discrepancy: u8,
search_direction: u8,
rom_no: u64
}
enum SearchResult {
NotFound,
Rom( u64 )
}
fn search_rom( state: &mut SearchState ) -> SearchResult
{
let mut last_zero: u8 = 0;
let mut result = SearchResult::NotFound;
// Сбрасываем шину.
one_wire_reset();
if is_presance() && state.last_device_flag != 1
{
// Запускаем процесс поиска.
one_wire_write( 0x0F );
for id_bit_number in 1..64 {
let id_bit = read_bit();
let cmp_id_bit = read_unbit();
if id_bit == 1 && cmp_id_bit == 1
{
break;
}
state.search_direction =
match id_bit_number {
_ if id_bit != cmp_id_bit => id_bit,
_ if id_bit_number == state.last_discrepancy => 1,
_ if id_bit_number > state.last_discrepancy => 0,
_ =>
if state.rom_no & (1 << id_bit_number as u64) == 0 { 0 } else { 1 }
};
if state.search_direction == 0
{
last_zero = id_bit_number;
state.rom_no &= !( 1 << id_bit_number as u64 );
}
else
{
state.rom_no |= 1 << id_bit_number as u64;
}
// Отправляем устройствам бит выбранного направления обхода.
one_wire_write( state.search_direction );
if id_bit_number == 64
{
result = SearchResult::Rom( state.rom_no );
}
}
}
match result {
SearchResult::Rom( _ ) =>
{
state.last_discrepancy = last_zero;
if state.last_discrepancy == 0 { state.last_device_flag = 1 }
}
SearchResult::NotFound =>
{
state.last_discrepancy = 0;
state.last_device_flag = 0;
}
}
return result;
}
fn main()
{
// Создаём начальный стейт нашего поиска.
let mut state =
SearchState {
last_device_flag: 0,
last_discrepancy: 0,
search_direction: 0,
rom_no: 0
};
// Ищем устройства до тех пор пока они находятся.
loop {
match search_rom( &mut state ) {
SearchResult::Rom( w ) => println!( "{}", w ),
SearchResult::NotFound => break
}
}
}