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