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