Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

onewire: Implement scan for multiple devices #139

Merged
merged 6 commits into from
Sep 28, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
241 changes: 188 additions & 53 deletions src/hydrabus/hydrabus_mode_onewire.c
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,26 @@ static const char* str_prompt_onewire[] = {
"onewire1" PROMPT,
};

static uint8_t onewire_crc_table[] = {
0, 94,188,226, 97, 63,221,131,194,156,126, 32,163,253, 31, 65,
157,195, 33,127,252,162, 64, 30, 95, 1,227,189, 62, 96,130,220,
35,125,159,193, 66, 28,254,160,225,191, 93, 3,128,222, 60, 98,
190,224, 2, 92,223,129, 99, 61,124, 34,192,158, 29, 67,161,255,
70, 24,250,164, 39,121,155,197,132,218, 56,102,229,187, 89, 7,
219,133,103, 57,186,228, 6, 88, 25, 71,165,251,120, 38,196,154,
101, 59,217,135, 4, 90,184,230,167,249, 27, 69,198,152,122, 36,
248,166, 68, 26,153,199, 37,123, 58,100,134,216, 91, 5,231,185,
140,210, 48,110,237,179, 81, 15, 78, 16,242,172, 47,113,147,205,
17, 79,173,243,112, 46,204,146,211,141,111, 49,178,236, 14, 80,
175,241, 19, 77,206,144,114, 44,109, 51,209,143, 12, 82,176,238,
50,108,142,208, 83, 13,239,177,240,174, 76, 18,145,207, 45,115,
202,148,118, 40,171,245, 23, 73, 8, 86,180,234,105, 55,213,139,
87, 9,235,181, 54,104,138,212,149,203, 41,119,244,170, 72, 22,
233,183, 85, 11,136,214, 52,106, 43,117,151,201, 74, 20,246,168,
116, 42,200,150, 21, 75,169,247,182,232, 10, 84,215,137,107, 53
};


void onewire_init_proto_default(t_hydra_console *con)
{
mode_config_proto_t* proto = &con->mode->proto;
Expand All @@ -47,21 +67,21 @@ static void show_params(t_hydra_console *con)
mode_config_proto_t* proto = &con->mode->proto;

cprintf(con, "Device: onewire%d\r\nGPIO resistor: %s\r\n",
proto->dev_num + 1,
proto->config.onewire.dev_gpio_pull == MODE_CONFIG_DEV_GPIO_PULLUP ? "pull-up" :
proto->config.onewire.dev_gpio_pull == MODE_CONFIG_DEV_GPIO_PULLDOWN ? "pull-down" :
"floating");
proto->dev_num + 1,
proto->config.onewire.dev_gpio_pull == MODE_CONFIG_DEV_GPIO_PULLUP ? "pull-up" :
proto->config.onewire.dev_gpio_pull == MODE_CONFIG_DEV_GPIO_PULLDOWN ? "pull-down" :
"floating");

cprintf(con, "Bit order: %s first\r\n",
proto->config.onewire.dev_bit_lsb_msb == DEV_FIRSTBIT_MSB ? "MSB" : "LSB");
proto->config.onewire.dev_bit_lsb_msb == DEV_FIRSTBIT_MSB ? "MSB" : "LSB");
}

bool onewire_pin_init(t_hydra_console *con)
{
mode_config_proto_t* proto = &con->mode->proto;

bsp_gpio_init(BSP_GPIO_PORTB, ONEWIRE_PIN,
proto->config.onewire.dev_gpio_mode, proto->config.onewire.dev_gpio_pull);
proto->config.onewire.dev_gpio_mode, proto->config.onewire.dev_gpio_pull);
return true;
}

Expand Down Expand Up @@ -91,11 +111,11 @@ void onewire_write_bit(t_hydra_console *con, uint8_t bit)
{
onewire_mode_output(con);
onewire_low();
if(bit){
if(bit) {
DelayUs(6);
onewire_high();
DelayUs(64);
}else{
} else {
DelayUs(60);
onewire_high();
DelayUs(10);
Expand Down Expand Up @@ -135,17 +155,32 @@ static void bitr(t_hydra_console *con)
cprintf(con, hydrabus_mode_str_read_one_u8, rx_data);
}

void onewire_start(t_hydra_console *con)
static bool
onewire_start_and_check(t_hydra_console *con)
{
bool devices_present_p;

/* Pull low for >= 480µsec to signal a bus reset. */
onewire_mode_output(con);
onewire_low();
DelayUs(480);
onewire_high();

/* After some 15..60µsec, devices will pull down the bus if anybody recognized the reset pulse. */
DelayUs(70);
onewire_mode_input(con);
// Can check for device presence here
devices_present_p = ! bsp_gpio_pin_read (BSP_GPIO_PORTB, ONEWIRE_PIN);

/* Wait some more to let all devices release their presence pulse. */
DelayUs(410);

return devices_present_p;
}

void onewire_start(t_hydra_console *con)
{
onewire_start_and_check (con);
return;
}

void onewire_write_u8(t_hydra_console *con, uint8_t tx_data)
Expand Down Expand Up @@ -180,58 +215,158 @@ uint8_t onewire_read_u8(t_hydra_console *con)
return value;
}

void onewire_scan(t_hydra_console *con)
static uint8_t onewire_crc8(uint8_t value, struct onewire_scan_state *state)
{
uint8_t id_bit_number = 0;
uint8_t last_zero = 0;
uint8_t id_bit = 0, cmp_id_bit = 0;
uint8_t search_direction = 0;
uint8_t LastDiscrepancy = 0;
uint8_t LastDeviceFlag = 0;
uint8_t i;
uint8_t ROM_NO[8] = {0};
onewire_start(con);
onewire_write_u8(con, 0xf0);
cprintf(con, "Discovered devices : ");
while(!LastDeviceFlag && !hydrabus_ubtn()) {
do{
state->crc8 = onewire_crc_table[state->crc8 ^ value];

return state->crc8;
}

/* onewire_search() is based on the official bus scan example published by
* Dallas and now hosted by Maxim. It can be found at
* https://www.maximintegrated.com/en/design/technical-documents/app-notes/1/187.html
*
* Changes have been made: Variables no longer use camel case and search state
* was move from a bunch of global variables to a struct. But the overall
* design remains unchanged.
*/
static bool onewire_search(t_hydra_console *con, struct onewire_scan_state *state, enum onewire_scan_mode mode)
jbglaw marked this conversation as resolved.
Show resolved Hide resolved
{
int id_bit_number;
int last_zero, rom_byte_number;
bool device_found_p;
int id_bit, cmp_id_bit;
unsigned char rom_byte_mask, search_direction;

/* Initialize global search state. */
if(mode == onewire_scan_start) {
state->last_discrepancy = 0;
state->last_device_p = false;
state->last_family_discrepancy = 0;
}

/* Initialize for this search. */
id_bit_number = 1;
last_zero = 0;
rom_byte_number = 0;
rom_byte_mask = 1;
device_found_p = false;
state->crc8 = 0;

/* If the last call was not the last one. */
if(!state->last_device_p) {
/* 1-Wire reset. */
if(!onewire_start_and_check(con)) {
/* Reset the search. */
state->last_discrepancy = 0;
state->last_device_p = false;
state->last_family_discrepancy = 0;
return false;
}

/* Issue the search command. */
onewire_write_u8(con, ONEWIRE_CMD_SEARCHROM);

/* Loop to do the search. */
do {
/* Read a bit and its complement. */
id_bit = onewire_read_bit(con);
cmp_id_bit = onewire_read_bit(con);
if(id_bit && cmp_id_bit) {

/* Check for no devices on 1-wire. */
if(id_bit && cmp_id_bit)
break;
} else {
if (!id_bit && !cmp_id_bit) {
if (id_bit_number == LastDiscrepancy) {
search_direction = 1;
} else {
if (id_bit_number > LastDiscrepancy) {
search_direction = 0;
} else {
search_direction =
(ROM_NO[id_bit_number/8]
& (id_bit_number%8))>0;
}
}
else {
/* All devices coupled have 0 or 1. */
if(id_bit != cmp_id_bit)
search_direction = id_bit; /* Bit write value for search. */
else {
/* If this discrepancy if before the Last Discrepancy
on a previous next then pick the same as last time. */
if(id_bit_number < state->last_discrepancy)
search_direction = ((state->ROM_ADDR[rom_byte_number] & rom_byte_mask) > 0);
else
/* If equal to last pick 1, if not then pick 0. */
search_direction = (id_bit_number == state->last_discrepancy);

/* If 0 was picked then record its position in LastZero. */
if(search_direction == 0) {
last_zero = id_bit_number;

/* Check for Last discrepancy in family. */
if(last_zero < 9)
state->last_family_discrepancy = last_zero;
}
} else {
search_direction = id_bit;
}

/* Set or clear the bit in the ROM byte rom_byte_number
with mask rom_byte_mask. */
if(search_direction == 1)
state->ROM_ADDR[rom_byte_number] |= rom_byte_mask;
else
state->ROM_ADDR[rom_byte_number] &= ~rom_byte_mask;

/* Serial number search direction write bit. */
onewire_write_bit(con, search_direction);

/* Increment the byte counter id_bit_number
and shift the mask rom_byte_mask. */
id_bit_number++;
rom_byte_mask <<= 1;

/* If the mask is 0 then go to new SerialNum byte rom_byte_number and reset mask. */
if(rom_byte_mask == 0) {
onewire_crc8(state->ROM_ADDR[rom_byte_number], state); /* Accumulate the CRC. */
rom_byte_number++;
rom_byte_mask = 1;
}
}
ROM_NO[id_bit_number/8] |= search_direction<<(id_bit_number%8);
onewire_write_bit(con, search_direction);
id_bit_number++;
}while(id_bit_number<64);
LastDiscrepancy = last_zero;
if (LastDiscrepancy == 0) {
LastDeviceFlag = true;
}
for(i=0; i<8; i++) {
cprintf(con, "%02X ", ROM_NO[i]);
} while (rom_byte_number < 8); /* Loop until through all ROM bytes 0-7. */

/* If the search was successful then... */
if(!((id_bit_number < 65) || (state->crc8 != 0))) {
/* ...search successful so set last_discrepancy,last_device_p,device_found_p. */
state->last_discrepancy = last_zero;

/* Check for last device. */
if (state->last_discrepancy == 0)
state->last_device_p = true;

device_found_p = true;
}
}

/* If no device found then reset counters so next 'search' will be like a first. */
if(!device_found_p || !state->ROM_ADDR[0]) {
state->last_discrepancy = 0;
state->last_device_p = false;
state->last_family_discrepancy = 0;
device_found_p = false;
}

return device_found_p;
}

static void onewire_scan(t_hydra_console *con)
{
int i;
int count = 0;
bool device_found_p;
struct onewire_scan_state state;

cprintf(con, "Scanning bus for devices.\r\n");

device_found_p = onewire_search(con, &state, onewire_scan_start);
while(device_found_p) {
cprintf(con, "%i: ", ++count);
for(i = 0; i < 8; i++)
cprintf(con, "%02X ", state.ROM_ADDR[i]);
cprintf(con, "\r\n");

device_found_p = onewire_search(con, &state, onewire_scan_continue);
}

return;
}

static int init(t_hydra_console *con, t_tokenline_parsed *p)
Expand Down Expand Up @@ -308,7 +443,7 @@ static uint32_t write(t_hydra_console *con, uint8_t *tx_data, uint8_t nb_data)
cprintf(con, hydrabus_mode_str_mul_write);
for(i = 0; i < nb_data; i++) {
cprintf(con, hydrabus_mode_str_mul_value_u8,
tx_data[i]);
tx_data[i]);
}
cprintf(con, hydrabus_mode_str_mul_br);
}
Expand All @@ -330,7 +465,7 @@ static uint32_t read(t_hydra_console *con, uint8_t *rx_data, uint8_t nb_data)
cprintf(con, hydrabus_mode_str_mul_read);
for(i = 0; i < nb_data; i++) {
cprintf(con, hydrabus_mode_str_mul_value_u8,
rx_data[i]);
rx_data[i]);
}
cprintf(con, hydrabus_mode_str_mul_br);
}
Expand All @@ -342,7 +477,7 @@ static uint32_t dump(t_hydra_console *con, uint8_t *rx_data, uint8_t nb_data)
uint8_t i;

i = 0;
while(i < nb_data){
while(i < nb_data) {
rx_data[i] = onewire_read_u8(con);
i++;
}
Expand Down
13 changes: 12 additions & 1 deletion src/hydrabus/hydrabus_mode_onewire.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,4 +38,15 @@ void onewire_send_bit(t_hydra_console *con, uint8_t bit);
uint8_t onewire_read_bit(t_hydra_console *con);
void onewire_cleanup(t_hydra_console *con);
void onewire_start(t_hydra_console *con);
void onewire_scan(t_hydra_console *con);

struct onewire_scan_state {
uint8_t ROM_ADDR[8];
int last_discrepancy;
int last_family_discrepancy;
bool last_device_p;
uint8_t crc8;
};
enum onewire_scan_mode {
onewire_scan_start,
onewire_scan_continue,
};