parent
a81190c2e1
commit
0e378b6547
@ -0,0 +1,34 @@ |
|||||||
|
//
|
||||||
|
// Created by MightyPork on 2018/02/01.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "platform.h" |
||||||
|
#include "_ow_checksum.h" |
||||||
|
|
||||||
|
static inline uint8_t crc8_bits(uint8_t data) |
||||||
|
{ |
||||||
|
uint8_t crc = 0; |
||||||
|
if(data & 1) crc ^= 0x5e; |
||||||
|
if(data & 2) crc ^= 0xbc; |
||||||
|
if(data & 4) crc ^= 0x61; |
||||||
|
if(data & 8) crc ^= 0xc2; |
||||||
|
if(data & 0x10) crc ^= 0x9d; |
||||||
|
if(data & 0x20) crc ^= 0x23; |
||||||
|
if(data & 0x40) crc ^= 0x46; |
||||||
|
if(data & 0x80) crc ^= 0x8c; |
||||||
|
return crc; |
||||||
|
} |
||||||
|
|
||||||
|
static uint8_t crc8_add(uint8_t cksum, uint8_t byte) |
||||||
|
{ |
||||||
|
return crc8_bits(byte ^ cksum); |
||||||
|
} |
||||||
|
|
||||||
|
uint8_t ow_checksum(const uint8_t *buff, uint16_t len) |
||||||
|
{ |
||||||
|
uint8_t cksum = 0; |
||||||
|
for(uint16_t i = 0; i < len; i++) { |
||||||
|
cksum = crc8_add(cksum, buff[i]); |
||||||
|
} |
||||||
|
return cksum; |
||||||
|
} |
@ -0,0 +1,23 @@ |
|||||||
|
//
|
||||||
|
// Created by MightyPork on 2018/02/01.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef GEX_F072_OW_CHECKSUM_H |
||||||
|
#define GEX_F072_OW_CHECKSUM_H |
||||||
|
|
||||||
|
#include <stdint.h> |
||||||
|
|
||||||
|
/**
|
||||||
|
* Compute a 1-wire type checksum. |
||||||
|
* If the buffer includes the checksum, the result should be 0. |
||||||
|
* |
||||||
|
* (this function may be used externally, or you can delete the implementation |
||||||
|
* from the c file if another implementation is already available) |
||||||
|
* |
||||||
|
* @param[in] buf - buffer of bytes to verify |
||||||
|
* @param[in] len - buffer length |
||||||
|
* @return checksum |
||||||
|
*/ |
||||||
|
uint8_t ow_checksum(const uint8_t *buf, uint16_t len); |
||||||
|
|
||||||
|
#endif //GEX_F072_OW_CHECKSUM_H
|
@ -0,0 +1,67 @@ |
|||||||
|
//
|
||||||
|
// Created by MightyPork on 2018/02/01.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef GEX_F072_OW_LOW_LEVEL_H |
||||||
|
#define GEX_F072_OW_LOW_LEVEL_H |
||||||
|
|
||||||
|
#include "platform.h" |
||||||
|
#include "unit_base.h" |
||||||
|
#include "_ow_low_level.h" |
||||||
|
|
||||||
|
/**
|
||||||
|
* Reset the 1-wire bus |
||||||
|
*/ |
||||||
|
bool ow_reset(Unit *unit); |
||||||
|
|
||||||
|
/**
|
||||||
|
* Write a bit to the 1-wire bus |
||||||
|
*/ |
||||||
|
void ow_write_bit(Unit *unit, bool bit); |
||||||
|
|
||||||
|
/**
|
||||||
|
* Read a bit from the 1-wire bus |
||||||
|
*/ |
||||||
|
bool ow_read_bit(Unit *unit); |
||||||
|
|
||||||
|
/**
|
||||||
|
* Write a byte to the 1-wire bus |
||||||
|
*/ |
||||||
|
void ow_write_u8(Unit *unit, uint8_t byte); |
||||||
|
|
||||||
|
/**
|
||||||
|
* Write a halfword to the 1-wire bus |
||||||
|
*/ |
||||||
|
void ow_write_u16(Unit *unit, uint16_t halfword); |
||||||
|
|
||||||
|
/**
|
||||||
|
* Write a word to the 1-wire bus |
||||||
|
*/ |
||||||
|
void ow_write_u32(Unit *unit, uint32_t word); |
||||||
|
|
||||||
|
/**
|
||||||
|
* Write a doubleword to the 1-wire bus |
||||||
|
*/ |
||||||
|
void ow_write_u64(Unit *unit, uint64_t dword); |
||||||
|
|
||||||
|
/**
|
||||||
|
* Read a byte form the 1-wire bus |
||||||
|
*/ |
||||||
|
uint8_t ow_read_u8(Unit *unit); |
||||||
|
|
||||||
|
/**
|
||||||
|
* Read a halfword form the 1-wire bus |
||||||
|
*/ |
||||||
|
uint16_t ow_read_u16(Unit *unit); |
||||||
|
|
||||||
|
/**
|
||||||
|
* Read a word form the 1-wire bus |
||||||
|
*/ |
||||||
|
uint32_t ow_read_u32(Unit *unit); |
||||||
|
|
||||||
|
/**
|
||||||
|
* Read a doubleword form the 1-wire bus |
||||||
|
*/ |
||||||
|
uint64_t ow_read_u64(Unit *unit); |
||||||
|
|
||||||
|
#endif //GEX_F072_OW_LOW_LEVEL_H
|
@ -0,0 +1,121 @@ |
|||||||
|
//
|
||||||
|
// Created by MightyPork on 2018/02/01.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "platform.h" |
||||||
|
#include "unit_1wire.h" |
||||||
|
|
||||||
|
#define OW_INTERNAL |
||||||
|
#include "_ow_search.h" |
||||||
|
#include "_ow_internal.h" |
||||||
|
#include "_ow_low_level.h" |
||||||
|
#include "_ow_checksum.h" |
||||||
|
#include "_ow_commands.h" |
||||||
|
|
||||||
|
void ow_search_init(Unit *unit, uint8_t command, bool test_checksums) |
||||||
|
{ |
||||||
|
if (unit->driver != &UNIT_1WIRE) |
||||||
|
trap("Wrong unit type - %s", unit->driver->name); |
||||||
|
|
||||||
|
assert_param(command == OW_ROM_SEARCH || command == OW_ROM_ALM_SEARCH); |
||||||
|
|
||||||
|
struct priv *priv = unit->data; |
||||||
|
struct ow_search_state *state = &priv->searchState; |
||||||
|
|
||||||
|
state->prev_last_fork = 64; |
||||||
|
memset(state->prev_code, 0, 8); |
||||||
|
state->status = OW_SEARCH_MORE; |
||||||
|
state->command = command; |
||||||
|
state->first = true; |
||||||
|
state->test_checksums = test_checksums; |
||||||
|
} |
||||||
|
|
||||||
|
uint16_t ow_search_run(Unit *unit, ow_romcode_t *codes, uint16_t capacity) |
||||||
|
{ |
||||||
|
if (unit->driver != &UNIT_1WIRE) |
||||||
|
trap("Wrong unit type - %s", unit->driver->name); |
||||||
|
|
||||||
|
assert_param(codes); |
||||||
|
|
||||||
|
struct priv *priv = unit->data; |
||||||
|
struct ow_search_state *state = &priv->searchState; |
||||||
|
|
||||||
|
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(unit)) { |
||||||
|
state->status = OW_SEARCH_FAILED; |
||||||
|
goto done; |
||||||
|
} |
||||||
|
// Send the search command (SEARCH_ROM, SEARCH_ALARM)
|
||||||
|
ow_write_u8(unit, state->command); |
||||||
|
|
||||||
|
uint8_t *code_byte = &code[0]; |
||||||
|
|
||||||
|
bool p, n; |
||||||
|
while (index != 64) { |
||||||
|
// Read a bit and its complement
|
||||||
|
p = ow_read_bit(unit); |
||||||
|
n = ow_read_bit(unit); |
||||||
|
|
||||||
|
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) *code_byte |= (1 << (index & 7)); |
||||||
|
ow_write_bit(unit, p); |
||||||
|
|
||||||
|
index++; |
||||||
|
if((index & 7) == 0) { |
||||||
|
code_byte++; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
memcpy(state->prev_code, code, 8); |
||||||
|
|
||||||
|
if (!state->test_checksums || 0 == ow_checksum(code, 8)) { |
||||||
|
// Record a found address
|
||||||
|
memcpy(codes[found_devices], code, 8); |
||||||
|
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,81 @@ |
|||||||
|
//
|
||||||
|
// Created by MightyPork on 2018/02/01.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef GEX_F072_OW_SEARCH_H |
||||||
|
#define GEX_F072_OW_SEARCH_H |
||||||
|
|
||||||
|
#ifndef OW_INTERNAL |
||||||
|
#error bad include! |
||||||
|
#endif |
||||||
|
|
||||||
|
#include <stdint.h> |
||||||
|
#include <stdbool.h> |
||||||
|
#include "unit_base.h" |
||||||
|
|
||||||
|
// --------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Data type holding a romcode |
||||||
|
*/ |
||||||
|
typedef uint8_t ow_romcode_t[8]; |
||||||
|
|
||||||
|
/**
|
||||||
|
* Get a single bit from a romcode |
||||||
|
*/ |
||||||
|
#define ow_code_getbit(code, index) (bool)((code)[(index) >> 3] & (1 << ((index) & 7))) |
||||||
|
|
||||||
|
/**
|
||||||
|
* Convert to unsigned 64-bit integer |
||||||
|
* (works only on little-endian systems - eg. OK on x86/x86_64, not on PowerPC) |
||||||
|
*/ |
||||||
|
#define ow_romcode_to_u64(code) (*((uint64_t *) (void *)(code))) |
||||||
|
|
||||||
|
/**
|
||||||
|
* 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; |
||||||
|
bool test_checksums; |
||||||
|
}; |
||||||
|
|
||||||
|
/**
|
||||||
|
* Init the search algorithm state structure |
||||||
|
* |
||||||
|
* @param[out] state - inited struct |
||||||
|
* @param[in] command - command to send for requesting the search (e.g. SEARCH_ROM) |
||||||
|
* @param[in] test_checksums - verify checksums of all read romcodes |
||||||
|
*/ |
||||||
|
void ow_search_init(Unit *unit, uint8_t command, bool test_checksums); |
||||||
|
|
||||||
|
/**
|
||||||
|
* Perform a search of the 1-wire bus, with a state struct pre-inited |
||||||
|
* using ow_search_init(). |
||||||
|
* |
||||||
|
* Romcodes are stored in the provided array in a numerically ascending order. |
||||||
|
* |
||||||
|
* This function may be called repeatedly to retrieve more addresses than could fit |
||||||
|
* in the address buffer. |
||||||
|
* |
||||||
|
* @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(Unit *unit, ow_romcode_t *codes, uint16_t capacity); |
||||||
|
|
||||||
|
#endif //GEX_F072_OW_SEARCH_H
|
Loading…
Reference in new issue