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