one_wire_slave.c 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319
  1. #include "one_wire_slave.h"
  2. #include "one_wire_slave_i.h"
  3. #include "one_wire_device.h"
  4. #include <furi.h>
  5. #include <furi_hal.h>
  6. #define OWS_RESET_MIN 270
  7. #define OWS_RESET_MAX 960
  8. #define OWS_PRESENCE_TIMEOUT 20
  9. #define OWS_PRESENCE_MIN 100
  10. #define OWS_PRESENCE_MAX 480
  11. #define OWS_MSG_HIGH_TIMEOUT 15000
  12. #define OWS_SLOT_MAX 135
  13. #define OWS_READ_MIN 20
  14. #define OWS_READ_MAX 60
  15. #define OWS_WRITE_ZERO 30
  16. typedef enum {
  17. NO_ERROR = 0,
  18. VERY_LONG_RESET,
  19. VERY_SHORT_RESET,
  20. PRESENCE_LOW_ON_LINE,
  21. AWAIT_TIMESLOT_TIMEOUT_HIGH,
  22. INCORRECT_ONEWIRE_CMD,
  23. FIRST_BIT_OF_BYTE_TIMEOUT,
  24. RESET_IN_PROGRESS
  25. } OneWireSlaveError;
  26. struct OneWireSlave {
  27. OneWireSlaveError error;
  28. OneWireDevice* device;
  29. OneWireSlaveResultCallback result_cb;
  30. void* result_cb_ctx;
  31. };
  32. /*********************** PRIVATE ***********************/
  33. uint32_t onewire_slave_wait_while_gpio_is(OneWireSlave* bus, uint32_t time, const bool pin_value) {
  34. UNUSED(bus);
  35. uint32_t start = DWT->CYCCNT;
  36. uint32_t time_ticks = time * furi_hal_cortex_instructions_per_microsecond();
  37. uint32_t time_captured;
  38. do {
  39. time_captured = DWT->CYCCNT;
  40. if(furi_hal_ibutton_pin_get_level() != pin_value) {
  41. uint32_t remaining_time = time_ticks - (time_captured - start);
  42. remaining_time /= furi_hal_cortex_instructions_per_microsecond();
  43. return remaining_time;
  44. }
  45. } while((time_captured - start) < time_ticks);
  46. return 0;
  47. }
  48. bool onewire_slave_show_presence(OneWireSlave* bus) {
  49. // wait while master delay presence check
  50. onewire_slave_wait_while_gpio_is(bus, OWS_PRESENCE_TIMEOUT, true);
  51. // show presence
  52. furi_hal_ibutton_pin_low();
  53. furi_delay_us(OWS_PRESENCE_MIN);
  54. furi_hal_ibutton_pin_high();
  55. // somebody also can show presence
  56. const uint32_t wait_low_time = OWS_PRESENCE_MAX - OWS_PRESENCE_MIN;
  57. // so we will wait
  58. if(onewire_slave_wait_while_gpio_is(bus, wait_low_time, false) == 0) {
  59. bus->error = PRESENCE_LOW_ON_LINE;
  60. return false;
  61. }
  62. return true;
  63. }
  64. bool onewire_slave_receive_bit(OneWireSlave* bus) {
  65. // wait while bus is low
  66. uint32_t time = OWS_SLOT_MAX;
  67. time = onewire_slave_wait_while_gpio_is(bus, time, false);
  68. if(time == 0) {
  69. bus->error = RESET_IN_PROGRESS;
  70. return false;
  71. }
  72. // wait while bus is high
  73. time = OWS_MSG_HIGH_TIMEOUT;
  74. time = onewire_slave_wait_while_gpio_is(bus, time, true);
  75. if(time == 0) {
  76. bus->error = AWAIT_TIMESLOT_TIMEOUT_HIGH;
  77. return false;
  78. }
  79. // wait a time of zero
  80. time = OWS_READ_MIN;
  81. time = onewire_slave_wait_while_gpio_is(bus, time, false);
  82. return (time > 0);
  83. }
  84. bool onewire_slave_send_bit(OneWireSlave* bus, bool value) {
  85. const bool write_zero = !value;
  86. // wait while bus is low
  87. uint32_t time = OWS_SLOT_MAX;
  88. time = onewire_slave_wait_while_gpio_is(bus, time, false);
  89. if(time == 0) {
  90. bus->error = RESET_IN_PROGRESS;
  91. return false;
  92. }
  93. // wait while bus is high
  94. time = OWS_MSG_HIGH_TIMEOUT;
  95. time = onewire_slave_wait_while_gpio_is(bus, time, true);
  96. if(time == 0) {
  97. bus->error = AWAIT_TIMESLOT_TIMEOUT_HIGH;
  98. return false;
  99. }
  100. // choose write time
  101. if(write_zero) {
  102. furi_hal_ibutton_pin_low();
  103. time = OWS_WRITE_ZERO;
  104. } else {
  105. time = OWS_READ_MAX;
  106. }
  107. // hold line for ZERO or ONE time
  108. furi_delay_us(time);
  109. furi_hal_ibutton_pin_high();
  110. return true;
  111. }
  112. void onewire_slave_cmd_search_rom(OneWireSlave* bus) {
  113. const uint8_t key_bytes = 8;
  114. uint8_t* key = onewire_device_get_id_p(bus->device);
  115. for(uint8_t i = 0; i < key_bytes; i++) {
  116. uint8_t key_byte = key[i];
  117. for(uint8_t j = 0; j < 8; j++) {
  118. bool bit = (key_byte >> j) & 0x01;
  119. if(!onewire_slave_send_bit(bus, bit)) return;
  120. if(!onewire_slave_send_bit(bus, !bit)) return;
  121. onewire_slave_receive_bit(bus);
  122. if(bus->error != NO_ERROR) return;
  123. }
  124. }
  125. }
  126. bool onewire_slave_receive_and_process_cmd(OneWireSlave* bus) {
  127. uint8_t cmd;
  128. onewire_slave_receive(bus, &cmd, 1);
  129. if(bus->error == RESET_IN_PROGRESS) return true;
  130. if(bus->error != NO_ERROR) return false;
  131. switch(cmd) {
  132. case 0xF0:
  133. // SEARCH ROM
  134. onewire_slave_cmd_search_rom(bus);
  135. return true;
  136. case 0x0F:
  137. case 0x33:
  138. // READ ROM
  139. onewire_device_send_id(bus->device);
  140. return true;
  141. default: // Unknown command
  142. bus->error = INCORRECT_ONEWIRE_CMD;
  143. }
  144. if(bus->error == RESET_IN_PROGRESS) return true;
  145. return (bus->error == NO_ERROR);
  146. }
  147. bool onewire_slave_bus_start(OneWireSlave* bus) {
  148. bool result = true;
  149. if(bus->device == NULL) {
  150. result = false;
  151. } else {
  152. FURI_CRITICAL_ENTER();
  153. furi_hal_ibutton_start_drive_in_isr();
  154. bus->error = NO_ERROR;
  155. if(onewire_slave_show_presence(bus)) {
  156. // TODO think about multiple command cycles
  157. onewire_slave_receive_and_process_cmd(bus);
  158. result = (bus->error == NO_ERROR || bus->error == INCORRECT_ONEWIRE_CMD);
  159. } else {
  160. result = false;
  161. }
  162. furi_hal_ibutton_start_interrupt_in_isr();
  163. FURI_CRITICAL_EXIT();
  164. }
  165. return result;
  166. }
  167. static void exti_cb(void* context) {
  168. OneWireSlave* bus = context;
  169. volatile bool input_state = furi_hal_ibutton_pin_get_level();
  170. static uint32_t pulse_start = 0;
  171. if(input_state) {
  172. uint32_t pulse_length =
  173. (DWT->CYCCNT - pulse_start) / furi_hal_cortex_instructions_per_microsecond();
  174. if(pulse_length >= OWS_RESET_MIN) {
  175. if(pulse_length <= OWS_RESET_MAX) {
  176. // reset cycle ok
  177. bool result = onewire_slave_bus_start(bus);
  178. if(result && bus->result_cb != NULL) {
  179. bus->result_cb(bus->result_cb_ctx);
  180. }
  181. } else {
  182. bus->error = VERY_LONG_RESET;
  183. }
  184. } else {
  185. bus->error = VERY_SHORT_RESET;
  186. }
  187. } else {
  188. //FALL event
  189. pulse_start = DWT->CYCCNT;
  190. }
  191. };
  192. /*********************** PUBLIC ***********************/
  193. OneWireSlave* onewire_slave_alloc() {
  194. OneWireSlave* bus = malloc(sizeof(OneWireSlave));
  195. bus->error = NO_ERROR;
  196. bus->device = NULL;
  197. bus->result_cb = NULL;
  198. bus->result_cb_ctx = NULL;
  199. return bus;
  200. }
  201. void onewire_slave_free(OneWireSlave* bus) {
  202. onewire_slave_stop(bus);
  203. free(bus);
  204. }
  205. void onewire_slave_start(OneWireSlave* bus) {
  206. furi_hal_ibutton_add_interrupt(exti_cb, bus);
  207. furi_hal_ibutton_start_interrupt();
  208. }
  209. void onewire_slave_stop(OneWireSlave* bus) {
  210. UNUSED(bus);
  211. furi_hal_ibutton_stop();
  212. furi_hal_ibutton_remove_interrupt();
  213. }
  214. void onewire_slave_attach(OneWireSlave* bus, OneWireDevice* device) {
  215. bus->device = device;
  216. onewire_device_attach(device, bus);
  217. }
  218. void onewire_slave_detach(OneWireSlave* bus) {
  219. if(bus->device != NULL) {
  220. onewire_device_detach(bus->device);
  221. }
  222. bus->device = NULL;
  223. }
  224. void onewire_slave_set_result_callback(
  225. OneWireSlave* bus,
  226. OneWireSlaveResultCallback result_cb,
  227. void* context) {
  228. bus->result_cb = result_cb;
  229. bus->result_cb_ctx = context;
  230. }
  231. bool onewire_slave_send(OneWireSlave* bus, const uint8_t* address, const uint8_t data_length) {
  232. uint8_t bytes_sent = 0;
  233. furi_hal_ibutton_pin_high();
  234. // bytes loop
  235. for(; bytes_sent < data_length; ++bytes_sent) {
  236. const uint8_t data_byte = address[bytes_sent];
  237. // bit loop
  238. for(uint8_t bit_mask = 0x01; bit_mask != 0; bit_mask <<= 1) {
  239. if(!onewire_slave_send_bit(bus, bit_mask & data_byte)) {
  240. // if we cannot send first bit
  241. if((bit_mask == 0x01) && (bus->error == AWAIT_TIMESLOT_TIMEOUT_HIGH))
  242. bus->error = FIRST_BIT_OF_BYTE_TIMEOUT;
  243. return false;
  244. }
  245. }
  246. }
  247. return true;
  248. }
  249. bool onewire_slave_receive(OneWireSlave* bus, uint8_t* data, const uint8_t data_length) {
  250. uint8_t bytes_received = 0;
  251. furi_hal_ibutton_pin_high();
  252. for(; bytes_received < data_length; ++bytes_received) {
  253. uint8_t value = 0;
  254. for(uint8_t bit_mask = 0x01; bit_mask != 0; bit_mask <<= 1) {
  255. if(onewire_slave_receive_bit(bus)) value |= bit_mask;
  256. }
  257. data[bytes_received] = value;
  258. }
  259. return (bytes_received != data_length);
  260. }