one_wire_slave.c 8.8 KB

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