one_wire_host.c 9.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321
  1. #include <furi.h>
  2. /**
  3. * Timings based on Application Note 126:
  4. * https://www.analog.com/media/en/technical-documentation/tech-articles/1wire-communication-through-software--maxim-integrated.pdf
  5. */
  6. #include "one_wire_host.h"
  7. typedef struct {
  8. uint16_t a;
  9. uint16_t b;
  10. uint16_t c;
  11. uint16_t d;
  12. uint16_t e;
  13. uint16_t f;
  14. uint16_t g;
  15. uint16_t h;
  16. uint16_t i;
  17. uint16_t j;
  18. } OneWireHostTimings;
  19. static const OneWireHostTimings onewire_host_timings_normal = {
  20. .a = 9,
  21. .b = 64,
  22. .c = 64,
  23. .d = 14,
  24. .e = 9,
  25. .f = 55,
  26. .g = 0,
  27. .h = 480,
  28. .i = 70,
  29. .j = 410,
  30. };
  31. static const OneWireHostTimings onewire_host_timings_overdrive = {
  32. .a = 1,
  33. .b = 8,
  34. .c = 8,
  35. .d = 3,
  36. .e = 1,
  37. .f = 7,
  38. .g = 3,
  39. .h = 70,
  40. .i = 9,
  41. .j = 40,
  42. };
  43. struct OneWireHost {
  44. const GpioPin* gpio_pin;
  45. const OneWireHostTimings* timings;
  46. unsigned char saved_rom[8]; /** < global search state */
  47. uint8_t last_discrepancy;
  48. uint8_t last_family_discrepancy;
  49. bool last_device_flag;
  50. };
  51. OneWireHost* onewire_host_alloc(const GpioPin* gpio_pin) {
  52. OneWireHost* host = malloc(sizeof(OneWireHost));
  53. host->gpio_pin = gpio_pin;
  54. onewire_host_reset_search(host);
  55. onewire_host_set_overdrive(host, false);
  56. return host;
  57. }
  58. void onewire_host_free(OneWireHost* host) {
  59. onewire_host_stop(host);
  60. free(host);
  61. }
  62. bool onewire_host_reset(OneWireHost* host) {
  63. uint8_t r;
  64. uint8_t retries = 125;
  65. const OneWireHostTimings* timings = host->timings;
  66. // wait until the gpio is high
  67. furi_hal_gpio_write(host->gpio_pin, true);
  68. do {
  69. if(--retries == 0) return 0;
  70. furi_delay_us(2);
  71. } while(!furi_hal_gpio_read(host->gpio_pin));
  72. // pre delay
  73. furi_delay_us(timings->g);
  74. // drive low
  75. furi_hal_gpio_write(host->gpio_pin, false);
  76. furi_delay_us(timings->h);
  77. // release
  78. furi_hal_gpio_write(host->gpio_pin, true);
  79. furi_delay_us(timings->i);
  80. // read and post delay
  81. r = !furi_hal_gpio_read(host->gpio_pin);
  82. furi_delay_us(timings->j);
  83. return r;
  84. }
  85. bool onewire_host_read_bit(OneWireHost* host) {
  86. bool result;
  87. const OneWireHostTimings* timings = host->timings;
  88. // drive low
  89. furi_hal_gpio_write(host->gpio_pin, false);
  90. furi_delay_us(timings->a);
  91. // release
  92. furi_hal_gpio_write(host->gpio_pin, true);
  93. furi_delay_us(timings->e);
  94. // read and post delay
  95. result = furi_hal_gpio_read(host->gpio_pin);
  96. furi_delay_us(timings->f);
  97. return result;
  98. }
  99. uint8_t onewire_host_read(OneWireHost* host) {
  100. uint8_t result = 0;
  101. for(uint8_t bitMask = 0x01; bitMask; bitMask <<= 1) {
  102. if(onewire_host_read_bit(host)) {
  103. result |= bitMask;
  104. }
  105. }
  106. return result;
  107. }
  108. void onewire_host_read_bytes(OneWireHost* host, uint8_t* buffer, uint16_t count) {
  109. for(uint16_t i = 0; i < count; i++) {
  110. buffer[i] = onewire_host_read(host);
  111. }
  112. }
  113. void onewire_host_write_bit(OneWireHost* host, bool value) {
  114. const OneWireHostTimings* timings = host->timings;
  115. if(value) {
  116. // drive low
  117. furi_hal_gpio_write(host->gpio_pin, false);
  118. furi_delay_us(timings->a);
  119. // release
  120. furi_hal_gpio_write(host->gpio_pin, true);
  121. furi_delay_us(timings->b);
  122. } else {
  123. // drive low
  124. furi_hal_gpio_write(host->gpio_pin, false);
  125. furi_delay_us(timings->c);
  126. // release
  127. furi_hal_gpio_write(host->gpio_pin, true);
  128. furi_delay_us(timings->d);
  129. }
  130. }
  131. void onewire_host_write(OneWireHost* host, uint8_t value) {
  132. uint8_t bitMask;
  133. for(bitMask = 0x01; bitMask; bitMask <<= 1) {
  134. onewire_host_write_bit(host, (bitMask & value) ? 1 : 0);
  135. }
  136. }
  137. void onewire_host_write_bytes(OneWireHost* host, const uint8_t* buffer, uint16_t count) {
  138. for(uint16_t i = 0; i < count; ++i) {
  139. onewire_host_write(host, buffer[i]);
  140. }
  141. }
  142. void onewire_host_start(OneWireHost* host) {
  143. furi_hal_gpio_write(host->gpio_pin, true);
  144. furi_hal_gpio_init(host->gpio_pin, GpioModeOutputOpenDrain, GpioPullNo, GpioSpeedLow);
  145. }
  146. void onewire_host_stop(OneWireHost* host) {
  147. furi_hal_gpio_write(host->gpio_pin, true);
  148. furi_hal_gpio_init(host->gpio_pin, GpioModeAnalog, GpioPullNo, GpioSpeedLow);
  149. }
  150. void onewire_host_reset_search(OneWireHost* host) {
  151. host->last_discrepancy = 0;
  152. host->last_device_flag = false;
  153. host->last_family_discrepancy = 0;
  154. for(int i = 7;; i--) {
  155. host->saved_rom[i] = 0;
  156. if(i == 0) break;
  157. }
  158. }
  159. void onewire_host_target_search(OneWireHost* host, uint8_t family_code) {
  160. host->saved_rom[0] = family_code;
  161. for(uint8_t i = 1; i < 8; i++) host->saved_rom[i] = 0;
  162. host->last_discrepancy = 64;
  163. host->last_family_discrepancy = 0;
  164. host->last_device_flag = false;
  165. }
  166. bool onewire_host_search(OneWireHost* host, uint8_t* new_addr, OneWireHostSearchMode mode) {
  167. uint8_t id_bit_number;
  168. uint8_t last_zero, rom_byte_number, search_result;
  169. uint8_t id_bit, cmp_id_bit;
  170. unsigned char rom_byte_mask, search_direction;
  171. // initialize for search
  172. id_bit_number = 1;
  173. last_zero = 0;
  174. rom_byte_number = 0;
  175. rom_byte_mask = 1;
  176. search_result = 0;
  177. // if the last call was not the last one
  178. if(!host->last_device_flag) {
  179. // 1-Wire reset
  180. if(!onewire_host_reset(host)) {
  181. // reset the search
  182. host->last_discrepancy = 0;
  183. host->last_device_flag = false;
  184. host->last_family_discrepancy = 0;
  185. return false;
  186. }
  187. // issue the search command
  188. switch(mode) {
  189. case OneWireHostSearchModeConditional:
  190. onewire_host_write(host, 0xEC);
  191. break;
  192. case OneWireHostSearchModeNormal:
  193. onewire_host_write(host, 0xF0);
  194. break;
  195. }
  196. // loop to do the search
  197. do {
  198. // read a bit and its complement
  199. id_bit = onewire_host_read_bit(host);
  200. cmp_id_bit = onewire_host_read_bit(host);
  201. // check for no devices on 1-wire
  202. if((id_bit == 1) && (cmp_id_bit == 1))
  203. break;
  204. else {
  205. // all devices coupled have 0 or 1
  206. if(id_bit != cmp_id_bit)
  207. search_direction = id_bit; // bit write value for search
  208. else {
  209. // if this discrepancy if before the Last Discrepancy
  210. // on a previous next then pick the same as last time
  211. if(id_bit_number < host->last_discrepancy)
  212. search_direction =
  213. ((host->saved_rom[rom_byte_number] & rom_byte_mask) > 0);
  214. else
  215. // if equal to last pick 1, if not then pick 0
  216. search_direction = (id_bit_number == host->last_discrepancy);
  217. // if 0 was picked then record its position in LastZero
  218. if(search_direction == 0) {
  219. last_zero = id_bit_number;
  220. // check for Last discrepancy in family
  221. if(last_zero < 9) host->last_family_discrepancy = last_zero;
  222. }
  223. }
  224. // set or clear the bit in the ROM byte rom_byte_number
  225. // with mask rom_byte_mask
  226. if(search_direction == 1)
  227. host->saved_rom[rom_byte_number] |= rom_byte_mask;
  228. else
  229. host->saved_rom[rom_byte_number] &= ~rom_byte_mask;
  230. // serial number search direction write bit
  231. onewire_host_write_bit(host, search_direction);
  232. // increment the byte counter id_bit_number
  233. // and shift the mask rom_byte_mask
  234. id_bit_number++;
  235. rom_byte_mask <<= 1;
  236. // if the mask is 0 then go to new SerialNum byte rom_byte_number and reset mask
  237. if(rom_byte_mask == 0) {
  238. rom_byte_number++;
  239. rom_byte_mask = 1;
  240. }
  241. }
  242. } while(rom_byte_number < 8); // loop until through all ROM bytes 0-7
  243. // if the search was successful then
  244. if(!(id_bit_number < 65)) {
  245. // search successful so set last_Discrepancy, last_device_flag, search_result
  246. host->last_discrepancy = last_zero;
  247. // check for last device
  248. if(host->last_discrepancy == 0) host->last_device_flag = true;
  249. search_result = true;
  250. }
  251. }
  252. // if no device found then reset counters so next 'search' will be like a first
  253. if(!search_result || !host->saved_rom[0]) {
  254. host->last_discrepancy = 0;
  255. host->last_device_flag = false;
  256. host->last_family_discrepancy = 0;
  257. search_result = false;
  258. } else {
  259. for(int i = 0; i < 8; i++) new_addr[i] = host->saved_rom[i];
  260. }
  261. return search_result;
  262. }
  263. void onewire_host_set_overdrive(OneWireHost* host, bool set) {
  264. host->timings = set ? &onewire_host_timings_overdrive : &onewire_host_timings_normal;
  265. }