parent
97b33510d9
commit
f7bcc754e4
@ -0,0 +1,6 @@ |
||||
cmake-build-debug/ |
||||
.idea/ |
||||
CMakeLists.txt |
||||
*.o |
||||
*.elf |
||||
*.out |
@ -0,0 +1,122 @@ |
||||
#include <stdlib.h> |
||||
#include <stdio.h> |
||||
#include <stdint.h> |
||||
#include <stdbool.h> |
||||
#include <inttypes.h> |
||||
|
||||
#include "ow_search.h" |
||||
|
||||
// ----------- DEMO -----------------
|
||||
|
||||
void main(void) |
||||
{ |
||||
struct ow_search_state search_state; |
||||
ow_search_init(&search_state, 0xFF); // the real onewire search command will go here when used with real hw
|
||||
|
||||
ow_romcode_t addresses[4]; |
||||
|
||||
int x=0; |
||||
while (search_state.status == OW_SEARCH_MORE) { |
||||
uint16_t count = ow_search_run(&search_state, addresses, 4); |
||||
printf("Found %d addresses, status %d\n", count, search_state.status); |
||||
for(int i=0; i<count; i++) { |
||||
for(int j=0; j<8; j++) { |
||||
printf("%02x ", addresses[i][j]); |
||||
} |
||||
printf("\n"); |
||||
uint64_t numeric = *((uint64_t*)(void*)&addresses[i][0]); |
||||
printf("n = 0x%016"PRIx64"\n", numeric); |
||||
} |
||||
printf("\n"); |
||||
if(++x > 10) break; |
||||
} |
||||
} |
||||
|
||||
// ------------ SIMULATOR ---------------
|
||||
|
||||
struct owunit { |
||||
ow_romcode_t romcode; |
||||
bool selected; |
||||
uint8_t rompos; |
||||
int state; |
||||
}; |
||||
|
||||
#define UNITS_COUNT 12 |
||||
struct owunit units[UNITS_COUNT] = { |
||||
{.romcode = {0b00000000}},//00
|
||||
{.romcode = {0b00000001}},//01
|
||||
{.romcode = {0b00010001}},//11
|
||||
{.romcode = {0b00110001}},//31
|
||||
{.romcode = {0b00110101}},//35
|
||||
{.romcode = {0b01010001}},//51
|
||||
{.romcode = {0b10000000}},//80
|
||||
{.romcode = {0b10101010}},//aa
|
||||
{.romcode = {0b11110101}},//f5
|
||||
{.romcode = {0b11110111}},//f7
|
||||
{.romcode = {0xFF,0x00,0xFF,0x00,0x55,0x00,0xAA,0x00}}, |
||||
{.romcode = {0x12,0x34,0x56,0x78,0x9a,0xbc,0xde,0xf0}}, |
||||
}; |
||||
|
||||
bool rom_device_reset(struct owunit *device) |
||||
{ |
||||
device->rompos = 0; |
||||
device->state = 0; |
||||
device->selected = true; |
||||
} |
||||
|
||||
bool rom_device_read(struct owunit *device) |
||||
{ |
||||
if (!device->selected) return true; |
||||
if (device->state == 0) { |
||||
device->state++; |
||||
bool res = ow_code_getbit(device->romcode, device->rompos); |
||||
return res; |
||||
} |
||||
if (device->state == 1) { |
||||
device->state++; |
||||
bool res = !ow_code_getbit(device->romcode, device->rompos); |
||||
return res; |
||||
} |
||||
} |
||||
|
||||
void rom_device_write(struct owunit *device, bool selectedbit) |
||||
{ |
||||
if (!device->selected) return; |
||||
|
||||
if (ow_code_getbit(device->romcode, device->rompos) != selectedbit) { |
||||
device->selected = false; |
||||
} |
||||
else { |
||||
device->rompos++; |
||||
device->state = 0; |
||||
} |
||||
} |
||||
|
||||
bool ow_reset(void) |
||||
{ |
||||
for (int i = 0; i < UNITS_COUNT; ++i) { |
||||
rom_device_reset(&units[i]); |
||||
} |
||||
return (UNITS_COUNT > 0); |
||||
} |
||||
|
||||
bool ow_read_bit(void) |
||||
{ |
||||
bool bus = 1; |
||||
for (int i = 0; i < UNITS_COUNT; ++i) { |
||||
bus &= rom_device_read(&units[i]); |
||||
} |
||||
return bus; |
||||
} |
||||
|
||||
void ow_write_bit(bool value) |
||||
{ |
||||
for (int i = 0; i < UNITS_COUNT; ++i) { |
||||
rom_device_write(&units[i], value); |
||||
} |
||||
} |
||||
|
||||
void ow_write_u8(uint8_t value) |
||||
{ |
||||
// Dummy, do nothing
|
||||
} |
@ -0,0 +1,92 @@ |
||||
//
|
||||
// Created by MightyPork on 2018/02/01.
|
||||
//
|
||||
|
||||
#include <stdlib.h> |
||||
#include <stdint.h> |
||||
#include <stdbool.h> |
||||
#include <string.h> |
||||
|
||||
#include "ow_search.h" |
||||
|
||||
void ow_search_init(struct ow_search_state *state, uint8_t command) |
||||
{ |
||||
state->prev_last_fork = 64; |
||||
memset(&state->prev_code[0], 0, 8); |
||||
state->status = OW_SEARCH_MORE; |
||||
state->command = command; |
||||
state->first = true; |
||||
} |
||||
|
||||
uint16_t |
||||
ow_search_run(struct ow_search_state *state, ow_romcode_t *codes, uint16_t capacity) |
||||
{ |
||||
if (state->status != OW_SEARCH_MORE) return 0; |
||||
|
||||
uint16_t found_devices = 0; |
||||
|
||||
while (found_devices < capacity) { |
||||
uint8_t index = 0; |
||||
ow_romcode_t code = {}; |
||||
int8_t last_fork = -1; |
||||
|
||||
// Start a new transaction. Devices respond to reset
|
||||
if (!ow_reset()) { |
||||
state->status = OW_SEARCH_FAILED; |
||||
goto done; |
||||
} |
||||
// Send the search command (SEARCH_ROM, SEARCH_ALARM)
|
||||
ow_write_u8(state->command); |
||||
|
||||
bool p, n; |
||||
while (index != 64) { |
||||
// Read a bit and its complement
|
||||
p = ow_read_bit(); |
||||
n = ow_read_bit(); |
||||
|
||||
if (!p && !n) { |
||||
// A fork: there are devices on the bus with different bit value
|
||||
// (the bus is open-drain, in both cases one device pulls it low)
|
||||
if ((found_devices > 0 || !state->first) && |
||||
index < state->prev_last_fork) { |
||||
// earlier than the last fork, take the same turn as before
|
||||
p = ow_code_getbit(state->prev_code, index); |
||||
if (!p) last_fork = index; // remember for future runs, 1 not explored yet
|
||||
} |
||||
else if (index == state->prev_last_fork) { |
||||
p = 1; // both forks are now exhausted
|
||||
} |
||||
else { // a new fork
|
||||
last_fork = index; |
||||
} |
||||
} |
||||
else if (p && n) { |
||||
// No devices left connected - this doesn't normally happen
|
||||
state->status = OW_SEARCH_FAILED; |
||||
goto done; |
||||
} |
||||
|
||||
// All devices have a matching bit here, or it was resolved in a fork
|
||||
if (p) ow_code_setbit(code, index); |
||||
ow_write_bit(p); |
||||
index++; |
||||
} |
||||
|
||||
// Record a found address
|
||||
for (int i = 0; i < 8; i++) { |
||||
state->prev_code[i] = codes[found_devices][i] = code[i]; |
||||
} |
||||
found_devices++; |
||||
|
||||
// Stop condition
|
||||
if (last_fork == -1) { |
||||
state->status = OW_SEARCH_DONE; |
||||
goto done; |
||||
} |
||||
|
||||
state->prev_last_fork = last_fork; |
||||
} |
||||
done: |
||||
state->first = false; |
||||
return found_devices; |
||||
} |
@ -0,0 +1,92 @@ |
||||
//
|
||||
// Created by MightyPork on 2018/02/01.
|
||||
//
|
||||
|
||||
#ifndef OW_SEARCH_H |
||||
#define OW_SEARCH_H |
||||
|
||||
// --------------------------------------------------------------------------------------
|
||||
|
||||
// External API functions for interfacing the bus
|
||||
// Customize as needed (and also update calls in the search function)
|
||||
|
||||
/**
|
||||
* Reset the 1-wire bus |
||||
* |
||||
* @return presence pulse received |
||||
*/ |
||||
extern bool ow_reset(void); |
||||
|
||||
/**
|
||||
* Write a byte to the bus |
||||
* |
||||
* @param[in] value byte value |
||||
*/ |
||||
extern void ow_write_u8(uint8_t value); |
||||
/**
|
||||
* Write a bit to the 1-wire bus |
||||
* |
||||
* @param[in] value bit value |
||||
*/ |
||||
extern void ow_write_bit(bool value); |
||||
|
||||
/**
|
||||
* Read a bit from the 1-wire bus |
||||
* |
||||
* @return bit value |
||||
*/ |
||||
extern bool ow_read_bit(void); |
||||
|
||||
// --------------------------------------------------------------------------------------
|
||||
|
||||
/** Data type holding one romcode */ |
||||
typedef uint8_t ow_romcode_t[8]; |
||||
|
||||
/** Get a bit from a romcode */ |
||||
#define ow_code_getbit(code, index) (bool)((code)[(index) / 8] & (1 << ((index) % 8))) |
||||
/** Set a bit to 1 in a romcode */ |
||||
#define ow_code_setbit(code, index) ((code)[(index) / 8] |= (1 << ((index) % 8))) |
||||
|
||||
/**
|
||||
* States of the search algorithm |
||||
*/ |
||||
enum ow_search_result { |
||||
OW_SEARCH_DONE = 0, |
||||
OW_SEARCH_MORE = 1, |
||||
OW_SEARCH_FAILED = 2, |
||||
}; |
||||
|
||||
/**
|
||||
* Internal state of the search algorithm. |
||||
* Check status to see if more remain to be read or an error occurred. |
||||
*/ |
||||
struct ow_search_state { |
||||
int8_t prev_last_fork; |
||||
ow_romcode_t prev_code; |
||||
uint8_t command; |
||||
enum ow_search_result status; |
||||
bool first; |
||||
}; |
||||
|
||||
/**
|
||||
* Init the state search struct |
||||
* |
||||
* @param[out] state - inited struct |
||||
* @param[in] command - command to send for requesting the search (e.g. SEARCH_ROM) |
||||
*/ |
||||
void ow_search_init(struct ow_search_state *state, uint8_t command); |
||||
|
||||
/**
|
||||
* Perform a search of the 1-wire bus, with a state struct pre-inited |
||||
* using ow_search_init(). |
||||
* |
||||
* Romcodes are stored in the byte arrays in a numerically ascending order. |
||||
* |
||||
* @param[in,out] state - search state, used for multiple calls with limited buffer size |
||||
* @param[out] codes - buffer for found romcodes |
||||
* @param[in] capacity - buffer capacity |
||||
* @return number of romcodes found. Search status is stored in state->status |
||||
*/ |
||||
uint16_t ow_search_run(struct ow_search_state *state, ow_romcode_t *codes, uint16_t capacity); |
||||
|
||||
#endif //OW_SEARCH_H
|
Loading…
Reference in new issue